Webhooks gerçek zamanlı imza olaylarını alın
Certyneo panolarınızda bir HTTPS URL ayarlayın ve zarflarınızda bir olay olduğunda HMAC-SHA256 imzalı bir POST alın: imza, reddedilme, sona erme. 8 olay desteklenir, 6 deneme ile katlanarak tekrar denenebilir, 8 satırlık şifre doğrulama.
< 5s
Olay sonrası ortalama teslim süresi
5x
Başarısızlık denemeleri ( ~ 9 saat sonra)
HMAC-SHA256
Her talebin imzası algoritması
Olay Kataloğu
Aşağıdaki 8 olay, bir Certyneo zarfının tüm yaşam döngüsünü kapsar. Seçenekler → Webhooks'ta ilgilendiğiniz olayları etkinleştirin, diğerlerini görmezden gelin abonelik olay başına granülerdir.
| Olay | Çıkış |
|---|---|
envelope.created | Bir zarf oluşturulur (UI, API veya şablon tarafından) CRM tarafında bir kayıt oluşturulduğunda senkronize etmek için kullanılır. |
envelope.sent | Zarf, imzalayanlara gönderilir (ilk e-posta gönderilmektedir). |
envelope.completed | Tüm imzacılar imzaladı. eIDAS mühürlü PDF ve iz denetimi payload'da `proof_pdf_url` üzerinden mevcuttur. |
envelope.declined | İmzacı, mührü reddetti.Rezim sebebi (imzacı tarafından verildiğinde) `data.decline_reason`'da yer almaktadır. |
envelope.voided | Bütçe, göndericiden imzalandırılmadan önce iptal edildi. |
envelope.expired | Envantopun son kullanma tarihi tam olarak imzalanmadan geçti. Kayıp imzalayanların listesi `data.missing_signers`'da. |
recipient.signed | Bireysel bir imzacı imzaladı (ama hepsi değil). Sıralı iş akışları için yararlı: bir sonraki imzacıya geçiş yaptırmak. |
recipient.viewed | Bir imzacı imzalama bağlantısını henüz imzalamadan açtı. |
Uygulanabilir yükü biçimi
Tüm olaylar aynı üst seviye JSON şemasını paylaşır: `event`, `envelope_id`, `occurred_at`, `data`. `data` içeriği olay başına göre değişir (API referansındaki olay başına belgelenen alanlar). İşte tam bir örnek `envelope.completed`.
{
"event": "envelope.completed",
"envelope_id": "env_01HG3K8X9Y2N4P5Q6R7S8T9V0W",
"occurred_at": "2026-05-27T08:42:13.521Z",
"data": {
"title": "Contrat de prestation Acme Corp",
"status": "completed",
"created_at": "2026-05-24T14:12:00.000Z",
"completed_at": "2026-05-27T08:42:13.000Z",
"signers": [
{
"email": "client@acme.example",
"name": "Alex Client",
"signed_at": "2026-05-27T08:42:13.000Z",
"method": "eidas_aes",
"ip": "203.0.113.42"
}
],
"proof_pdf_url": "https://certyneo.com/api/envelopes/env_01HG.../proof.pdf"
}
}Payload UTF-8 kodlanmıştır, BOM bulunmamaktadır. HMAC imzası gönderildiği gibi gövdeye hesaplanır boşlukları değiştirmeyin, JSON yeniden ayrıştırılması genellikle anahtarların sırasını değiştirir ve doğrulamaları bozar.
HMAC imzasını kontrol et.
Her istek webhook gizinizle imzalanacak (dashboard'da oluşturulduğunda bir kez görünür, sonra dinlenirken şifrelenmiş olacak). İmza `Certyneo-Signature` başlığında `t= biçiminde iletilecek<timestamp>V1=<hex_hmac>Payload'u işlemeden önce her zaman imza kontrol edin. Bu adım olmadan, herkes bir olayı sahteleyip son noktanızı arayabilir.
Node.js / TypeScript
import crypto from "node:crypto";
export function verifyCertyneoSignature(
rawBody: string,
signatureHeader: string,
secret: string,
): boolean {
// Header format: t=<timestamp>,v1=<hex_hmac>
const parts = Object.fromEntries(
signatureHeader.split(",").map((p) => p.split("=")),
);
const ts = parts.t;
const sig = parts.v1;
if (!ts || !sig) return false;
// Reject events older than 5 minutes (replay protection).
const age = Math.abs(Date.now() / 1000 - Number(ts));
if (age > 300) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(`${ts}.${rawBody}`)
.digest("hex");
// timingSafeEqual to mitigate timing attacks.
return crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(sig, "hex"),
);
}Python
import hashlib
import hmac
import time
def verify_certyneo_signature(
raw_body: bytes, signature_header: str, secret: str
) -> bool:
"""Verify a Certyneo webhook signature.
Header format: `t=<timestamp>,v1=<hex_hmac>`
Rejects events older than 5 minutes (replay protection).
"""
parts = dict(p.split("=") for p in signature_header.split(","))
ts = parts.get("t")
sig = parts.get("v1")
if not ts or not sig:
return False
if abs(time.time() - int(ts)) > 300:
return False
expected = hmac.new(
secret.encode("utf-8"),
f"{ts}.{raw_body.decode('utf-8')}".encode("utf-8"),
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, sig)Sıkça yapılan hatalar
Beklenen imzayı alınan imzaya karşılaştırmak için `===` veya `==` kullanmayın. Zamanlama güvenli bir işlev kullanın (`crypto.timingSafeEqual` Node'de, `hmac.compare_digest` Python'da). Aksi takdirde, iki imza arasındaki karşılaştırma zaman farkı sırrı yavaş yavaş hasta bir saldırganın (zamanlama saldırısı) farkına neden olur.
Tekrar deneme politikası
Eğer uç noktanız HTTP 2xx (timeout, 5xx, connection refused) dışında bir şey yanıtlarsa, katlanarak yedekleme yapıyoruz. Toplamda ~9 saat içinde 6 girişim. 6'sının ardından olay webhook panolarınızda `failed` olarak işaretlenir ve uyarı e-postası gönderilir.
| Deneme | Toplam süre | Geçmiş zaman |
|---|---|---|
| #1 | 0 | 0 |
| #2 | + 1 min | 1 min |
| #3 | + 5 min | 6 min |
| #4 | + 30 min | 36 min |
| #5 | + 2 h | 2h 36 |
| #6 | + 6 h | 8h 36 |
Eğer başarısız bir olayı elle iletmek istiyorsanız, webhook panoları başarısız olan her teslimat için bir Tekrar teslimat düğmesi sunar.
Gerçek zarf göndermeden test etmek
`/v1/webhooks/test` son noktası bir URL ve bir olay türünü kabul eder ve gerçek gibi tam olarak imzalanan hayali bir payload gönderir.
# Trigger a test webhook to your endpoint
curl -X POST https://api.certyneo.com/v1/webhooks/test \
-H "Authorization: Bearer $CERTYNEO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"event": "envelope.completed", "url": "https://your.app/webhooks/certyneo"}'6 Uyumlu Uygulamalar
- HMAC imzasını BİR BİR BİR BÜR BÜR BÜR BÜR BÜR BÜR BÜR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR
- Her `envelope_id` × `event`'i, bazda zaten görülen ID'leri saklayarak sadece bir kez işleyin (dönüşümler aynı olayı tekrar sunabilir).
- HTTP 200'e en fazla 5 saniye içinde cevap verin, sonra asynchronous olarak işleyin (kuyruk). Aksi takdirde zaman aşımına uğrayacaksınız ve tekrar deneme olarak sayılacaksınız.
- Kötü vücut + tam imzanın depoglanması HMAC doğrulama genellikle görünmez bir BOM veya beyaz alan üzerinde başarısız olur.
- Default. olaylar için bir dead-letter kuyruğu takın.
- `t=` ile sonrası zaman aralığı arasında 5 dakika geçişe izin verin, tekrarları engellemek için reddedin.
Daha Fazla
Sistemlerinizi bağlamaya hazır mısınız?
Ücretsiz bir hesap oluştur 2 dakikada webhook kurulumları Starter planından (ücretsiz, ayda 5 zarf) mevcuttur.