WAthink 使用手册

Webhook 配置指南:创建出站事件订阅、配置 HMAC 签名校验及入站捕获字段映射排查

出站 Webhook 让 WAthink 把事件实时推送到你自己的系统 — CRM、数据仓库、Zapier、Make、n8n,或任何 HTTPS 端点。只要工作区中发生你订阅的事件,WAthink 就会向你的 URL 发送一条 JSON 请求;你可以为请求签名,以验证它确实来自 WAthink。

实际入口、可用参数与操作权限,请结合所用版本、套餐及已启用模块核对。
本篇内容

概览

出站 Webhook 让 WAthink 把事件实时推送到你自己的系统 — CRM、数据仓库、Zapier、Make、n8n,或任何 HTTPS 端点。只要工作区中发生你订阅的事件,WAthink 就会向你的 URL 发送一条 JSON 请求;你可以为请求签名,以验证它确实来自 WAthink。

在 More → Webhooks 中管理它们。Webhook 在整个工作区共享:无论由谁创建,每位成员都能看到所有端点。事件发生时,WAthink 会把它投递到该工作区内所有订阅了该事件(或通配符 *)的活跃端点。

套餐限制。出站 Webhook 是付费套餐功能,每个套餐允许的端点数有限。如果你的套餐不包含该功能,或已达到上限,创建新端点会被阻止并提示升级。你仍然可以编辑和暂停/恢复已有的端点。
两个不同方向 — 不要混淆。本页讲的是 WAthink 发送给你 的 Webhook。外部系统 推送进 WAthink 的入站 Webhook 是另一个功能 — 它把外部系统接入 WAthink,见文末的入站与出站。

创建端点

在索引页点击 Add a webhook 并填写表单。右侧栏会显示实时示例负载与 Test fire 操作,让你在真实事件到来之前就能接好并验证接收端。

字段必填说明
Webhook URL是WAthink 发送的目标地址。必须是有效 URL — 请使用 HTTPS。以加密方式存储。
Method否投递使用的 HTTP 方法 — POST(默认)或 PUT。
Internal name否便于识别端点的名称,例如 "Production CRM relay"。最多 191 个字符。
Environment否用于组织端点的自由文本标签(默认 Production)。
Events是至少选择一个事件。见事件类型。
Signing secret否(推荐)用于为每次投递签名,便于你校验。以加密方式存储。见签名与校验。
Status否保存时端点是否活跃(接收事件)。默认开启。
所有敏感信息都已加密。URL、密钥与事件列表都在数据库中加密存放,只在发送投递的那一刻于内存中解锁 — 因此数据库泄露不会暴露你的端点或密钥。

事件类型

以下是可以为端点订阅的事件。你可以订阅任意子集 — 端点只会收到其列表中的事件。事件名称就是每个负载中 event / eventType 字段的值。

事件触发时机
message_received收到联系人发来的入站消息。
message_sent出站消息被接受发送。
message_delivered出站消息已送达收件人的设备。
message_read出站消息被读取(收件人开启了已读回执)。
message_failed出站消息发送失败 — 负载携带失败原因。
broadcast_created广播被创建。
broadcast_status_updated广播的整体状态变化。
broadcast_message_status_updated单个广播收件人的消息状态变化。
campaign_created营销活动被创建。
campaign_status_updated营销活动的状态变化。
campaign_contact_status_updated营销活动联系人的状态变化。
campaign_contact_clicked营销活动联系人点击了被跟踪的链接。
campaign_contact_replied营销活动联系人回复了。
contact_opt_in联系人的订阅状态变化 — 订阅或退订(STOP 关键词,或联系人上的退订开关)。负载携带 opted_in(布尔值)、action(unsubscribed / resubscribed)与 source。
contact_updated联系人记录被编辑(来自联系人详情页)。
device_status_updated设备的连接状态变化(已连接 / 已断开 / 配对中)。
上述每个事件都是实时的。全部十六个事件都会在动作发生时立即触发。投递在动作完成之后发送,因此接收端再慢,也不会拖慢 WAthink 内的发送、入站消息或状态更新。
通配符。为端点订阅 * 即可接收所有事件类型,包括未来版本新增的事件。可以把它当兜底;当接收端只处理特定事件时,请使用明确的列表。

投递负载

