核心指南
Webhook 管理 API
透過 Dashboard、API 或 MCP 設定任務通知、驗證簽章並排解傳送問題。
當非同步任務完成、失敗或逾時時,Webhook 會通知您的應用程式。您可以透過 Dashboard → API → Webhooks、Management API 或 TokenLab MCP 的 full 設定檔來進行設定。它們共享相同的工作區端點與傳送記錄。
應使用哪種憑證
| 憑證 | 用途 | 使用位置 |
|---|---|---|
Management Token mt-… | 建立、列出、更新、刪除、測試及輪替 Webhook | /v1/management/webhooks* 的 Authorization: Bearer mt-… |
API key sk-… | 提交模型請求並查詢任務狀態 | 模型 API 與 /v1/tasks/{id} |
Signing secret whsec_… | 驗證接收到的通知是否真實 | 您的接收端;切勿將其作為 API Bearer token 使用 |
請在 Dashboard → API → Management Tokens 建立 Management Token。Token 是以工作區為範圍的:請選擇與提交任務的 API key 相同的工作區。Token 無法讀取或修改其他工作區的端點。API key 與 signing secret 無法用於 Management API。Dashboard 設定會使用您已登入的工作區管理員工作階段。
請將 mt-… 與 whsec_… 儲存在您的後端。請勿將它們嵌入瀏覽器程式碼、提示詞 (prompts)、儲存庫檔案或 URL 中。Management Token 也會授權其他工作區管理操作;它們並非僅限於 Webhook 的憑證。
設定端點
export TOKENLAB_MANAGEMENT_TOKEN="mt-your-management-token"
curl https://api.tokenlab.sh/v1/management/webhooks \
-H "Authorization: Bearer $TOKENLAB_MANAGEMENT_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"url":"https://your-app.example/webhooks/tokenlab","events":["task.completed","task.failed","task.timeout"],"description":"Production task results"}'201 回應包含 id 以及一個以 whsec_ 開頭的一次性 secret。請在離開此步驟前儲存該 secret。列出/取得/更新的回應絕不會顯示它。每個工作區最多可設定 10 個端點。URL 必須使用公開的 HTTPS,且不得包含憑證、查詢字串或片段。系統不會跟隨重新導向 (redirects)。
| 操作 | 端點 |
|---|---|
| 列出 / 建立 | GET / POST /v1/management/webhooks |
| 取得 / 更新 / 刪除 | GET / PATCH / DELETE /v1/management/webhooks/{webhookId} |
| 輪替簽章 secret | POST /v1/management/webhooks/{webhookId}/rotate-secret |
| 發送測試 | POST /v1/management/webhooks/{webhookId}/test |
| 傳送記錄 | GET /v1/management/webhooks/{webhookId}/deliveries?page=1&limit=50 |
使用 PATCH {"is_active":false} 暫停;使用 PATCH {"is_active":true} 恢復。恢復會重置連續失敗次數。輪替操作會回傳一次新的 secret;請立即在您的接收端進行設定。正在傳輸中的請求可能仍帶有先前的簽章,因此在輪替期間請短暫接受兩組 secret。輪替操作無法復原。
事件與酬載 (Payloads)
訂閱涵蓋未來的終止非同步任務事件;同步結果與歷史任務不會重新發送。接收所選事件類型的所有工作區任務,並將 data.taskId 與您建立任務時回傳的 ID 進行比對。回呼欄位使用 camelCase;管理回應欄位使用 snake_case。
{
"id": "event-unique-id",
"type": "task.completed",
"created": 1790000000,
"data": {
"taskType": "video",
"taskId": "ldtask_0123456789abcdef0123456789abcdef",
"model": "your-selected-model",
"durationMs": 42000,
"resultUrls": ["https://api.tokenlab.sh/v1/media-results/7c9e6679-7425-40de-944b-e07fc1f90ae7.mp4?token=…"],
"settledCost": 0.12
}
}| 事件 | 資料 |
|---|---|
task.completed | taskType, taskId, 選填 model, durationMs, resultUrls, settledCost |
task.failed | taskType, taskId, error, errorCode, retryable, refundOutcome |
task.timeout | taskType, taskId, expectedTimeoutMs, actualWaitMs, refundIssued, resolutionSource, refundOutcome |
webhook.test | 測試訊息與已設定的訂閱;僅由測試操作發送 |
resultUrls 中的每個項目都是 TokenLab 媒體結果 URL,有效期 30 天。請參閱資料保留。
對於 task.timeout,expectedTimeoutMs 是設定的逾時閾值,actualWaitMs 是經過的等待時間,兩者皆以毫秒為單位。refundIssued: true 表示退款成功或已發出;false 不排除稍後退款的可能性。refundOutcome 描述退款處理結果。逾時事件不包含 durationMs。
欄位取決於任務,且可能不存在。請使用原始工作區的 sk-… key 呼叫 GET /v1/tasks/{id} 以取得權威結果與計費狀態。事件的 retryable 描述生成失敗的原因;這並非指示您無限期輪詢終止任務或自動提交新的計費任務。在 task.failed 中,error、errorCode 與 retryable 是任務公開的 error_details.message、code 與 retryable,與狀態讀取回傳的值相同。
處理前進行驗證
每個 POST 請求皆包含 X-Webhook-ID、X-Webhook-Timestamp (Unix 秒數) 與 X-Webhook-Signature (sha256=<hex>)。請使用完整的 whsec_… secret,對精確的時間戳記字串、句點以及原始請求主體位元組 (raw request body bytes) 計算 HMAC-SHA256。請勿在驗證前解析並重新序列化 JSON。
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyWebhook(rawBody, headers, secrets) {
const timestamp = headers['x-webhook-timestamp'];
const signature = headers['x-webhook-signature'];
if (typeof timestamp !== 'string' || !/^\d+$/.test(timestamp)) return false;
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
if (typeof signature !== 'string' || !/^sha256=[a-f0-9]{64}$/.test(signature)) return false;
const received = Buffer.from(signature.slice(7), 'hex');
return secrets.some(secret => {
const expected = createHmac('sha256', secret).update(timestamp + '.').update(rawBody).digest();
return timingSafeEqual(expected, received);
});
}驗證後,請檢查主體 id 是否與 X-Webhook-ID 相符,將事件 ID 與您的工作項目原子性地持久化,並儘速回傳 2xx。請從您自己的佇列處理繁重的工作。請在接收端點內根據事件 ID 進行去重:傳送可能會重複,且不保證順序。五分鐘的時間戳記容差限制了重放 (replay) 的時效;ID 去重可防止在該視窗內重複處理。
重試與恢復
每個傳送週期最多進行三次嘗試,分別等待 1 秒與 4 秒。每次 HTTP 嘗試皆有 10 秒的逾時時間以及新的時間戳記/簽章。網路失敗、429 與 5xx 為可重試錯誤。其他 4xx、重新導向與無效的網路目標會停止該週期而不進行重試。暫時性失敗可能會觸發後續具有相同傳送 ID 的事件重試。十次連續失敗的週期會自動暫停該端點。
請使用測試操作與傳送記錄來查看 outcome、http_status、attempts 與 delivered_at。成功的測試 API 回應 (200) 僅表示嘗試已被記錄:請檢查 outcome == "delivered"。請修復接收端、恢復端點,然後再次發送測試。記錄包含傳送中繼資料,而非酬載;無法手動重放舊事件。請保留任務 ID,若您的接收端曾暫停或無法使用,請與任務狀態進行核對。
MCP 設定
Webhook 管理工具可在 full 設定檔中使用。管理憑證與推論 key 是分開的;目錄與 Webhook 管理可以在沒有推論 key 的情況下運作。
{
"mcpServers": {
"tokenlab": {
"command": "npx",
"args": ["-y", "@tokenlabai/mcp-server@latest"],
"env": {
"TOKENLAB_MCP_TOOL_PROFILE": "full",
"TOKENLAB_MANAGEMENT_TOKEN": "mt-your-management-token",
"TOKENLAB_API_KEY": "sk-your-inference-key"
}
}
}
}工具:list_webhooks、create_webhook、get_webhook、update_webhook、delete_webhook、rotate_webhook_secret、test_webhook、list_webhook_deliveries。切勿將憑證貼入工具參數中。僅授權受信任的 MCP 客戶端進行管理存取。
輪詢備援 (Polling fallback)
Webhook 不會移除狀態查詢存取權,也不會強制執行新的輪詢限制。若您進行輪詢,請使用建立回應中的 poll_url,在狀態為 pending 時進行退避 (back off),並在終止狀態時停止。在遇到 401、403、404 或 error.retryable == false 時停止;對於暫時性的 503 async_task_owner_unavailable 則應進行退避重試。遺失或過期的任務會回傳 404 async_task_not_found。重複查詢遺失的任務無法重新建立它。
Seedance 相容 API 的 callback_url 是每個請求獨立的回呼合約。它可以在建立該任務時設定;它不使用這些工作區事件酬載或 HMAC 標頭。