Webhook
订阅 Warmbly 平台事件,在自己的 HTTPS 端点接收带有 HMAC 签名的投递回调。
Webhook 让你的系统能够实时响应 Warmbly 中的活动。注册一个或多个 HTTPS 端点,可按特定事件类型筛选;每当订阅事件发生时,Warmbly 会向所有匹配端点 POST 已签名的 JSON 载荷。每次投递都使用 HMAC-SHA256 签名,并携带唯一事件 ID,便于验证真实性和对重放去重。失败投递会按指数退避重试,且可查询历史进行排错。
所有 Webhook 管理端点均限定在组织范围内,并共用身份验证要求:权限范围 WEBHOOKS · 组织权限 manage_settings。签名密钥由服务器生成,仅在创建和轮换时返回,因此应立即保存。
列出 Webhook 端点
GET /webhooks
返回调用者组织配置的所有端点。响应绝不包含密钥。
身份验证:权限范围 WEBHOOKS · 组织权限 manage_settings。
响应
返回包含已配置 endpoints 数组的对象,不使用 data + pagination 封装。
{
"endpoints": [
{
"id": "a3f1c2e4-5b6d-7e8f-9a0b-1c2d3e4f5a6b",
"organization_id": "11111111-2222-3333-4444-555555555555",
"url": "https://hooks.example.com/warmbly",
"description": "Production event sink",
"event_types": ["campaign.reply_received", "meeting.booked"],
"enabled": true,
"verified_at": "2026-06-11T18:02:14Z",
"ownership_confirmed": true,
"last_success_at": "2026-06-11T18:02:14Z",
"last_failure_at": null,
"last_failure_reason": null,
"consecutive_failures": 0,
"created_at": "2026-05-01T09:00:00Z",
"updated_at": "2026-06-11T18:02:14Z"
}
]
}列出可用事件类型
GET /webhooks/event-types
返回 Warmbly 可发出的所有事件的标准目录。可用于构建事件类型选择器,或在写入前验证 event_types 的值。
身份验证:权限范围 WEBHOOKS · 组织权限 manage_settings。
响应
{
"event_types": [
{
"type": "campaign.reply_received",
"category": "campaign",
"description": "A human reply lands for a campaign thread.",
"firehose": false
},
{
"type": "campaign.email_sent",
"category": "campaign",
"description": "A campaign email is dispatched by a worker.",
"firehose": true
}
]
}firehose: true 表示高频事件。event_types 列表为空的端点不会自动接收全量事件流中的高频事件;必须在 event_types 中逐项明确列出。详情见全量事件流。
创建 Webhook 端点
POST /webhooks
创建新的订阅。此次响应是唯一一次返回签名 secret,应立即保存。URL 必须为 HTTPS,且解析到可公开路由的主机。回环、私有和链路本地目标均会被拒绝,除非服务器为本地或自托管开发启用了不安全 Webhook URL。
新端点初始处于未经验证状态,只会收到一次已签名的挑战请求,在验证通过前不会收到实际事件。参阅端点验证。
身份验证:权限范围 WEBHOOKS · 组织权限 manage_settings。
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
url | string | 是 | 接收 POST 回调的 HTTPS URL,必须可公开路由。 |
description | string | 否 | 供自己识别使用的自由文本标签。 |
event_types | string[] | 否 | 要订阅的事件名称,每项都必须是已知类型。数组为空或省略时订阅全部常规事件,不包含全量事件流中的高频事件。 |
enabled | boolean | 否 | 端点是否启用。默认 true。 |
{
"url": "https://hooks.example.com/warmbly",
"description": "Production event sink",
"event_types": ["campaign.reply_received", "meeting.booked"],
"enabled": true
}响应
201 Created,包含完整端点对象和仅返回一次的 secret。新端点初始未经验证,verified_at 为 null;只有验证通过后才接收实时事件流。
{
"id": "a3f1c2e4-5b6d-7e8f-9a0b-1c2d3e4f5a6b",
"organization_id": "11111111-2222-3333-4444-555555555555",
"url": "https://hooks.example.com/warmbly",
"description": "Production event sink",
"event_types": ["campaign.reply_received", "meeting.booked"],
"enabled": true,
"verified_at": null,
"ownership_confirmed": false,
"last_success_at": null,
"last_failure_at": null,
"last_failure_reason": null,
"consecutive_failures": 0,
"created_at": "2026-06-11T18:00:00Z",
"updated_at": "2026-06-11T18:00:00Z",
"secret": "whsec_9f8e7d6c5b4a39281706f5e4d3c2b1a09f8e7d6c5b4a39281706f5e4d3c2b1a0"
}更新 Webhook 端点
PATCH /webhooks/:id
更新订阅的 URL、说明、事件筛选或启用状态。此处不修改签名密钥,需使用轮换端点。URL 和事件类型采用与创建时相同的验证规则。修改 URL 主机后,需要重新验证端点。
身份验证:权限范围 WEBHOOKS · 组织权限 manage_settings。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | UUID | 要更新的端点 ID。 |
请求体
结构与创建时相同。所有字段都会替换为发送的值,因此应发送完整的期望状态;event_types 会被覆盖,不会合并。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
url | string | 是 | 使用 HTTPS 且可公开路由的 URL。 |
description | string | 否 | 自由文本标签。 |
event_types | string[] | 否 | 替换现有事件筛选。为空表示全部常规事件,不含高频事件。 |
enabled | boolean | 否 | 启用状态。省略时默认 true。 |
响应
200 OK,包含更新后的端点,不含密钥。
删除 Webhook 端点
DELETE /webhooks/:id
删除订阅,并级联删除其投递历史。
身份验证:权限范围 WEBHOOKS · 组织权限 manage_settings。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | UUID | 要删除的端点 ID。 |
响应
204 No Content,响应体为空。
轮换签名密钥
POST /webhooks/:id/rotate-secret
签发新的签名密钥,并仅返回一次。已完成签名的在途投递在完成前仍需使用旧密钥验证,新投递则使用新密钥。轮换后应及时更新验证器。
身份验证:权限范围 WEBHOOKS · 组织权限 manage_settings。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | UUID | 要轮换密钥的端点 ID。 |
响应
200 OK,包含新密钥。这是唯一一次返回该密钥。
{
"secret": "whsec_1a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f7081"
}端点验证
POST /webhooks/:id/verify
新端点初始未经验证,通过可达性检查前不会收到实际事件。调用此端点会向目标 URL 发送一次已签名的挑战请求。端点验证后,它也可用作“发送测试事件”功能。
身份验证:权限范围 WEBHOOKS · 组织权限 manage_settings。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | UUID | 要验证的端点 ID。 |
质询请求
Warmbly 向端点 URL 发送 POST,携带 X-Warmbly-Event: webhook.test,请求体如下:
{
"event_type": "webhook.test",
"data": {
"challenge": "whcg_...",
"endpoint_id": "a3f1c2e4-5b6d-7e8f-9a0b-1c2d3e4f5a6b",
"message": "This is a Warmbly webhook verification request."
}
}挑战使用端点密钥签名,因此可像其他投递一样验证,参阅验证签名。
响应质询
对于简单可达性检查,即在控制台注册的端点,返回任意 2xx 即可,端点会标为已验证。
对于 URL 所有权证明,OAuth 应用注册的端点必须完成此项,还需回显 challenge 值。可在 JSON 响应体中返回:
{ "challenge": "whcg_..." }也可在响应头中返回:
X-Warmbly-Webhook-Challenge: whcg_...修改端点 URL 的主机后,会重新启动验证要求:端点恢复为未经验证,必须再次通过挑战才能恢复接收事件。
列出所有投递记录(整个组织)
GET /webhooks/deliveries
返回组织所有端点的投递尝试,按最新优先排序。可通过查询参数缩小结果范围。
身份验证:权限范围 WEBHOOKS · 组织权限 manage_settings。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
status | query | string | 按投递状态筛选,取值为 pending、in_flight、delivered、failed、abandoned 之一。 |
event_type | query | string | 按事件类型筛选,例如 campaign.reply_received。 |
limit | query | integer | 最大行数。范围为 1 至 200,默认 50。超出范围会返回 400。 |
cursor | query | string | 上一次响应 pagination.next_cursor 中的不透明分页游标。 |
响应
使用标准 data + pagination 封装和不透明游标。
{
"data": [
{
"id": "d1e2f3a4-b5c6-7d8e-9f0a-1b2c3d4e5f6a",
"endpoint_id": "a3f1c2e4-5b6d-7e8f-9a0b-1c2d3e4f5a6b",
"organization_id": "11111111-2222-3333-4444-555555555555",
"event_type": "campaign.reply_received",
"event_id": "e9f8a7b6-c5d4-3e2f-1a0b-9c8d7e6f5a4b",
"status": "delivered",
"attempt_count": 1,
"max_attempts": 8,
"next_attempt_at": null,
"last_attempt_at": "2026-06-11T18:02:14Z",
"response_status": 200,
"response_body_excerpt": "ok",
"error_reason": null,
"created_at": "2026-06-11T18:02:13Z",
"updated_at": "2026-06-11T18:02:14Z"
}
],
"pagination": {
"next_cursor": "eyJpZCI6ImQx...",
"has_more": true
}
}列出指定端点的投递记录
GET /webhooks/:id/deliveries
返回特定端点最近的投递尝试,最新优先。每行反映对应事件在全部重试尝试中的最新状态。
身份验证:权限范围 WEBHOOKS · 组织权限 manage_settings。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | UUID | 要列出投递记录的端点 ID。 |
status | query | string | 按投递状态筛选。 |
event_type | query | string | 按事件类型筛选。 |
limit | query | integer | 最大行数。范围为 1 至 200,默认 50。超出范围会返回 400。 |
cursor | query | string | 不透明分页游标。 |
响应
使用与组织级列表相同的 data + pagination 封装。
投递 status 为 pending、in_flight、delivered、failed 或 abandoned(重试次数耗尽)之一。response_body_excerpt 最多保留订阅者响应的前 1024 字节。
重新投递
POST /webhooks/deliveries/:deliveryId/redeliver
无论当前状态如何,都可手动将投递重新入队。适合在修复接收端后重放失败或已放弃的投递。重新投递是一轮新尝试,具有独立重试生命周期,但携带相同的 event_id,因此你的幂等键逻辑可以正确去重。
身份验证:权限范围 WEBHOOKS · 组织权限 manage_settings。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
deliveryId | path | UUID | 要重新投递的投递记录 ID。 |
响应
200 OK,包含更新后的投递对象。
列出因限流而丢弃的事件
GET /webhooks/throttle-drops
返回因每端点投递速率限制,或每组织、每事件类型分发限流而被抑制的事件。受限流影响的事件会在此展示,不会静默丢弃,便于监控集成处理压力,并在需要时重新投递。
身份验证:权限范围 WEBHOOKS · 组织权限 manage_settings。
投递负载
每次回调都是 HTTP POST,带有 Content-Type: application/json 请求体,结构如下:
| 字段 | 类型 | 说明 |
|---|---|---|
id | UUID | 唯一事件 ID。同一事件重试期间保持不变,与 X-Warmbly-Event-Id 一致。 |
event_type | string | 事件名称,例如 campaign.reply_received。 |
organization_id | UUID | 事件所属组织。 |
created_at | string | 事件分发时间,RFC 3339 UTC 时间戳。 |
data | object | 事件特定载荷,结构取决于 event_type。 |
{
"id": "e9f8a7b6-c5d4-3e2f-1a0b-9c8d7e6f5a4b",
"event_type": "campaign.reply_received",
"organization_id": "11111111-2222-3333-4444-555555555555",
"created_at": "2026-06-11T18:02:13Z",
"data": { "...": "event-specific object" }
}载荷中没有 version 字段。如果某种事件载荷发生不向后兼容的变更,会以新的 event_type 名称发布。现有事件类型名称绝不会原地变更版本。
收到回复事件的负载
campaign.reply_received 包含 contact_email、intent 和 confidence(基于工作区关键词列表的判读结果)、subject、snippet、action_taken、thread_id 及 email_account_id。contact_id 和 campaign_id 为可选项,仅在回复关联了对应联系人或营销活动时包含。如果收件箱标记已判断该邮件,还会携带已保存的判断结果:
{
"ai_labels": ["Meeting", "Interested"],
"ai_intent": "scheduling",
"ai_intent_confidence": 0.91,
"ai_kind": "human_reply",
"ai_relevance": 82,
"ai_needs_review": false
}如果标记功能对相应判断的置信度不足,无法据此操作,ai_kind 和 ai_intent 为空字符串;如果从未判断过该邮件,则省略全部六个键。各字段含义见自动化流程。
投递请求头
每次投递均携带以下请求头:
| 请求头 | 说明 |
|---|---|
X-Warmbly-Signature | HMAC-SHA256 签名,格式为 t=<unix>,v1=<hex>。 |
X-Warmbly-Event | 事件类型,便于无需解析请求体即可路由。 |
X-Warmbly-Event-Id | 唯一事件 ID,与载荷 id 相同。重试期间保持不变,应将其用作幂等键。 |
User-Agent | Warmbly-Webhooks/1.0. |
验证签名
Warmbly 使用端点签名密钥,通过 HMAC-SHA256 为每次投递签名。X-Warmbly-Signature 请求头格式为 t=<unix-timestamp>,v1=<hex-digest>。签名字符串依次为时间戳、字面字符 .、未经改动的原始请求体。
验证步骤:
- 从请求头解析
t和v1。 - 如果
t与当前系统时钟相差超过 5 分钟,拒绝请求。容差绝不能设为 0,否则即使晚到一秒也会导致投递失败。 - 计算
HMAC-SHA256(secret, t + "." + rawRequestBody),并将结果编码为十六进制。 - 使用恒定时间比较,将你的摘要与
v1比对,以防时序攻击。 - 忽略所有非
v1的方案,以防降级攻击,因为未来可能出现其他方案。
始终在任何 JSON 重新序列化之前,基于未经改动的原始请求体计算 HMAC。密钥是创建或轮换时返回的带 whsec_ 前缀的值。
# Pseudocode
signed_payload = t + "." + raw_body
expected_v1 = hex(hmac_sha256(whsec_..., signed_payload))
is_valid = constant_time_equal(expected_v1, v1) AND abs(now() - t) < 300Python 示例:
import hashlib, hmac, time
def verify(secret: str, header: str, raw_body: bytes) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
t, v1 = parts.get("t"), parts.get("v1")
if not t or not v1:
return False
if abs(time.time() - int(t)) > 300:
return False # replay too old
key = secret.encode() # whsec_... as bytes
signed = f"{t}.".encode() + raw_body
expected = hmac.new(key, signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, v1)使用 X-Warmbly-Event-Id 或载荷 id 字段作为幂等键,对重放去重。如果 Warmbly 收到你的 2xx 之前就触发重试,同一事件 ID 可能到达多次。
重试与退避
投递采用异步入队和消费,因此触发分发的 API 调用会立即返回,不会等待你的端点。
2xx响应会将投递标为delivered,并重置端点的失败健康状态。- 任意非
2xx响应,包括3xx(绝不跟随重定向),连接错误,或超时(请求超时为 15 秒),都会将尝试标为失败并安排重试。 - 退避间隔从 30 秒开始,每次重试加倍:30 秒、1 分钟、2 分钟、4 分钟、8 分钟、16 分钟、32 分钟。后续等待上限为 1 小时。
- 默认
max_attempts为 8。尝试次数耗尽后,投递标为abandoned。 4xx和5xx响应都会重试,直到尝试次数上限;4xx也可能只是暂时的验证异常。- 持续一段时间不断失败的端点会被自动停用,以保护第三方。接收端恢复稳定后,可在设置中重新启用。
处理程序应具有幂等性。按 X-Warmbly-Event-Id 去重,因为同一事件 ID 可能在重试中到达多次。
全量事件流
高频事件在事件目录中标有 firehose: true,且必须主动订阅。event_types 列表为空或省略的端点会订阅全部标准事件,但不会接收高频事件。要接收某个高频事件,必须明确列出:
{
"event_types": [
"campaign.reply_received",
"campaign.email_sent",
"campaign.email_opened"
]
}这样可避免默认集成被发送流水线或收件箱同步产生的大量事件淹没。应有选择地订阅,并在启用前确认接收端能承受持续吞吐量。
安全
- 仅限 HTTPS:端点 URL 必须使用
https://。普通 HTTP 会在注册时被拒绝。 - SSRF 防护:对外投递具备 SSRF 防护。建立连接时会阻止私有、回环、链路本地及云元数据 IP 范围。绝不跟随重定向,只允许标准 Web 端口。
- 速率限制:每端点投递速率限制和每组织、每事件类型分发限流,同时保护你的接收端和第三方。受限流影响的事件会出现在
GET /webhooks/throttle-drops中。 - 签名验证:始终验证
X-Warmbly-Signature请求头。忽略它意味着任何知道端点 URL 的人都可以重放或伪造事件。
事件目录
完整目录可通过 GET /webhooks/event-types 获取。下方为按类别分组的完整参考。标为高频事件的事件必须明确订阅,参阅全量事件流。
营销活动
| 事件 | 说明 | 高频事件 |
|---|---|---|
campaign.started | 营销活动开始发送。 | |
campaign.paused | 营销活动暂停。 | |
campaign.completed | 营销活动完成全部发送。 | |
campaign.created | 创建营销活动。 | |
campaign.updated | 营销活动设置发生变化。 | |
campaign.deleted | 删除营销活动。 | |
campaign.email_sent | 工作节点发出一封营销活动邮件。 | 是 |
campaign.email_delivered | 营销活动邮件被收件方邮件服务器接受。 | 是 |
campaign.email_opened | 用户打开跟踪邮件。能够获取打开环境信息时,载荷包含 origin,提供邮件客户端、应用或网页邮箱、设备和位置,与联系人时间线事件一致。自动打开,例如邮件隐私代理或发送后几秒内的抓取,不会触发此事件。 | 是 |
campaign.email_clicked | 用户点击跟踪链接。载荷包含 url、链接的 link_label,以及描述链接打开设备和浏览器的 origin。自动点击,例如安全网关遍历链接,不会触发此事件。 | 是 |
campaign.email_bounced | 营销活动邮件退信。 | |
campaign.reply_received | 营销活动会话收到人工回复。 | |
campaign.unsubscribed | 收件人退订。source 为 one_click(邮件客户端按钮)、link(邮件中的链接)、reply(要求停止联系的回复)或 action(邮件序列的退订步骤)。 | |
campaign.deliverability_warning | 营销活动的滚动退信率或投诉率进入预警区间。 | |
campaign.action | 邮件序列流程中的 notify 操作节点触发。 |
邮箱预热
| 事件 | 说明 | 高频事件 |
|---|---|---|
warmup.email_sent | 发送一封预热邮件。 | 是 |
warmup.health_changed | 邮箱预热健康状态发生转换。 | |
warmup.placement_in_spam | 观察到预热邮件落入垃圾邮件文件夹。载荷包含发件邮箱(email_account_id、email)、content_source,以及收件方的 recipient_provider(连接方式)和 recipient_host(邮件托管服务商,例如 google_workspace 或 zoho),绝不包含收件地址或域名。 | |
warmup.quarantined | 邮箱被隔离出共享预热池。 | |
warmup.blocked | 邮箱被共享预热池封禁。 |
邮件送达能力
| 事件 | 说明 | 高频事件 |
|---|---|---|
deliverability.bounce | 处理退信信号,包括硬退信或软退信。 | |
deliverability.complaint | 处理垃圾邮件投诉。 |
收件箱
| 事件 | 说明 | 高频事件 |
|---|---|---|
inbox.email_received | 已连接邮箱收到新邮件。 | 是 |
inbox.email_updated | 收件箱邮件状态变化,例如标签或已读状态。 | 是 |
inbox.email_deleted | 收件箱邮件被删除或彻底清除。 | 是 |
inbox.reply_received | 受跟踪的邮件会话收到人工回复,与 campaign.reply_received 不同。 |
邮箱
| 事件 | 说明 | 高频事件 |
|---|---|---|
email_account.connected | 邮箱连接到组织。 | |
email_account.disconnected | 邮箱失去连接,例如身份验证失败或令牌被撤销。 | |
email_account.removed | 邮箱从组织移除。 | |
email_account.error | 邮箱发生同步或发送错误。 | |
email_account.synced | 邮箱完成一次同步周期。 | 是 |
email_account.health_changed | 邮箱健康状态发生转换。 |
联系人
| 事件 | 说明 | 高频事件 |
|---|---|---|
contact.created | 创建联系人。包含 contact_id、contact_email、first_name、last_name、company、phone、subscribed、custom_fields、source、source_detail、campaign_ids、category_ids 和 created_at。手动、通过 API、表单或自动化流程添加联系人时触发;文件导入、表格同步和单个 API 请求添加超过 100 个联系人属于批量新增,不会触发。 | |
contact.updated | 联系人字段发生变化。 | |
contact.deleted | 删除联系人。 | |
form.submitted | 托管表单收到提交。包含表单 ID 和名称、提交记录 ID、data 下的答案、映射的联系人字段(contact_email、first_name、last_name、company、phone)、source_url;创建或匹配到联系人时还包含联系人 ID。 |
CRM
| 事件 | 说明 | 高频事件 |
|---|---|---|
crm.deal_created | 创建商机。 | |
crm.deal_updated | 商机字段或阶段发生变化。 | |
crm.deal_deleted | 删除商机。 | |
crm.task_created | 创建 CRM 任务。 | |
crm.task_updated | CRM 任务发生变化。批量写入(批量更新任务)只会对整次调用触发一次,不含 entity_id,metadata 中包含 bulk 和 count;因此缺少 ID 时,应理解为需要重新读取所跟踪的任务,而非单个任务。批量编辑联系人时,contact.updated 行为相同。 | |
crm.note_created | 向联系人或商机添加备注。 | |
crm.pipeline_updated | 销售管道或其阶段发生变化。 |
自动化流程
| 事件 | 说明 | 高频事件 |
|---|---|---|
automation.created | 创建自动化流程。 | |
automation.updated | 自动化流程定义或启用状态发生变化。 | |
automation.deleted | 删除自动化流程。 | |
automation.run | 自动化流程为某个联系人完成一次运行。 |
会议
| 事件 | 说明 | 高频事件 |
|---|---|---|
meeting.booked | 通过已连接的预约工具 Calendly 或 Cal.com 预约通话。 | |
meeting.rescheduled | 已预约的通话改期。 | |
meeting.canceled | 已预约的通话取消。 |
团队与访问权限
| 事件 | 说明 | 高频事件 |
|---|---|---|
team.member_invited | 发送团队成员邀请。 | |
team.member_removed | 成员从组织移除。 | |
role.created | 创建自定义角色。 | |
role.updated | 自定义角色权限发生变化。 | |
role.deleted | 删除自定义角色。 |
批量操作
| 事件 | 说明 | 高频事件 |
|---|---|---|
bulk_operation.started | 批量导入、导出或删除开始。 | |
bulk_operation.completed | 批量操作成功完成。 | |
bulk_operation.failed | 批量操作失败或中止。 |
工作区
| 事件 | 说明 | 高频事件 |
|---|---|---|
lead_sync_source.updated | 潜在客户同步来源更新,例如 CSV 导入或 Google Sheets。 | |
settings.updated | 组织设置发生变化。 | |
subscription.updated | 计费订阅变化,包括套餐、席位或状态。 |
开发者
| 事件 | 说明 | 高频事件 |
|---|---|---|
custom.event | 自动化流程或营销活动邮件序列中的“触发事件”步骤发出的自定义事件。 |
仅用作触发器(不向外投递)
inbound.webhook 是接收入站 HTTP 请求的自动化触发器,绝不会作为对外 Webhook 事件投递。
OAuth 应用级订阅
OAuth 应用无需手动为每个组织注册端点即可接收事件。只需在应用上设置一次 webhook_url 和 webhook_events,Warmbly 就会为每个授权该应用的组织自动创建受管理端点。事件取应用声明的事件与组织已授予权限范围允许事件的交集。应用使用同一个共享的 whsec_ 密钥签署所有投递,可通过验证签名所述的相同机制验证。
四个管理端点可检查和维护应用级投递流程:查看密钥、轮换密钥、列出各组织端点及健康状态,以及分页查看跨组织投递日志。四者均需 权限范围 API_KEYS 和组织权限 manage_api_keys。完整参考见OAuth:作为应用接收事件,其中包含权限范围与事件的对应表,以及与实时网关的比较。
OAuth 应用 Webhook 域名
代表用户注册 Webhook 端点的 OAuth 应用,必须声明这些端点可使用的域名。字段位于 OAuth 应用对象的 allowed_webhook_domains,类型为字符串数组。
OAuth 应用注册的任意 Webhook 端点,其 URL 主机都必须位于应用的 allowed_webhook_domains 允许范围内。注册时会强制检查,投递时也会重新检查。allowed_webhook_domains 列表为空的应用不能注册任何 Webhook 端点。
匹配规则:
- 不带前导点的条目(
acme.com)仅匹配完全相同的主机。 - 带前导点的条目(
.acme.com)匹配根域名及任意子域名:acme.com、hooks.acme.com、prod.hooks.acme.com。
例如,allowed_webhook_domains 为 [".acme.com"] 时,允许 https://hooks.acme.com/warmbly,拒绝 https://otherdomain.com/warmbly。
创建或更新 OAuth 应用时设置此字段:
{
"name": "My App",
"allowed_webhook_domains": [".acme.com"]
}完整的应用注册流程和字段参考见 OAuth。
从流程推送自定义数据
要将营销活动或自动化流程的自定义数据推送到端点,请添加“触发事件”操作步骤:它会发出 custom.event,由每个订阅该事件的端点接收,使用各端点自身密钥签名,并像其他投递一样重试。这样可保持统一验证模型:每个端点一份密钥,投递经过签名并支持重试。
错误
Webhook 端点采用标准错误封装,包含稳定的 code 和 request_id 字段,参阅错误码。常见情况:
400:载荷无效,url非 HTTPS 或不可路由,事件类型未知,或limit不在 1 至 200 之间。400:路径中的端点 ID 或投递 ID 无效。403:OAuth 应用尝试注册的端点 URL 主机不在allowed_webhook_domains中。404:端点或投递记录不存在,或不属于你的组织。
{
"error": "Bad Request",
"message": "unknown event type: campaign.exploded",
"code": "bad_request",
"request_id": "req_7Yc2pK1nQ4"
}