Skip to content
SuperToken 文档

Webhook 完成通知

Seedance 任务进入成功或失败终态后,SuperToken 可以向账号配置的地址发送 HTTP POST 通知。Webhook 是账号级配置,不是单次任务参数;创建 /v1/video/tasks 请求时不要传 webhook_url

配置步骤

  1. 进入控制台的“资源管理中心”,打开“Webhook”页签。
  2. 填写接收通知的公开 HTTP/HTTPS 地址并启用配置,生产环境建议使用 HTTPS。
  3. 保存生成的 wk-... Webhook Key,并配置到接收服务的安全环境变量中。
  4. 点击“发送测试”,确认接收端能验证 Key 并返回 HTTP 2xx。

Webhook Key 只用于验证 SuperToken 发出的回调,不具有模型或资源 API 权限。重新生成 Key 后旧 Key 会立即失效,需要同步更新接收服务。

事件与请求头

事件触发条件结果位置
video.task.succeeded视频任务成功data.object.result.videos[]
video.task.failed视频任务失败data.object.error
webhook.test在控制台点击“发送测试”用于验证地址和 Webhook Key

回调请求头:

http
POST /webhooks/supertoken HTTP/1.1
Authorization: Bearer wk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

接收端必须比较完整的 Authorization 值。当前验证方式是 Bearer Key,不是 HMAC 签名。

成功事件

json
{
  "id": "evt_video_example123",
  "object": "event",
  "api_version": "2026-07-17",
  "type": "video.task.succeeded",
  "created_at": 1785373268,
  "data": {
    "object": {
      "id": "task_example123",
      "object": "video.task",
      "model": "adobe-seedance-2.0-480p",
      "operation": "generation",
      "status": "succeeded",
      "progress": 100,
      "result": {
        "videos": [
          {
            "asset_id": "asset_example123",
            "index": 0,
            "url": "https://media.example.com/results/video.mp4?token=...",
            "mime_type": "video/mp4",
            "duration_ms": 4000,
            "temporary": true,
            "url_auth": "none"
          }
        ]
      },
      "error": null,
      "client_reference_id": "order-20260730-001",
      "metadata": {
        "order_id": "order-20260730-001"
      },
      "created_at": 1785373200,
      "started_at": 1785373202,
      "completed_at": 1785373268,
      "updated_at": 1785373268
    }
  }
}

data.objectGET /v1/video/tasks/{task_id} 返回的任务对象一致。url_auth: "none" 表示应完整保留 URL 查询参数并直接访问;只有值为 resource_api_key 时才使用 ak_... 请求结果 URL。temporary: true 的地址可能过期,平台不会自动刷新。

失败事件

json
{
  "id": "evt_video_example456",
  "object": "event",
  "api_version": "2026-07-17",
  "type": "video.task.failed",
  "created_at": 1785373268,
  "data": {
    "object": {
      "id": "task_example456",
      "object": "video.task",
      "model": "adobe-seedance-2.0-720p",
      "operation": "generation",
      "status": "failed",
      "progress": 100,
      "result": null,
      "error": {
        "code": "reference_media_duration_exceeded",
        "message": "reference video and audio must not exceed 15 seconds",
        "retryable": false
      },
      "client_reference_id": "order-20260730-002",
      "metadata": {},
      "created_at": 1785373200,
      "started_at": 1785373202,
      "completed_at": 1785373268,
      "updated_at": 1785373268
    }
  }
}

参考视频或参考音频无法解析时,失败码为 invalid_reference_media_duration;单项或合计时长 超过所选模型上限时为 reference_media_duration_exceeded。Seedance 2.0 / Fast 的参考视频和 参考音频总时长上限为 15 秒,Seedance 2.5 分别为 30.2 秒。其他上游失败通常使用 video_task_failed。异步失败会进入现有退款流程;实际计价以控制台当前模型配置为准。

Python 接收示例

python
import os
from secrets import compare_digest

from flask import Flask, abort, request

app = Flask(__name__)
webhook_key = os.environ["SUPERTOKEN_WEBHOOK_KEY"]


@app.post("/webhooks/supertoken")
def receive_video_event():
    expected = f"Bearer {webhook_key}"
    authorization = request.headers.get("Authorization", "")
    if not compare_digest(authorization, expected):
        abort(401)

    event = request.get_json()
    event_id = event["id"]
    event_type = event["type"]
    task = event["data"]["object"]

    # 生产环境应先按 event_id 去重,再把下载、转存等耗时操作放入任务队列。
    if event_type == "video.task.succeeded":
        videos = task["result"]["videos"]
        print(event_id, task["id"], videos)
    elif event_type == "video.task.failed":
        print(event_id, task["id"], task["error"])

    return "", 204


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=3000)
bash
export SUPERTOKEN_WEBHOOK_KEY="YOUR_WEBHOOK_KEY"
python3 -m pip install flask
python3 webhook.py

确认、去重与重试

  • 接收端返回任意 HTTP 2xx 即表示投递成功,响应体会被忽略。
  • 网络错误、超时或非 2xx 会触发重试。默认总共尝试 3 次、固定间隔 30 秒,实际次数和间隔可能由管理员调整。
  • 同一个事件在重试时保持相同的顶层 id。请给事件 ID 建立唯一约束,不要用任务 ID 代替事件去重键。
  • 接收端应快速完成鉴权、去重和入队,然后立即返回 2xx;视频下载、转存和订单更新应放在自己的后台任务中。
  • 不要在日志中记录完整的 wk-... Key;怀疑泄露时立即重新生成。

Webhook 与轮询可以同时使用。长时间没有收到通知时,使用资源 API Key 查询 /v1/video/tasks/{task_id} 作为兜底;业务处理前也可以再查询一次任务,确认最终状态。

接收端检查清单

检查项建议
来源校验常量时间比较完整的 Authorization: Bearer wk-...
幂等处理使用事件顶层 id 建立唯一约束
响应时间校验并入队后立即返回 2xx
结果下载根据 url_auth 决定是否发送 ak_...
长期保存下载后转存,不依赖 temporary URL 永久可用
补偿机制超时未收到事件时查询 /v1/video/tasks/{task_id}

下一步

SuperToken - 让全球顶级 AI 模型触手可达