Webhook 完成通知
图片任务进入成功或失败终态后,SuperToken 可以向账号配置的地址发送 HTTP POST 通知。Webhook 是账号级配置,不是单次任务参数;创建 /v1/image/tasks 请求时不要传 webhook_url。
配置步骤
- 进入控制台的“资源管理中心”,打开“Webhook”页签。
- 填写接收通知的公开 HTTP/HTTPS 地址并启用配置,生产环境建议使用 HTTPS。
- 保存生成的
wk-...Webhook Key,并配置到接收服务的安全环境变量中。 - 点击“发送测试”,确认接收端能验证 Key 并返回 HTTP 2xx。
Webhook Key 只用于验证 SuperToken 发出的回调,不具有模型或资源 API 权限。重新生成 Key 后旧 Key 会立即失效,需要同步更新接收服务。
事件
| 事件 | 触发条件 | 结果位置 |
|---|---|---|
image.task.succeeded | 图片任务成功 | data.object.result.images[] |
image.task.failed | 图片任务失败 | data.object.error |
webhook.test | 在控制台点击“发送测试” | 用于验证地址和 Webhook Key |
回调请求头:
http
POST /webhooks/supertoken HTTP/1.1
Authorization: Bearer wk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json事件 Payload
json
{
"id": "evt_example123",
"object": "event",
"api_version": "2026-07-17",
"type": "image.task.succeeded",
"created_at": 1784682038,
"data": {
"object": {
"id": "task_example123",
"object": "image.task",
"model": "gpt-image-2",
"operation": "generation",
"status": "succeeded",
"progress": 100,
"result": {
"images": [
{
"asset_id": "asset_example123",
"url": "https://example.com/generated/image.png",
"mime_type": "image/png",
"format": "png",
"width": 1024,
"height": 1024,
"size_bytes": 1843921,
"filename": "image.png"
}
]
},
"usage": {},
"error": null,
"client_reference_id": "order-20260722-001",
"metadata": {},
"created_at": 1784682000,
"started_at": 1784682001,
"completed_at": 1784682038,
"updated_at": 1784682038
}
}
}json
{
"id": "evt_example456",
"object": "event",
"api_version": "2026-07-17",
"type": "image.task.failed",
"created_at": 1784682038,
"data": {
"object": {
"id": "task_example456",
"object": "image.task",
"model": "gpt-image-2",
"operation": "edit",
"status": "failed",
"progress": 100,
"result": null,
"usage": {},
"error": {
"code": "524",
"message": "Image generation service is temporarily unavailable. Please try again later.",
"retryable": true
},
"client_reference_id": "order-20260722-002",
"metadata": {},
"created_at": 1784682000,
"started_at": 1784682001,
"completed_at": 1784682038,
"updated_at": 1784682038
}
}
}data.object 与任务查询接口返回的任务对象一致。使用顶层 id 作为事件去重键,因为失败重试可能让同一个事件被投递多次。
失败事件中的 "524" 是业务错误码,不是 Webhook 的 HTTP 状态码。它表示图片服务内部暂时不可用,可以使用新的 Idempotency-Key 创建一次有限重试;回调不会暴露内部渠道、子分组、余额或上游 Request ID。
接收 Demo
Python · Flask
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_image_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 == "image.task.succeeded":
image_urls = [image["url"] for image in task["result"]["images"]]
print(event_id, task["id"], image_urls)
elif event_type == "image.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.pyNode.js 内置 HTTP 的完整接收程序见 Python 与 Node.js 代码示例。
确认、重试与兜底
- 接收端返回任意 HTTP 2xx 即表示投递成功,响应体会被忽略。
- 网络错误、超时或非 2xx 会触发重试。默认总共尝试 3 次、固定间隔 30 秒,实际次数和间隔可能由管理员调整。
- 接收端应快速返回 2xx,把下载图片、数据库更新等耗时操作放入自己的任务队列。
- 不要在日志中记录完整的
wk-...Key;怀疑泄露时应立即重新生成。 - Webhook 和任务查询可以同时使用。长时间未收到通知时,使用资源 API Key 查询任务状态作为兜底。
接收端检查清单
| 检查项 | 建议 |
|---|---|
| 来源校验 | 常量时间比较完整的 Authorization: Bearer wk-... |
| 幂等处理 | 使用事件顶层 id 建立唯一约束 |
| 响应时间 | 校验并落队列后立即返回 2xx |
| 业务处理 | 在自己的后台任务中下载图片、更新订单 |
| 补偿机制 | 超时未收到事件时查询 /v1/image/tasks/{task_id} |