Webhooks
AvatarGo 可以在事情发生时通知你的服务器——会话开始或结束了、预渲染视频做好了——方式是向你的一个地址发送 HTTPS POST。
有哪些事件、每个事件带什么,列在 API 参考的 Webhooks 下。
设置接收地址
在 AvatarGo 控制台 打开 Webhooks,按 Add endpoint:
- URL——你服务器上一个
https://地址,要能从公网访问。 - Events——要发到这里的事件类型。
接收地址的签名密钥只在添加后显示一次:当场复制,保存在你的服务器上。Send test event 会发送一个 webhook.test 事件
(data 为 {}),用来检查你的服务器能否正常回复。一个账户最多 20 个接收地址。
发送的内容
每个事件是一个带 JSON 正文的 POST:
{
"id": "evt_…",
"type": "session.ended",
"createdAt": "2026-11-07T09:30:00.000Z",
"data": { }
}id 每个事件唯一;data 的内容取决于 type。
校验签名
每个请求都带一个 AvatarGo-Signature 请求头:
AvatarGo-Signature: t=1794040000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bdt 是发送时间,自 1970 年起的秒数;v1 是以你的签名密钥为 key,对 t、一个点和请求正文计算的 HMAC-SHA256,十六进制。
要对原样收到的正文计算——在解析 JSON 之前——并检查 t 是最近的,这样旧请求无法被当作新请求重发。
Node
import { createHmac, timingSafeEqual } from "node:crypto";
// header:AvatarGo-Signature 请求头;body:原始请求正文,字符串;secret:接收地址的签名密钥。
export function verifyAvatarGo(header, body, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
const expected = createHmac("sha256", secret).update(`${t}.${body}`).digest();
const given = Buffer.from(parts.v1 ?? "", "hex");
return given.length === expected.length && timingSafeEqual(given, expected);
}回复与重试
10 秒内回复任意 2xx 状态。其他情况——别的状态码、没有及时回复、连接失败——会在 1 分钟、5 分钟、30 分钟、2 小时、6 小时和
15 小时后重试:一共 7 次,持续大约一天。
所以同一个事件可能到达不止一次:记下处理过的 id,跳过重复的。先回复再做事,不要反过来,免得一件慢活变成一次重试。
接收地址一直失败时
如果发往某个接收地址的投递连续 3 天全部失败,这个接收地址会被关闭,并发邮件通知你账户的所有者。修好你的服务器后,在控制台里该接收地址上按 Turn on:从那时起,新事件会重新发送;关闭期间的事件不会补发。
请求只发往公网上的地址,不跟随重定向。在控制台里,每个接收地址的 Deliveries 显示最近 30 天发送的内容及每一次尝试,Resend 可以把一个事件再发一次。