API 参考
Webhook
任务进终态时由平台主动推送,省掉轮询。
01配置
建任务时传 webhook_url 即可:
{
"prompt": "…",
"webhook_url": "https://your.app/hooks/h3"
}任务到达 succeeded / failed / cancelled 时推送一次。
02请求头与签名
POST /hooks/h3
X-H3-Event-Id: evt_...
X-H3-Signature: t=1756180000,v1=<hmac_sha256>
{ "id": "vid_...", "status": "succeeded", "output": { … } }签名的计算对象是 "<t>.<原始报文>", 密钥是你的 webhook secret,算法 HMAC-SHA256。
必须用原始字节验签
先解析 JSON 再重新序列化会改变字节(键序、空白、Unicode 转义), 签名一定对不上。请在解析之前先拿到 raw body。03验签
import crypto from "node:crypto";
function verify(rawBody, header, secret) {
const parts = Object.fromEntries(
header.split(",").map((kv) => kv.split("=")),
);
const expected = crypto
.createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
// 定长比较,避免时序侧信道
const ok = crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(parts.v1),
);
// 顺带拒掉过老的时间戳,防重放
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
return ok && fresh;
}04幂等
至少一次投递
同一个事件可能被送达多次(网络抖动、我们这边重试)。 请用 X-H3-Event-Id 去重,把它当作幂等键存下来。05重试策略
你的服务返回非 2xx 或超时时,按以下间隔退避重试:
1min → 5min → 30min → 2h → 6h6 小时窗口用完即放弃,之后不再投递 —— 此时只能靠轮询兜底。 因此关键流程建议同时保留一条轮询路径,不要把成片交付完全押在 webhook 上。
多副本部署下同一事件不会被不同副本重复发送。