每次投递都是一个 JSON 请求体,所有事件共享相同的外层「信封」;事件特有的字段位于 data 下。请求以 Content-Type: application/json 发送。

信封

键类型含义
idstring (UUID)本次投递的唯一 ID。用于幂等 / 去重。
eventstring事件名称,例如 message_delivered。
eventTypestring与 event 相同的值(供按任一名称取值的接收端使用)。
createdstring (ISO-8601)WAthink 构建负载的时间,例如 2026-05-29T18:32:08+00:00。
timestampinteger (Unix)事件时间(秒)。有上游事件时间时与之相同,否则为构建时间。
dataobject事件特有的负载(字段随事件而变)。

示例 — message_delivered

一次真实投递如下所示。message_* 系列的 data 块包含消息标识、收件人、WhatsApp 消息 ID(wamid),以及失败时的类型化错误码与原因:

POST /your/endpoint HTTP/1.1
Host: api.yourbrand.example
Content-Type: application/json
X-WAthink-Signature: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

{
  "id": "3a8f7e2c-91b5-4d0f-a7a1-d6c8e4b9f2c0",
  "event": "message_delivered",
  "eventType": "message_delivered",
  "created": "2026-05-29T18:32:08+00:00",
  "timestamp": 1780000328,
  "data": {
    "workspace_id": 42,
    "user_id": 7,
    "message_id": 918273,
    "wamid": "3EB0A1B2C3D4E5F6A7B8C9",
    "recipient": "+919876543210",
    "status": "delivered",
    "timestamp": 1780000328,
    "error_code": null,
    "error_reason": null
  }
}
发送失败时(message_failed),同样的 data 结构会带有 status: "failed",并在 error_code 与 error_reason 中填入底层连接返回的失败原因。广播事件会额外包含 broadcast_id / broadcast_name,以及带有 sent / delivered / read / failed / clicked / total 实时计数的 aggregate 块。请始终防御式编程 — 把未知键视为可选。

签名与校验

如果你为端点设置了签名密钥,每次投递都会包含以下请求头:

X-WAthink-Signature: <hex>

该值是 HMAC-SHA256,对完整的 JSON 请求体(整个信封,而不仅是 data)计算,使用端点的密钥作为密钥,并以小写十六进制编码。如果未设置密钥,该请求头会被完全省略。

在你的服务端校验

对原始请求体(在 JSON 解析或重新序列化之前)重新计算 HMAC,并用恒定时间比较它与请求头:

# Pseudo-code — works in any language
secret   = "the secret you configured on the endpoint"
raw_body = read_raw_request_body()          # bytes, exactly as received
expected = hex( hmac_sha256(secret, raw_body) )
given    = request.header("X-WAthink-Signature")

if not constant_time_equals(expected, given):
    return 401                              # reject — do not process
process(json_parse(raw_body))               # safe to handle now
// Node.js (Express, raw body required)
const crypto = require('crypto');
const expected = crypto
  .createHmac('sha256', SECRET)
  .update(req.rawBody)                       // Buffer of the raw body
  .digest('hex');
const given = req.get('X-WAthink-Signature') || '';
const ok = expected.length === given.length &&
  crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(given));
if (!ok) return res.status(401).end();
// PHP (mirrors how WAthink signs it)
$expected = hash_hmac('sha256', $rawBody, $secret);
$given    = $_SERVER['HTTP_X_WATHINK_SIGNATURE'] ?? '';
if (!hash_equals($expected, $given)) { http_response_code(401); exit; }
先校验,再解析。务必对原始请求体的字节计算 HMAC — 重新序列化解析后的 JSON 可能改变键顺序或空白,从而破坏签名。请使用恒定时间比较。签名缺失或不匹配时,应视为失败请求并丢弃。密钥务必保密:任何持有它的人都能伪造看起来合法的投递。

投递、重试与健康状态

每次投递都是单次 HTTP 请求,超时时间 10 秒。收到任何 2xx 响应即视为成功;其它情况(4xx、5xx、超时、DNS 失败或连接错误)都算失败。失败时 WAthink 会自动重试:连接错误、超时、429 与 5xx 这类暂时性失败最多尝试 3 次(间隔很短);其它 4xx 视为永久失败,不会重试。每次尝试,WAthink 都会记录状态码、耗时、响应体与错误文本,并更新端点的成功、失败计数与最近触发时间。

