TokenLab

核心指南

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}
輪替簽章 secretPOST /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.completedtaskType, taskId, 選填 model, durationMs, resultUrls, settledCost
task.failedtaskType, taskId, error, errorCode, retryable, refundOutcome
task.timeouttaskType, 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 標頭。

本頁內容