接收 Webhook

新条目一保存就直接推送到您自己的地址。条目变为可检索(或未能变为可检索)、条目被删除,这两件事无法通过轮询得知,只能通过这条路径获得。接收地址在账户页面设置。

请求头

每次推送都会带上。是否校验由您决定。

请求头示例说明
webhook-idmsg_2KWPBg…幂等键。同一事件的所有重试中保持不变。
webhook-timestamp1614265330unix 秒。确认是近期值可防止重放。
webhook-signaturev1,g0hM9SsE…正文的 HMAC-SHA256,base64 编码。
content-typeapplication/json固定为该值。
您注册的认证请求头名称您注册的认证请求头的值若已注册则一并发送。
POST <your endpoint>
content-type: application/json
webhook-id: msg_2KWPBgLlAfxdpx2AI54pPJ85f4W
webhook-timestamp: 1614265330
webhook-signature: v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=

正文

信封始终一致,由 type 决定 data 的形状。

typedata何时
note.created单个条目,包含正文条目被保存时。并不表示已可检索 — 请看 status
note.ready{ count, group_id?, items[] }已保存的条目变为可检索时。每一轮处理按分组各发一次。
note.failed{ count, group_id?, items[] }已保存的条目最终未能变为可检索时。条目仍然还在。
note.deleted{ count, items[{id}] }条目被删除时。只有 id——它们已经不在了。
webhook.ping{}您点击测试连接时。

单条保存

{
  "type": "note.created",
  "timestamp": "2026-09-05T04:12:07Z",
  "data": {
    "id": 41,
    "title": "…",
    "summary": "…",
    "content": "…",
    "created_at": "2026-09-05T04:11:58Z",
    "origin": "Claude",
    "status": "ready",
    "group_id": null
  }
}

上传的一个分片

{
  "type": "note.created",
  "timestamp": "2026-09-05T04:12:09Z",
  "data": {
    "id": 42,
    "title": "… (3/77, p.47–53)",
    "summary": "…",
    "content": "…",
    "created_at": "2026-09-05T04:12:08Z",
    "origin": "Upload",
    "status": "pending",
    "group_id": "9f2c1ab84e7d4f0b93c5a61d2e8b7c40"
  }
}

上传的分片变为可检索时

{
  "type": "note.ready",
  "timestamp": "2026-09-05T04:31:12Z",
  "data": {
    "count": 2,
    "group_id": "9f2c1ab84e7d4f0b93c5a61d2e8b7c40",
    "items": [
      { "id": 42, "title": "… (3/77, p.47–53)", "status": "ready" },
      { "id": 43, "title": "… (4/77, p.54–60)", "status": "ready" }
    ]
  }
}

上传的分片检索准备失败时

{
  "type": "note.failed",
  "timestamp": "2026-09-05T04:36:40Z",
  "data": {
    "count": 2,
    "group_id": "9f2c1ab84e7d4f0b93c5a61d2e8b7c40",
    "items": [
      { "id": 44, "title": "… (5/77, p.61–67)", "status": "failed" },
      { "id": 45, "title": "… (6/77, p.68–74)", "status": "failed" }
    ]
  }
}

同一个文件可能一部分已就绪、一部分失败:这时两条事件会带着同一个 group_id,相隔几秒先后送达。

条目被删除时

{
  "type": "note.deleted",
  "timestamp": "2026-09-05T05:02:44Z",
  "data": { "count": 2, "items": [{ "id": 42 }, { "id": 43 }] }
}

连接测试

{
  "type": "webhook.ping",
  "timestamp": "2026-09-05T05:10:00Z",
  "data": {}
}

单条保存与上传

两种流程使用相同的事件类型;statusgroup_id 会告诉您收到的是哪一种。

单条保存——从 MCP、REST API 或仪表板保存时。只有一条 note.created,而且一到达就已经可以检索。

文件上传——文件会被拆成分片,每个分片各有一条 note.created。此时都还不能检索;准备好之后 note.ready 再单独发来。

单条保存上传(一个文件)
note.created一条,status: "ready"group_id: null每个分片一条status: "pending",带 group_id
note.ready不会发送分片变为可检索时发送
note.failed不会发送某个分片无法变为可检索时发送
可检索时点note.creatednote.ready
可读取时点立即立即——等待的只是检索
分片编号不是字段。只有标题里的 (3/77)data.id 的顺序
  • status——表示条目是否可以检索。"ready" 是可以,"pending" 是还在准备中,"failed" 是检索准备失败,检索不会找到它。
  • group_id——一批条目的名字。它在您上传文件时签发,该文件的每个分片都带同一个值。它表示分片属于哪个文件,而不是第几个分片,也是把 note.created 和随后到来的 note.ready 关联起来的键。
  • 如果只需要能检索的条目——请以 note.ready 为准,跳过 status"pending"note.created
  • 待处理的分片也能立即读取——正文已经在负载里。如需再次读取,请用不计入打开次数的 GET /api/v1/notes/{id},整批则用 GET /api/v1/notes/group/{group_id}
  • note.ready 不是每个文件一次——每次只带上同时准备好的分片,所以处理分批、或某个分片重试过,就会用同一个 group_id 发送多次。count 是这一次带的条数,不是整个文件的分片数,请累加 items
  • note.failed 不表示条目被删除——它仍然保存着、也能读取,失败的只是检索准备。请不要从您的副本中删除它;删除另有自己的事件 note.deleted。在仪表板点击重试可以重新准备,若再次失败会送来一条新的 note.failed

如何编写接收端

收到后立即返回 2xx,处理交给自己的队列。

要这样做否则
立即返回 2xx,稍后处理超过 25 秒我们会视为失败并重发。
webhook-id 去重同一条目会被处理两次。
对重复返回 200,切勿 429429 表示“慢一点”,我们会再发一次。
data.id 排序重试可能超过后面的事件;顺序不保证。
注册最终地址我们不跟随重定向——3xx 会当场结束投递。

验证签名(可选)

用于确认这次推送确实来自我们,且正文在途中没有被改动。

  1. 构造签名字符串:{webhook-id}.{webhook-timestamp}.{原始正文}
  2. 推导密钥:去掉密钥的 whsec_ 前缀,再对其余部分做 base64 解码
  3. 计算 HMAC-SHA256,base64 编码后与 v1, 之后的值比较
  4. 检查 webhook-timestamp 是否在当前时间的几分钟以内
  5. 用收到的原始字节校验——把 JSON 解析后再序列化会破坏签名
  6. 使用任意 Standard Webhooks 库(standardwebhooks.com)可代为完成第 1~5 步

签名密钥在账户页面,可在那里复制或更换。

重试

投递失败时我们最多再发三次(含首次共 4 次)。只有 2xx 算作送达。

响应我们的处理
2xx完成。
4084295xx分别在 15 分钟、1 小时、3 小时后重试。
完全没有响应按相同间隔重试。
3xx 及其他所有 4xx就此结束——答案不会改变。

即使持续失败,我们也不会自动停用投递。在此期间每天最多发一封邮件通知您,账户页面会显示连续失败次数和最后一次错误。

如果您的接收端停机超过约四小时,请用 GET /api/v1/notes/changes 追平。

更多

接收地址的设置、签名密钥和连接测试都在账户页面。REST API 的密钥、端点和错误见 REST API 文档。常见问题的答案在 FAQ 里。如果有不清楚或出问题 的地方,请联系我们——每一条消息都有真人阅读。