वेबहुक
आप जिस भी लिफ़ाफ़ा इवेंट को सब्सक्राइब करते हैं, उसके लिए Bona Fide आपके एंडपॉइंट पर एक HTTPS POST भेजता है। डिलीवरी
Standard Webhooks स्पेसिफ़िकेशन का पालन करती हैं, इसलिए इसकी कोई भी लाइब्रेरी उन्हें सत्यापित कर सकती है।
एंडपॉइंट रजिस्टर करना
Section titled “एंडपॉइंट रजिस्टर करना”सेटिंग्स › वेबहुक में, या ऐसी API कुंजी से जिसके पास org:manage
स्कोप हो:
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"] }'रिस्पॉन्स में secret (whsec_…) होता है, सिर्फ़ इसी एक बार। ख़ाली events सूची हर इवेंट को सब्सक्राइब करती है।
URL सार्वजनिक https:// होना चाहिए। एंडपॉइंट एक ही मोड का होता है: टेस्ट कुंजी से बने एंडपॉइंट को सिर्फ़
टेस्ट मोड वाले लिफ़ाफ़ों के इवेंट मिलते हैं, और लाइव एंडपॉइंट को सिर्फ़ लाइव इवेंट।
PATCH /v1/webhook-endpoints/{id} URL, इवेंट या विवरण बदलता है और एंडपॉइंट को रोकता या फिर से शुरू करता है
(enabled)। POST /v1/webhook-endpoints/{id}/test एक webhook.test पिंग भेजता है।
| प्रकार | कब |
|---|---|
envelope.created |
लिफ़ाफ़ा बनाया गया |
envelope.ready |
दस्तावेज़ रेंडर हो गया और लिफ़ाफ़ा अपने प्राप्तकर्ताओं के लिए तैयार है |
recipient.sent |
किसी प्राप्तकर्ता की बारी आई (और ईमेल डिलीवरी में, उसका लिंक भेजा गया) |
recipient.viewed |
किसी प्राप्तकर्ता ने पहली बार हस्ताक्षर पेज खोला |
recipient.signed |
किसी प्राप्तकर्ता ने सबमिट किया (या अपने आप काउंटरसाइन हुआ) |
recipient.declined |
किसी प्राप्तकर्ता ने मना किया |
envelope.completed |
हर प्राप्तकर्ता ने अपना काम पूरा कर लिया। data.values में वेरिएबल और टाइप किया गया हर मान होता है |
envelope.sealed |
सील किया गया PDF डाउनलोड के लिए तैयार है |
envelope.declined |
लिफ़ाफ़ा समाप्त हुआ, क्योंकि किसी प्राप्तकर्ता ने मना कर दिया |
envelope.voided |
आपने लिफ़ाफ़ा रद्द किया |
envelope.expired |
पूरा होने से पहले expiresAt बीत गया |
signing_link.used |
किसी विज़िटर ने हमेशा चालू हस्ताक्षर लिंक से लिफ़ाफ़ा शुरू किया |
acceptance.created स्कीमा में आरक्षित है और अभी जारी नहीं होता।
{ "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 इवेंट के समय का पूरा लिफ़ाफ़ा है। data.values सिर्फ़
envelope.completed पर होता है: आपके भेजे गए वेरिएबल, और फ़ील्ड id के अनुसार हर भूमिका के फ़ील्ड मान।
हेडर और हस्ताक्षर
Section titled “हेडर और हस्ताक्षर”हर डिलीवरी में ये होते हैं:
| हेडर | मान |
|---|---|
webhook-id |
इवेंट id (evt_…); हर रीट्राई पर वही। डुप्लिकेट हटाने के लिए इसका इस्तेमाल करें |
webhook-timestamp |
Unix सेकंड, जब इस प्रयास पर हस्ताक्षर हुआ |
webhook-signature |
v1,<base64 HMAC-SHA256>, एक से ज़्यादा सीक्रेट से हस्ताक्षर होने पर स्पेस से अलग किए गए |
user-agent |
BonaFide-Webhooks/1 |
हस्ताक्षर {webhook-id}.{webhook-timestamp}.{raw body} पर HMAC-SHA256 है, जिसकी कुंजी सीक्रेट में whsec_ के बाद वाले हिस्से को
base64 से डिकोड करके मिलती है। रॉ बॉडी को सत्यापित करें (JSON पार्स करने से पहले), तुलना कॉन्स्टेंट टाइम में करें, और
आपकी घड़ी से पाँच मिनट से ज़्यादा दूर के टाइमस्टैम्प अस्वीकार करें।
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);}रीट्राई
Section titled “रीट्राई”कोई डिलीवरी तब सफल होती है जब 10 सेकंड के भीतर कोई भी 2xx मिल जाए। रीडायरेक्ट फ़ॉलो नहीं किए जाते। बाकी हर स्थिति में बैकऑफ़ के साथ
रीट्राई होता है: 5 सेकंड, 5 मिनट, 30 मिनट, 2 घंटे, 5 घंटे, 10 घंटे, 14 घंटे, 20 घंटे और 24 घंटे बाद,
इवेंट के बाद अधिकतम तीन दिन तक। उसके बाद डिलीवरी को विफल चिह्नित कर दिया जाता है।
- जल्दी जवाब दें और प्रोसेसिंग एसिंक्रोनस रूप से करें;
webhook-idके आधार पर डुप्लिकेट हटाएँ। - डिलीवरी क्रम से बाहर आ सकती हैं: कोई क्रम मानकर चलने के बजाय
data.envelope.statusजाँचें। GET /v1/webhook-endpoints/{id}/deliveriesहाल के प्रयासों को स्टेटस कोड, एरर और समय के साथ सूचीबद्ध करता है, और हर एंडपॉइंट अपनी 24 घंटे की सफलता दर (health) दिखाता है।POST /v1/events/{id}/redeliverकिसी इवेंट को एंडपॉइंट पर फिर से भेजता है, उदाहरण के लिए किसी आउटेज के बाद।
सीक्रेट रोटेट करना
Section titled “सीक्रेट रोटेट करना”POST /v1/webhook-endpoints/{id}/secret/rotate तुरंत नया सीक्रेट लौटाता है। अगले 24 घंटे तक हर
डिलीवरी पर नए और पुराने, दोनों सीक्रेट से हस्ताक्षर होते हैं (webhook-signature में दो एंट्री), ताकि आप
कोई इवेंट खोए बिना नया सीक्रेट डिप्लॉय कर सकें।