开发者文档
Webhooks
Webhook 是带签名的变更通知,不包含笔记正文。请通过 REST API 获取最新内容。
Webhook 事件
| 事件 | 触发时机 |
|---|---|
| note.ended | 录音会话结束且最终转录可以通过 API 获取时触发。每次录音会话触发一次,因此包含多个会话的笔记可能多次触发。 |
| note.summary.generated | 摘要生成完成且可以通过 API 获取时触发。 |
| note.updated | 已结束笔记中的标题、内容等 API 可见信息发生变更时触发。短时间内的多次编辑会合并为一个事件。 |
| note.deleted | 笔记被删除(data.reason: "deleted"),或离开 API 密钥的可见范围(data.reason: "access_lost")时触发。 |
另有两个与 Webhook 端点本身相关的事件。endpoint.verification 会在创建端点或修改 URL 时发送;返回 2xx 后即可启用端点。endpoint.test 会在控制台点击“发送测试”或调用测试 API 时发送。
请求正文结构
Webhook 请求只包含事件标识符和处理状态,不包含转录或摘要正文。收到通知后,请使用 note_id 从 REST API 获取最新内容。
JSON
{
"event_id": "5f8c0a5e-...",
"event_type": "note.ended",
"occurred_at": "2026-08-12T05:20:00Z",
"data": {
"note_id": "note_abc123",
"recording_session_id": "rec_456",
"revision": 7,
"transcript_status": "ready",
"summary_status": "pending"
}
}验证签名
Alt 使用创建端点时签发的 whsec_... 密钥为每个请求签名。签名格式遵循 Standard Webhooks 规范:
HTTP
POST /webhooks/alt HTTP/1.1
Content-Type: application/json
webhook-id: 5f8c0a5e-...
webhook-timestamp: 1765515600
webhook-signature: v1,K5oZfzN95Z9UVu1EsPQmSmZQGGVfCM0jaZ0lPI4dvLU=signature
signed_content = "{webhook-id}.{webhook-timestamp}.{raw request body}"
signature = base64( HMAC-SHA256( base64url_decode(secret_after_whsec_), signed_content ) )- 请在框架解析 JSON 之前,使用原始请求体(raw body)验证签名。重新序列化解析后的 JSON 可能改变正文并导致验签失败。
- 使用常量时间比较函数验证签名,以防止时序攻击。
- 拒绝过期的时间戳以防止重放攻击。建议只接受与当前时间相差 ±5 分钟以内的时间戳。
- 签名不匹配的请求返回 4xx 拒绝。可直接使用的接收端代码见快速开始第 4 步。
投递失败与重试
- 请在 10 秒内返回 2xx。其他状态码或响应超时都会被视为投递失败。请先返回响应,再异步处理事件。
- 投递失败后,Alt 会逐步延长重试间隔(30 秒 → 5 分钟 → 30 分钟 → 2 小时 → 12 小时 → 12 小时,最多共 7 次)。
- 连续多次投递失败的端点会被自动停用。
- 不会跟随重定向;webhook URL 必须通过 HTTPS 直接响应。
处理重复事件
Webhook 采用至少一次投递(at-least-once),因此重试或在控制台重新发送时,同一事件可能到达多次。请短期保存已处理的 event_id,并跳过已处理的事件。
处理乱序事件
重试和并行投递可能导致事件的到达顺序与发生顺序不同。不要假设最后到达的事件包含最新状态。每当 API 可见的笔记信息发生变更,服务端都会将 revision 更新为更大的值。请为每篇笔记保存最后应用的 revision,并忽略相同或更小的值。若无法判断正确顺序,请通过 REST API 重新获取笔记;API 始终返回当前 revision。
检查遗漏的变更
- 如果接收端停机时间超过重试窗口,或端点被停用,Webhook 可能会遗漏。请定期调用
GET /v1/notes?updated_after=<last sync>,获取上次同步后发生变更的笔记。 - 带
reason: "access_lost"的note.deleted表示该笔记已离开你的凭据范围(例如个人笔记被移入团队空间)。请完全按删除处理:删除你保存的副本或阻断其访问。 - 仅靠增量查询无法发现已删除或离开可见范围的笔记。请定期重新获取完整笔记列表。使用
include_deleted=true可包含删除标记(tombstone)。如果已保存的笔记 ID 未出现在完整列表中,说明该笔记已被删除或已离开可见范围。