连续三次失败后,端点会被自动标记为 failing(异常)。异常期间仍会继续接收事件 — 该标记只是健康警告,不是暂停。要真正停止投递,请暂停端点。

状态含义
active已启用且未被标记 — 正常投递。
failing已启用,但最近的投递出错。仍会接收事件。
paused已禁用 — 完全不接收事件。
让接收端保持幂等且快速。立即返回 2xx,把耗时工作放在你自己的服务端异步处理。用信封中的 id 去重 — 同一逻辑事件可能被重复投递,上游重试也可能产生不止一条通知。接收端过慢会抬高你的 p95 延迟,并可能导致 failing 标记。

监控与分析

Webhooks 索引页提供工作区内所有端点的实时健康概览:

  • Endpoints — 已配置总数,以及活跃 / 已暂停计数。
  • Events fired (24h) — 过去 24 小时的投递数。
  • Success rate — 过去 24 小时 2xx 响应的百分比。
  • Latency p95 — 第 95 百分位投递延迟。
  • Event mix — 24 小时内按量排序的头部事件。
  • Recent deliveries — 最新尝试及其状态码的实时列表。

打开单个端点会显示最近 7 天的投递:每日成功/失败图表、状态码分桶(2xx / 4xx / 5xx / 其它)、p95 延迟、重试与失败计数,以及带响应详情的近期投递表格。索引页可按状态(all / active / paused / failing)筛选,并按 URL、名称或事件搜索。

管理与测试触发端点

对每个端点,你可以:

  • Test fire — 发送一条示例负载(一个 test_fire 事件,data.message 中带一段友好问候),并像真实事件那样显示实时的状态码与延迟。它也会用你的密钥为请求签名,因此能验证包含签名校验在内的完整链路。
  • Toggle — 暂停或恢复端点。
  • Edit — 修改 URL、事件、密钥、方法、名称或环境。
  • Delete — 删除端点并停止向它的一切投递。
提示。编辑端点后,先运行 Test fire,确认接收端仍接受该负载与签名,再依赖真实事件。成功的测试触发会记录一条正常的投递记录,因此也会出现在分析中。

入站与出站

这是两个完全不同的东西 — 请分清:

出站 Webhook(本页)入站 Webhook(Incoming)
方向WAthink → 你的系统外部系统 → WAthink
由谁配置你,按工作区,在 More → Webhooks 下你,在 Webhooks → Incoming 中生成捕获 URL
携带内容你订阅的生命周期事件外部系统 POST 的任意请求体(订单、表单提交、告警等)
端点你拥有的任意 URLWAthink 提供的一个入站捕获 URL

入站 Webhook 用于把外部系统接入 WAthink。在 Webhooks → Incoming 中生成一个捕获 URL,把它交给外部系统(Zapier、表单、你自己的应用等),对方按该地址 POST:

  • 捕获与记录。URL 中的 40 字符随机 token 就是它的密码,请妥善保密。WAthink 会记录每个到达请求的方法、来源 IP、Content-Type、请求头与请求体(不会保存 auth / cookie 请求头),每个 URL 保留最近 100 条请求,方便你在页面中检查与排错。它接受 POST / GET / PUT / PATCH。
  • 转发(Relay)。打开转发后,每个收到的请求都会以相同请求体与 Content-Type 重新发送到你自己的目标 URL,无需改动外部系统。
  • 保存为联系人。把负载中的字段映射到电话、姓名与邮箱(支持 data.phone 这类点号路径,留空则自动识别常见键名),可设置默认国家区号、标签,并可选把新联系人加入一条流程。命中的请求会在捕获列表中标记为 lead saved。
  • 发送模板。选择本工作区一个已连接号码作为发送方,再选择一条已保存的模板,并把收件人号码字段与各模板变量映射到负载字段;每个到达的请求都会触发一次模板发送,走与收件箱相同的发送通道。
入站 WhatsApp 消息不需要任何回调配置。当前部署使用 WhatsApp 协议连接:入站消息由辅助服务(连接运行服务)直接投递到 WAthink,无需向任何服务商注册回调地址。入站捕获 URL 只用于把外部系统的事件接入 WAthink;入站 Webhook 与出站一样属于付费套餐功能。
仍需进一步帮助?查看反馈与支持方式

文档目录

返回官网

搜索操作文档

正在准备文档索引…

↑ ↓ 切换结果 · Enter 打开Esc 关闭