Webhook'lar
Bona Fide, abone olduğunuz her zarf olayı için uç noktanıza bir HTTPS POST isteği gönderir. Teslimatlar
Standard Webhooks belirtimine uyar; bu nedenle bu belirtimin kitaplıklarından
herhangi biri onları doğrulayabilir.
Uç nokta kaydetme
Bölüm başlığı “Uç nokta kaydetme”Ayarlar › Webhook’lar bölümünde veya org:manage kapsamına sahip bir
API anahtarıyla:
curl https://api.bonafidesign.com/v1/webhook-endpoints \ -H "Authorization: Bearer $BONA_FIDE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://app.example.com/hooks/bona-fide", "description": "Production", "events": ["envelope.completed", "envelope.sealed", "envelope.declined"] }'Yanıt secret (whsec_…) değerini yalnızca bu seferlik içerir. Boş bir events listesi tüm olaylara abone
olur. URL herkese açık bir https:// adresi olmalıdır. Bir uç nokta tek bir moda aittir: test anahtarıyla
oluşturulan uç noktalar yalnızca test modu zarflarının olaylarını, canlı uç noktalar yalnızca canlı olayları alır.
PATCH /v1/webhook-endpoints/{id} URL’yi, olayları veya açıklamayı değiştirir ve uç noktayı duraklatır ya da
sürdürür (enabled). POST /v1/webhook-endpoints/{id}/test bir webhook.test ping’i gönderir.
Olaylar
Bölüm başlığı “Olaylar”| Tür | Ne zaman |
|---|---|
envelope.created |
Zarf oluşturuldu |
envelope.ready |
Belge oluşturuldu ve zarf alıcıları için hazır |
recipient.sent |
Sıra bir alıcıya geldi (ve e-postayla teslimatta bağlantısı gönderildi) |
recipient.viewed |
Bir alıcı imzalama sayfasını ilk kez açtı |
recipient.signed |
Bir alıcı gönderim yaptı (veya otomatik olarak karşı imza atıldı) |
recipient.declined |
Bir alıcı reddetti |
envelope.completed |
Tüm alıcılar işlemini bitirdi. data.values değişkenleri ve girilen her değeri içerir |
envelope.sealed |
Mühürlü PDF indirilmeye hazır |
envelope.declined |
Bir alıcı reddettiği için zarf sona erdi |
envelope.voided |
Zarfı siz iptal ettiniz |
envelope.expired |
Tamamlanmadan önce expiresAt geçti |
signing_link.used |
Bir ziyaretçi kalıcı bir imzalama bağlantısından bir zarf başlattı |
acceptance.created şemada ayrılmıştır ve henüz yayılmamaktadır.
{ "id": "evt_9sKq2Lm4Tz", "type": "envelope.completed", "createdAt": "2026-10-13T14:09:52.004Z", "testMode": false, "data": { "envelope": { "id": "env_8Gm2kQ4rT1", "status": "completed", "seal": "pending", "recipients": [{ "id": "rcp_5Jw0pLs9Xe", "role": "client", "status": "completed", "…": "…" }], "externalId": "user_8841", "metadata": {}, "…": "…" }, "values": { "variables": { "client": { "name": "Acme Robotics, Inc." }, "effective_date": "2026-10-13" }, "recipients": { "client": { "client_title": "CEO", "start_date": "2026-11-01" } } } }}data.envelope, olay anındaki zarfın tamamıdır. data.values yalnızca
envelope.completed üzerinde bulunur: gönderdiğiniz değişkenler ve alan kimliğine göre her rolün alan değerleri.
Başlıklar ve imza
Bölüm başlığı “Başlıklar ve imza”Her teslimat şunları taşır:
| Başlık | Değer |
|---|---|
webhook-id |
Olay kimliği (evt_…); her yeniden denemede aynıdır. Tekilleştirme için kullanın |
webhook-timestamp |
Bu denemenin imzalandığı an, Unix saniyesi cinsinden |
webhook-signature |
v1,<base64 HMAC-SHA256>; birden fazla sır imzaladığında boşlukla ayrılır |
user-agent |
BonaFide-Webhooks/1 |
İmza, {webhook-id}.{webhook-timestamp}.{raw body} üzerinde HMAC-SHA256’dır ve anahtarı, sırrın whsec_
sonrasındaki kısmının base64 kodu çözülmüş hâlidir. Ham gövdeyi (JSON ayrıştırmasından önce) doğrulayın, sabit
zamanlı karşılaştırma yapın ve saatinizden beş dakikadan fazla sapan zaman damgalarını reddedin.
import express from 'express';import { Webhook } from 'standardwebhooks'; // npm i standardwebhooks
const wh = new Webhook(process.env.BONA_FIDE_WEBHOOK_SECRET!); // whsec_…const app = express();
app.post('/hooks/bona-fide', express.raw({ type: 'application/json' }), (req, res) => { let event; try { event = wh.verify(req.body, req.headers as Record<string, string>); // throws if forged or too old } catch { return res.sendStatus(400); } queue.add(event); // do the work asynchronously and answer quickly res.sendStatus(204);});# pip install standardwebhooks flaskimport osfrom flask import Flask, requestfrom standardwebhooks.webhooks import Webhook
wh = Webhook(os.environ["BONA_FIDE_WEBHOOK_SECRET"]) # whsec_…app = Flask(__name__)
@app.post("/hooks/bona-fide")def bona_fide(): try: event = wh.verify(request.get_data(), dict(request.headers)) except Exception: return "", 400 enqueue(event) return "", 204import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(secret: string, headers: Record<string, string>, rawBody: string) { const id = headers['webhook-id']; const ts = Number(headers['webhook-timestamp']); if (!id || !ts || Math.abs(Date.now() / 1000 - ts) > 300) throw new Error('stale or missing headers'); const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64'); const expected = createHmac('sha256', key).update(`${id}.${ts}.${rawBody}`).digest(); const ok = (headers['webhook-signature'] ?? '').split(' ').some((part) => { const [version, sig] = part.split(','); const given = Buffer.from(sig ?? '', 'base64'); return version === 'v1' && given.length === expected.length && timingSafeEqual(given, expected); }); if (!ok) throw new Error('bad signature'); return JSON.parse(rawBody);}Yeniden denemeler
Bölüm başlığı “Yeniden denemeler”Bir teslimat, 10 saniye içinde herhangi bir 2xx yanıtı alındığında başarılı olur. Yönlendirmeler izlenmez. Diğer
her durum, geri çekilmeyle (backoff) 5 saniye, 5 dakika, 30 dakika, 2 saat, 5 saat, 10 saat, 14 saat, 20 saat ve 24
saat sonra, olaydan sonra en fazla üç gün boyunca yeniden denenir. Ardından teslimat başarısız olarak işaretlenir.
- Hızlı yanıt verin ve işlemi eşzamansız yapın;
webhook-idüzerinden tekilleştirin. - Teslimatlar sırasız gelebilir: bir sıra varsaymak yerine
data.envelope.statusdeğerini kontrol edin. GET /v1/webhook-endpoints/{id}/deliveriesson denemeleri durum kodları, hatalar ve sürelerle listeler; her uç nokta 24 saatlik başarı oranını (health) gösterir.POST /v1/events/{id}/redeliver, örneğin bir kesintiden sonra, bir olayı bir uç noktaya yeniden gönderir.
Sırrı döndürme
Bölüm başlığı “Sırrı döndürme”POST /v1/webhook-endpoints/{id}/secret/rotate hemen yeni bir sır döndürür. Sonraki 24 saat boyunca her teslimat
yeni ve eski sırrın ikisiyle birden imzalanır (webhook-signature içinde iki girdi); böylece olay kaybetmeden
yeni sırrı dağıtabilirsiniz.