开发者
Webhook
在通话结束、留言被记录、预约、订单和预订发生变化,或营销活动结束时接收带签名的 HTTPS 通知,并验证每条通知确实来自 Ringhum。
2 分钟阅读 更新于 24 九月 2026
webhook 会在您工作区中发生某件事的那一刻,向您的服务器发送一个 HTTPS 请求。使用 webhook 而不是轮询 API:当通话结束时,您会立即收到摘要、处理结果、收集到的细节和转录记录。每次投递都使用只有您和 Ringhum 知道的密钥进行签名,因此您的服务器可以拒绝任何非来自 Ringhum 的请求。
添加端点
只有工作区所有者和管理员可以添加、测试和移除端点。
- 在侧边栏打开开发者。
- 在 Webhook 卡片中,点击添加端点。
- 输入端点网址,必须以
https://开头。 - 在事件下,勾选您需要的事件,
call.ended已默认为您勾选。 - 点击添加端点。
- 从绿色框中复制签名密钥(以
whsec_开头)并保存到您的服务器上,点击完成。
重要: 签名密钥仅显示一次。如果丢失,请移除该端点并重新添加以获取新密钥。
您可以根据需要添加任意数量的端点,webhook 覆盖工作区中的每个助手。您也可以通过 API 使用 POST /webhooks 和具有写入权限的密钥来管理端点。
事件
| 事件 | 发送时机 |
|---|---|
call.started |
助手接听了一通电话 |
call.ended |
通话结束并已生成摘要(包含转录记录和摘要) |
call.transferred |
通话已转接给人工 |
message.taken |
助手记录了留言 |
appointment.booked |
助手完成了预约 |
appointment.rescheduled |
预约被改期 |
appointment.cancelled |
预约被取消 |
order.created |
已下单(通过助手、手动或 API) |
order.updated |
订单状态发生变化 |
order.cancelled |
订单被取消 |
reservation.created |
已预订客房(通过助手、手动或 API) |
reservation.updated |
预订状态发生变化(已确认、已入住、已退房、未到) |
reservation.cancelled |
预订被取消 |
campaign.completed |
外呼营销活动完成了整个列表的拨打 |
test.ping |
您点击了发送测试 |
一次投递的内容
每次投递都是一个带 JSON 请求体和以下请求头的 POST 请求:
POST https://example.com/hooks/ringhum
Content-Type: application/json
User-Agent: Ringhum-Webhooks/1.0
X-Ringhum-Event: call.ended
X-Ringhum-Timestamp: 1789250000
X-Ringhum-Signature: v1=5f1a…
{
"id": "evt_8f2k…",
"type": "call.ended",
"created_at": "2026-09-24T14:03:11+00:00",
"data": {
"call_id": 4812,
"direction": "inbound",
"from": "+14155550132",
"to": "+14155550100",
"assistant_id": 3,
"status": "completed",
"outcome": "message_taken",
"sentiment": "neutral",
"duration_seconds": 94,
"summary": "Caller asked for a quote for a kitchen repair…",
"extracted": { "name": "Dana Lee", "reason": "Quote" },
"transcript": [
{ "role": "assistant", "content": "Hello, you've reached…" },
{ "role": "user", "content": "Hi, I'd like a quote…" }
]
}
}
data 对象的内容取决于事件类型:
call.ended和message.taken:上方的通话字段。call.started和call.transferred:call_id、direction、from、to、assistant_id、status和started_at。appointment.*:appointment_id、title、status、starts_at、ends_at、timezone、customer(姓名、电话、邮箱)、contact_id、service、staff、call_id和notes。order.*:order_id、number、status、fulfillment、customer、address、items(含选项和价格)、currency、subtotal、fee、total、source、call_id,以及取消时的cancel_reason。reservation.*:reservation_id、number、status、room、check_in、check_out、nights、adults、children、guest、currency、nightly、total和source。campaign.completed:campaign_id、name以及该活动的进度统计。
注: 当助手在通话中完成预约时,您可能会收到两次
appointment.booked。一次是在预约创建时发送,包含预约字段;另一次是在通话摘要生成后发送,包含通话字段。请检查data中是否包含appointment_id或call_id,并使用id字段来避免重复处理同一次投递。
验证签名
签名是使用您端点的签名密钥,对"时间戳 + 点号 + 原始请求体"计算得出的 HMAC-SHA256 值,以 v1= 加十六进制摘要的形式发送。
- 读取收到的原始请求体,不要先进行任何 JSON 解析。
- 构造字符串
{X-Ringhum-Timestamp}.{原始请求体}。 - 使用您的密钥计算 HMAC-SHA256,并加上
v1=前缀。 - 使用恒定时间比较将其与
X-Ringhum-Signature进行比对。 - 如果时间戳距今超过五分钟,请拒绝该请求,以防止重放攻击。
Node.js:
const crypto = require('crypto');
function isValid(req, rawBody, secret) {
const ts = req.header('X-Ringhum-Timestamp');
const sig = req.header('X-Ringhum-Signature') || '';
const expected = 'v1=' + crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
return fresh && sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
PHP:
$ts = $_SERVER['HTTP_X_RINGHUM_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_RINGHUM_SIGNATURE'] ?? '';
$expected = 'v1=' . hash_hmac('sha256', $ts . '.' . file_get_contents('php://input'), $secret);
if (! hash_equals($expected, $sig) || abs(time() - (int) $ts) > 300) {
http_response_code(400);
exit;
}
响应、超时与重试
- 返回任意
2xx状态码即表示确认收到,请在响应后再执行耗时较长的操作。 - Ringhum 最多等待 10 秒来接收您的响应。
- 如果您的端点没有返回
2xx,投递总共会尝试最多 3 次:立即尝试一次,约 10 秒后再次尝试,最后约 60 秒后再尝试一次,之后会被放弃。 - 投递可能不按顺序到达,请使用
created_at和data中的 ID 来确定顺序。
Webhook 表格会显示每个端点最近一次的 HTTP 状态码和发送时间。失败的端点会保持活动状态,Ringhum 不会替您自动关闭它。
测试、暂停和移除
- 发送测试会立即发送一个
test.ping事件,并显示您端点返回的 HTTP 状态。 - 启用开关可暂停某个端点,暂停期间发生的事件不会在之后补发。
- 移除会删除该端点及其密钥。
常见问题
这与"集成"下的 Zapier、Make 和 n8n 应用有什么区别? 那些连接使用的是集成页面及其六种事件类型,请求体格式为 {"event", "workspace", "sent_at", "data"},当您设置密钥后,签名请求头为 X-Ringhum-Signature: sha256=…,是仅对请求体计算的 HMAC-SHA256。本文介绍的开发者 webhook 涵盖更多事件,并使用带时间戳的 v1= 签名。参见选择发送哪些内容。
我的端点返回了 2xx,但我的代码没有收到任何内容。 请检查该端点是否勾选了相应事件、端点是否处于启用状态,以及您的防火墙是否允许来自互联网的请求。
为什么签名验证失败? 最常见的原因是请求体在计算哈希前被解析并重新编码过,请对收到的原始字节进行哈希计算。
相关文章
API 密钥与权限范围
在开发者页面创建和撤销 API 密钥,选择读取或写入权限,并了解 Ringhum REST API 的基础知识——基础网址、身份验证、分页、错误与速率限制。
将 Ringhum 连接到 Claude 及其他 AI 工具(MCP)
在 Claude、ChatGPT、Cursor、VS Code 等支持模型上下文协议(MCP)的 AI 应用中将 Ringhum 添加为连接器,选择只读或读写权限,并断开应用连接。
选择发送哪些内容
为每个已连接应用选择接收哪些通话、收件箱事项、预约和订单,并将通话更新限制为需要有人处理的通话。
连接应用
如何将 Slack、CRM、客服工单系统、任务工具、电子表格、店铺或日历连接到 Ringhum、每个应用使用哪种连接方式,以及如何检查连接是否正常。
仍未解决问题?
发送邮件至 [email protected],或给我们发消息。Team 和 Scale 套餐享有优先支持。