跳至內容

Webhook

針對您訂閱的每個信封事件,Bona Fide 都會向您的端點傳送 HTTPS POST 要求。傳遞內容遵循 Standard Webhooks 規格,因此可以使用該規格的任何程式庫進行驗證。

在 設定 › Webhook 中註冊,或使用具有 org:manage 權限範圍的 API 金鑰註冊:

Terminal window
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 列出的每個角色的欄位值。

每次傳遞都帶有:

標頭 值
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);
});

在 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 會將事件重新傳送到端點,例如在服務中斷之後。

POST /v1/webhook-endpoints/{id}/secret/rotate 會立即傳回新的密鑰。在接下來的 24 小時內,每次傳遞都會同時以新密鑰和舊密鑰簽章(webhook-signature 中會有兩個項目),讓您可以在不遺漏事件的情況下部署新密鑰。