Webhook 概览
每次发生重要变更时,Sursa 都会记录一个事件:卡片已发布、已核实或已归档,公告已被阅读,问题没有得到回答。有两种接收事件的方式,可以同时使用:
| Webhook | 事件记录 | |
|---|---|---|
| 方式 | 事件发生时,Sursa 把每个事件发送到您的 HTTPS 地址。 | 在需要时读取 GET /v1/webhook-events。 |
| 延迟 | 几秒。 | 取决于轮询频率。 |
| 需要 | 一个公网可访问的 HTTPS 接收端。 | 只需要一个具有 admin 角色和 webhooks:manage 权限范围的 API 密钥。 |
| 适用于 | 对变更作出响应:发送通知、同步、启动工作流。 | 批处理作业、停机后补齐、比对。 |
两种方式传递的事件相同,ID 也相同。无论是否有 Webhook 订阅,每个事件都会在事件记录中保留 30 天。
事件
{
"id": "evt_0123456789abcdef0123456789abcdef",
"type": "card.updated",
"created_at": "2026-10-24T10:00:03Z",
"org_id": 1,
"api_version": "1.60.0",
"sequence": 1042,
"object": {"type": "card", "id": "3f2c9a7e-5b1d-4c8e-9f0a-1b2c3d4e5f60"},
"payload": "full",
"data": {
"card": {"id": "3f2c9a7e-5b1d-4c8e-9f0a-1b2c3d4e5f60", "title": "Refund policy", "collection": "support", "version": 4},
"actor_id": 7,
"previous_attributes": {"title": "Refunds"}
},
"test": false
}
| 字段 | 含义 |
|---|---|
id | 事件的 ID,由 evt_ 和 32 个十六进制字符组成。在每次投递尝试和事件记录中都相同。 |
type | 发生了什么,形式为 <object>.<past-tense verb>:card.updated、access_request.resolved。 |
created_at | 变更发生的时间(UTC)。 |
api_version | data 所遵循的结构定义对应的 API 版本。 |
object | 事件所涉及对象的类型和 ID。 |
data | 详细信息。其结构取决于事件类型,在事件目录中有说明。 |
data.previous_attributes | 在 *.updated 事件中:已变更字段之前的值。 |
sequence、payload、test | 仅出现在 Webhook 投递中:在该 Webhook 投递顺序中的位置、有效负载模式,以及是否为测试事件。 |
data 只包含该对象的任何读者通过 API 都能看到的内容。其中从不包含访问列表、其他人的权限或隐藏字段。事件中的原因是简短的中性代码,例如 no_hits、restricted 或 index_failed。
事件类型
事件涵盖以下领域:
| 领域 | 示例 |
|---|---|
| 卡片 | card.created、card.updated、card.published、card.archived、card.deleted、card.indexed、card.index_failed |
| 核实 | card.verified、card.unverified、verification.expired、verification.requested |
| 结构 | collection.created、folder.updated |
| 协作 | comment.created、draft.publish_requested、announcement.sent、announcement.read |
| 回答 | question.unanswered、question.feedback_created、access_request.created |
| 人员与访问权限 | user.created、user.deactivated、group.member_added、api_key.expiring |
| 数据源与导入 | source.sync_completed、import.sync_completed、import.document_failed |
| 作业 | job.completed、job.failed、export.ready |
| Webhook | webhook.endpoint_disabled、webhook.ping |
包含结构定义和示例的完整事件列表,见 API 参考中的事件目录。GET /v1/webhooks/catalog 返回您的部署中可用的事件类型。
随着时间推移,会新增事件类型,现有事件也会增加字段。事件类型永远不会被重命名或删除。接收端必须跳过不认识的类型和字段。
谁会收到哪些事件
只有当事件所涉及的对象对某个 Webhook 可见时,该 Webhook 才会收到这个事件;可见性的判断方式与 API 密钥相同:按角色、数据权限档案和合集。仅限 support 合集的 Webhook 永远不会收到有关 finance 中卡片的事件。有关人员、密钥、数据源、导入、作业、导出、计费、应用以及 Webhook 本身的事件只投递给具有 admin 角色的 Webhook。
在此范围内,每个 Webhook 自行选择要接收的事件:
- 按类型,可以使用通配符:
card.*表示所有卡片事件,*表示所有事件; - 对于卡片事件,还可以按合集和标签选择。
Webhook 的有效负载模式为 full(带 data 的事件,默认)或 thin(不带 data 的事件:接收端用自己的密钥通过 API 读取对象,始终看到其当前状态)。
投递要点
- 以 JSON 形式发送事件的 HTTPS
POST,用该 Webhook 的签名密钥以两种格式签名:Standard Webhooks(webhook-signature)和旧版的X-KB-Signature。 - 10 秒内返回任何
2xx都算成功。 - 投递失败时,按逐渐拉长的间隔重试将近三天。遵循
429或503响应中的Retry-After;410会停用该 Webhook;连续失败 10 次会暂停该 Webhook,直到它被恢复。 - 投递到同一个 Webhook 的事件严格按顺序发送。响应慢的 Webhook 不会拖慢其他 Webhook。
- 同一个事件可能不止一次到达:按
webhook-id去除重复。
接收 Webhook逐步介绍一个完整的接收端,并提供 Node.js、Python 和 Go 的签名验证代码。
管理 Webhook
| 任务 | 接口 |
|---|---|
| 创建 Webhook 并获取其签名密钥 | POST /v1/webhooks |
| 更改接收地址、事件或状态 | PATCH /v1/webhooks/{webhook_id} |
| 发送测试事件 | POST /v1/webhooks/{webhook_id}/test |
| 轮换签名密钥 | POST /v1/webhooks/{webhook_id}/rotate-secret |
| 恢复已暂停的 Webhook | POST /v1/webhooks/{webhook_id}/resume |
| 查看投递和响应 | GET /v1/webhooks/{webhook_id}/deliveries |
| 重新投递 | POST /v1/webhooks/{webhook_id}/deliveries/{delivery_id}/redeliver |
管理 Webhook 需要具有 admin 角色和 webhooks:manage 权限范围的密钥,或者由管理员在管理后台中操作。一个组织最多可以有 20 个 Webhook。Webhook 是组织套餐的一部分;套餐不包含 Webhook 时,这些接口返回 403,错误码为 webhooks.feature_disabled。