Webhook 回调
Token8 支持任务完成后主动推送结果到你的服务器,无需轮询。
配置方式
在请求中传入 callback_url,任务完成后 Token8 自动 POST 结果到该地址:
{
"model": "gpt-image-2",
"prompt": "...",
"callback_url": "https://your-server.com/webhook"
}
callback_url 可选,不传则需主动轮询 任务查询接口。
回调格式
任务完成后,Token8 向你的 URL 发送 POST 请求。回调体与 任务查询 API 响应完全一致,客户端只需一套解析代码。
POST https://your-server.com/webhook
Content-Type: application/json
成功回调:
{
"task_id": "task_abc123def456",
"status": "completed",
"model": "gpt-image-2",
"provider": "Token8",
"elapsed_s": 23,
"created_at": 1714450000,
"completed_at": 1714450023,
"data": [{ "url": "https://r2.token8.pro/task_abc123def456.png" }],
"total_cost": 5000,
"attempt_count": 1,
"attempts": [
{ "attempt_no": 1, "provider": "Token8", "status": "completed", "elapsed_s": 23 }
]
}
重试后成功:
{
"task_id": "task_abc123def456",
"status": "completed",
"model": "gpt-image-2",
"provider": "Pic2API",
"elapsed_s": 35,
"created_at": 1714450000,
"completed_at": 1714450035,
"data": [{ "url": "https://r2.token8.pro/task_abc123def456.png" }],
"total_cost": 3000,
"attempt_count": 2,
"attempts": [
{ "attempt_no": 1, "provider": "Token8", "status": "failed", "fail_reason": "provider_timeout", "elapsed_s": 12 },
{ "attempt_no": 2, "provider": "Pic2API", "status": "completed", "elapsed_s": 23 }
]
}
完整字段说明见 任务查询 API — 响应字段。
本地调试?用 webhook.site
没有公网服务器也能测试回调。打开 webhook.site,页面会自动生成一个唯一 URL:
- 复制页面上的 URL(形如
https://webhook.site/xxxxxxxx-xxxx-...) - 将该 URL 作为请求中的
callback_url传入 - 任务完成后刷新 webhook.site 页面,即可看到 Token8 POST 过来的完整回调内容
curl https://api.token8.pro/v1/images/generations \
-H "Authorization: Bearer sk-你的AutoKey" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "测试回调",
"callback_url": "https://webhook.site/你的唯一ID"
}'
webhook.site 免费版每个 URL 可接收 500 次请求,足够开发调试使用。
生产环境接收端示例
如果你需要自建接收服务:
Node.js (H3):
import { createApp, createRouter, defineEventHandler, readBody, toNodeListener } from 'h3'
import { createServer } from 'node:http'
const app = createApp()
const router = createRouter()
router.post('/webhook', defineEventHandler(async (event) => {
const body = await readBody(event)
const { task_id, status, data, elapsed_s, attempt_count } = body
if (status === 'completed') {
console.log(`任务 ${task_id} 完成: ${data[0].url} (${elapsed_s}s, ${attempt_count}次)`)
}
return { ok: true }
}))
app.use(router)
createServer(toNodeListener(app)).listen(8080, () => {
console.log('Webhook 服务已启动 :8080')
})
Python (FastAPI):
from fastapi import FastAPI, Request
app = FastAPI()
@app.post('/webhook')
async def webhook(request: Request):
payload = await request.json()
if payload['status'] == 'completed':
print(f"任务 {payload['task_id']} 完成:{payload['data'][0]['url']} ({payload['elapsed_s']}s, {payload['attempt_count']}次)")
return {'ok': True}
# uvicorn main:app --port 8080