指南
Webhook
接收批次任務完成通知
對於執行時間超過一分鐘的批次任務,Webhook 比輪詢更便宜也更快。當任務到達終態時,Thunderbit 會向你的 URL 發起 POST。
提交時設定
{
"urls": ["https://example.com/page1"],
"webhook": {
"url": "https://your-server.com/api/webhook/distill",
"secret": "whsec_your_secret_key",
"headers": { "X-Custom-Auth": "your-token" }
}
}webhook.headers 欄位接受自訂請求標頭的 map,但此欄位為預留欄位,伺服器目前尚未送出。請僅依照下方文件列出的請求標頭進行驗簽。
請求標頭
每一次投遞都會包含以下 4 個請求標頭:
| Header | Value |
|---|---|
Content-Type | application/json |
X-Webhook-Event | batch.completed |
X-Webhook-Timestamp | Unix 時間戳(毫秒) |
X-Webhook-Signature | sha256=<base64-encoded HMAC-SHA256> |
載荷
{
"id": "batch_a1b2c3d4...",
"jobType": "batch_distill",
"status": "COMPLETED",
"total": 50,
"completed": 49,
"failed": 1,
"creditsUsed": 100,
"createdAt": "2026-04-26T10:00:00Z",
"completedAt": "2026-04-26T10:05:23Z"
}jobType取值為batch_distill或batch_extract。status取值為COMPLETED、FAILED或CANCELLED。
載荷刻意保持精簡——收到回呼後請透過 GET /batch/distill/{id}(或 /batch/extract/{id})取回完整結果。
簽章驗證
設定 secret 後,每一次投遞都會帶上 X-Webhook-Signature 請求標頭。
- 演算法:HMAC-SHA256
- 待簽字串:
<X-Webhook-Timestamp>.<raw-json-body>(兩者之間是字面上的.) - 輸出格式:
sha256=<base64-encoded-hash>(Base64,不是 hex)
請使用原始請求位元組進行驗證(不要重新序列化 JSON),再以常數時間比對。
import hmac, hashlib, base64
def verify(raw_body: bytes, timestamp: str, signature: str, secret: str) -> bool:
base = f"{timestamp}.{raw_body.decode('utf-8')}".encode('utf-8')
digest = hmac.new(secret.encode('utf-8'), base, hashlib.sha256).digest()
expected = "sha256=" + base64.b64encode(digest).decode('ascii')
return hmac.compare_digest(expected, signature)重放保護
若 |now - X-Webhook-Timestamp| > 60000(60 秒窗口),請拒絕該請求。時間戳為 毫秒 Unix 時間戳。在正式環境中絕不要信任未簽章的 webhook。
重試行為
- 單次投遞逾時:30 秒
- 最大重試次數:3
- 退避策略:指數退避,起始 1 秒,上限 10 秒
- 端到端總窗口:約 120 秒
所有重試都失敗後,任務在我們這側仍視為已完成——你的接收端必須具備冪等性(建議以 id 作為去重鍵)。