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:

  1. 复制页面上的 URL(形如 https://webhook.site/xxxxxxxx-xxxx-...
  2. 将该 URL 作为请求中的 callback_url 传入
  3. 任务完成后刷新 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