指南

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 個請求標頭:

HeaderValue
Content-Typeapplication/json
X-Webhook-Eventbatch.completed
X-Webhook-TimestampUnix 時間戳(毫秒
X-Webhook-Signaturesha256=<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_distillbatch_extract
  • status 取值為 COMPLETEDFAILEDCANCELLED

載荷刻意保持精簡——收到回呼後請透過 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 作為去重鍵)。