Webhook
Warmbly 工作区发生事件时,实时接收 HTTP 回调。
工作区发生事件,例如收到回复或营销活动完成时,Webhook 会向你自己的 URL 发送带签名的 HTTP POST。可据此更新 CRM 或触发其他工具,无需轮询 API。
添加 Webhook
打开设置 -> Webhook,点击添加端点。
输入 Warmbly 应通过 POST 投递事件的公开 HTTPS URL。
选择要订阅的事件;留空则接收所有标准事件。
点击创建并立即复制签名密钥,它只显示一次。
向 Warmbly 的测试请求返回任意 2xx 状态以验证端点,随后开始接收真实事件。
使用须知
- 未验证端点只会收到验证挑战请求,不会收到真实事件。
- 高流量 firehose 事件,包括营销活动发送、打开、点击和收件箱同步,必须明确添加。
- 每次投递都应基于原始请求体验证
X-Warmbly-Signature请求头。 - 投递失败会重试,最多尝试 8 次,随后标记为已放弃。
- 每次尝试均记录在端点的投递记录标签页,可从中重新投递失败事件。
浏览筛选、搜索和视图选择会保存在浏览器标签页中,刷新或导航后可恢复,并按用户和工作区分别记录。
Webhook 使外部系统无需轮询 API 即可响应 Warmbly 中的活动。事件触发时,例如收到回复、营销活动完成或会议被预约,Warmbly 向工作区注册的每个匹配端点发送带签名的 HTTP POST。随后可更新 CRM、触发 Slack 消息,或交给其他工具处理。
如果需要能够在防火墙后运行、无需公开 URL 的产品内替代方式,自动化流程的触发事件步骤可以将自定义事件发布到实时套接字。
在控制台打开设置 -> Webhook,点击添加端点。
- 输入 Warmbly 应通过 POST 投递事件的 HTTPS URL,必须可从公网路由访问。私有地址、回环地址和链路本地地址会被拒绝。
- 可添加描述,便于日后区分端点。
- 选择订阅事件。留空表示所有标准事件;高流量 firehose 事件需另行启用,详见下文。
- 点击创建。签名密钥只显示一次,请立即复制并妥善保存在密钥管理器或环境变量中,之后不会再次显示。日后需要新密钥时可使用轮换密钥。
密钥静态存储时使用实例凭据密钥加密,与保护邮箱密码的是同一密钥;仅在对投递签名时解密。创建后,API 不会再返回该密钥,管理员面板也不会显示。
创建后,端点处于未验证状态,只接收挑战请求,不接收真实事件。
创建后,Warmbly 立即向 URL 发送 POST,并携带 X-Warmbly-Event: webhook.test。在控制台点击发送测试或调用 POST /webhooks/{id}/verify 时也会发送。请求体为:
{
"event_type": "webhook.test",
"data": {
"challenge": "whcg_...",
"endpoint_id": "...",
"message": "This is a Warmbly webhook verification request."
}
}返回任意 2xx 即可确认端点可达。对于在常规控制台中注册的端点,只需完成这一步,Warmbly 就会将其标记为已验证,并开始投递真实事件。
如果开发的 OAuth 应用代表用户注册端点,还必须回传 challenge 值来证明对 URL 的控制权,可放在响应体({ "challenge": "whcg_..." })或 X-Warmbly-Webhook-Challenge 响应头中。
更改端点 URL 的主机名会重新要求验证。 端点恢复未验证状态,必须再次通过挑战。
设置中的事件选择器按类别显示完整目录,需要注意:
- 留空会订阅所有标准事件,即非 firehose 事件。
- 高流量事件,例如营销活动发送、打开、点击和收件箱同步,标记为 firehose,必须明确添加。仅在接收端能承受持续流量时订阅。
- 可随时更新事件列表,不影响签名密钥或验证状态。
完整事件目录可通过 GET /webhooks/event-types 获取。完整列表参见 Webhook API 参考。
每次投递尝试都会记录。在设置 -> Webhook 中打开端点,进入投递记录标签页,可查看:
- 状态(
delivered、failed、abandoned、pending); - 事件类型与时间戳;
- HTTP 响应码与响应体片段;
- 已尝试次数。
也可使用 GET /webhooks/deliveries 查询所有端点的投递,或用 GET /webhooks/{id}/deliveries 限定一个端点。两者均支持按状态和事件类型筛选,并返回不透明游标分页。
如果事件因限流而未投递,它会出现在 GET /webhooks/throttle-drops 中,而非投递日志。
在控制台打开失败的投递并点击重新投递。也可调用 POST /webhooks/deliveries/{deliveryId}/redeliver。重新投递会使用原始载荷和相同的 X-Warmbly-Event-Id 值再次入队;即使原投递最终也已到达,接收端的幂等逻辑仍可正确去重。
每次投递都携带 X-Warmbly-Signature 请求头,格式为 t=<unix>,v1=<hex>。必须在任何 JSON 解析之前,基于原始请求体进行验证:
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 # reject replays older than 5 minutes
key = secret.encode() # your whsec_... value as bytes
signed = f"{t}.".encode() + raw_body
expected = hmac.new(key, signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, v1)要点:
- 使用常量时间比较(
hmac.compare_digest或同类方法),防止时序攻击。 - 拒绝时间戳与当前时间相差超过 5 分钟的投递,限制重放窗口。
- 只接受可识别的方案(
v1),忽略未知方案前缀。 - 使用
X-Warmbly-Event-Id(或载荷中的id字段)作为幂等键。如果 Warmbly 收到2xx前已触发重试,同一事件 ID 可能到达多次。
端点返回非 2xx 响应或超时时,Warmbly 会采用指数退避重试:30 秒、1 分钟、2 分钟、4 分钟,依此类推,两次尝试间隔最长 1 小时,总计最多尝试 8 次。8 次均失败后,投递标记为已放弃。
不会跟随重定向。3xx 响应被视为失败。
如果端点在一段持续时间内不断失败,Warmbly 会自动禁用它,以保护下游系统及第三方接收基础设施。接收端恢复后,在设置中重新启用,再从投递日志重新发送需要恢复的已放弃事件。
OAuth 应用代表用户注册 Webhook 端点时,必须在创建或更新应用时通过 allowed_webhook_domains 声明允许的域名,参见 OAuth。应用注册的任何端点 URL,其主机名都必须位于该列表内。列表为空表示该应用不得注册 Webhook。
条目前加点号时,域名匹配包含子域名:.acme.com 匹配 acme.com、hooks.acme.com 和任意更深层子域名。acme.com 这样的裸条目只精确匹配该主机名。
后续内容
- Webhook API 参考:完整的端点、载荷和投递日志规范。
- 自动化流程:无需公开 URL,在 Warmbly 内响应事件。
- 集成:连接第三方 CRM、Slack 和自动化工具。