Warmbly文档

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,点击添加端点。

  1. 输入 Warmbly 应通过 POST 投递事件的 HTTPS URL,必须可从公网路由访问。私有地址、回环地址和链路本地地址会被拒绝。
  2. 可添加描述,便于日后区分端点。
  3. 选择订阅事件。留空表示所有标准事件;高流量 firehose 事件需另行启用,详见下文。
  4. 点击创建。签名密钥只显示一次,请立即复制并妥善保存在密钥管理器或环境变量中,之后不会再次显示。日后需要新密钥时可使用轮换密钥。

密钥静态存储时使用实例凭据密钥加密,与保护邮箱密码的是同一密钥;仅在对投递签名时解密。创建后,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 和自动化工具。

本页目录