Ringhum.

开发者

Webhook

在通话结束、留言被记录、预约、订单和预订发生变化,或营销活动结束时接收带签名的 HTTPS 通知,并验证每条通知确实来自 Ringhum。

2 分钟阅读 更新于 24 九月 2026

本页内容

webhook 会在您工作区中发生某件事的那一刻,向您的服务器发送一个 HTTPS 请求。使用 webhook 而不是轮询 API:当通话结束时,您会立即收到摘要、处理结果、收集到的细节和转录记录。每次投递都使用只有您和 Ringhum 知道的密钥进行签名,因此您的服务器可以拒绝任何非来自 Ringhum 的请求。

添加端点

只有工作区所有者管理员可以添加、测试和移除端点。

  1. 在侧边栏打开开发者
  2. Webhook 卡片中,点击添加端点
  3. 输入端点网址,必须以 https:// 开头。
  4. 事件下,勾选您需要的事件,call.ended 已默认为您勾选。
  5. 点击添加端点
  6. 从绿色框中复制签名密钥(以 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.endedmessage.taken:上方的通话字段。
  • call.startedcall.transferredcall_iddirectionfromtoassistant_idstatusstarted_at
  • appointment.*appointment_idtitlestatusstarts_atends_attimezonecustomer(姓名、电话、邮箱)、contact_idservicestaffcall_idnotes
  • order.*order_idnumberstatusfulfillmentcustomeraddressitems(含选项和价格)、currencysubtotalfeetotalsourcecall_id,以及取消时的 cancel_reason
  • reservation.*reservation_idnumberstatusroomcheck_incheck_outnightsadultschildrenguestcurrencynightlytotalsource
  • campaign.completedcampaign_idname 以及该活动的进度统计。

注: 当助手在通话中完成预约时,您可能会收到两次 appointment.booked。一次是在预约创建时发送,包含预约字段;另一次是在通话摘要生成后发送,包含通话字段。请检查 data 中是否包含 appointment_idcall_id,并使用 id 字段来避免重复处理同一次投递。

验证签名

签名是使用您端点的签名密钥,对"时间戳 + 点号 + 原始请求体"计算得出的 HMAC-SHA256 值,以 v1= 加十六进制摘要的形式发送。

  1. 读取收到的原始请求体,不要先进行任何 JSON 解析。
  2. 构造字符串 {X-Ringhum-Timestamp}.{原始请求体}
  3. 使用您的密钥计算 HMAC-SHA256,并加上 v1= 前缀。
  4. 使用恒定时间比较将其与 X-Ringhum-Signature 进行比对。
  5. 如果时间戳距今超过五分钟,请拒绝该请求,以防止重放攻击。

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_atdata 中的 ID 来确定顺序。

Webhook 表格会显示每个端点最近一次的 HTTP 状态码和发送时间。失败的端点会保持活动状态,Ringhum 不会替您自动关闭它。

测试、暂停和移除

  • 发送测试会立即发送一个 test.ping 事件,并显示您端点返回的 HTTP 状态。
  • 启用开关可暂停某个端点,暂停期间发生的事件不会在之后补发。
  • 移除会删除该端点及其密钥。

常见问题

这与"集成"下的 Zapier、Make 和 n8n 应用有什么区别? 那些连接使用的是集成页面及其六种事件类型,请求体格式为 {"event", "workspace", "sent_at", "data"},当您设置密钥后,签名请求头为 X-Ringhum-Signature: sha256=…,是仅对请求体计算的 HMAC-SHA256。本文介绍的开发者 webhook 涵盖更多事件,并使用带时间戳的 v1= 签名。参见选择发送哪些内容

我的端点返回了 2xx,但我的代码没有收到任何内容。 请检查该端点是否勾选了相应事件、端点是否处于启用状态,以及您的防火墙是否允许来自互联网的请求。

为什么签名验证失败? 最常见的原因是请求体在计算哈希前被解析并重新编码过,请对收到的原始字节进行哈希计算。

仍未解决问题?

发送邮件至 [email protected],或给我们发消息。Team 和 Scale 套餐享有优先支持。

联系支持团队