Sign inGet started

Realtime webhooks

发布(Publishing)将事件推送给客户端。Webhooks 则方向相反:当频道上发生事件时,Realtime 边缘节点会向你的端点 POST 一个签名事件。
你已经可以通过查询频道状态按需读取频道状态。Webhooks 让你在变更发生时立即收到通知,无需轮询:例如客户端订阅、成员关闭最后一个标签页、一个客户端向另一个客户端发送光标位置。

五个事件组

订阅一个或多个事件组:
回答的问题投递内容
realtime.channel_existence是否有人在监听?realtime.channel_occupiedrealtime.channel_vacated
realtime.presence谁在这里?realtime.member_addedrealtime.member_removed
realtime.connection_count有多少连接?realtime.connection_count
realtime.cache_channels该频道是否需要数据?realtime.cache_miss
realtime.client_events客户端在发送什么?每个客户端事件对应一个事件,以该事件命名
channel_existence 只报告频道生命周期的两个边界:从零连接变为一个连接时发送 channel_occupied,最后一个连接离开时发送 channel_vacated。中间的订阅者加入和离开不会产生任何事件,因此它是判断是否值得发布的低成本方式。
connection_count 需要在应用上启用连接计数。如果该设置被禁用,已订阅的组不会产生任何事件。

订阅端点

打开 Webhooks,创建或编辑一个端点,找到 Realtime events 部分。选择一个 Realtime 应用和要接收的组。
平台事件订阅在整个工作区范围内生效,而 realtime.* 订阅属于单个应用。创建后无法更改端点的 Realtime 应用,但可以更新其订阅的组。
平台事件和 Realtime 事件可以共用一个端点。例如,一个端点可以同时订阅 email.bouncedrealtime.presence。两者使用同一个端点签名密钥。
Realtime 组目前仅支持在仪表板中配置。包含 realtime.* 事件类型的公开 POST /v1/webhooks 请求会被拒绝,因此请在仪表板中配置这些订阅。

投递的结构

每个 POST 包含一个事件,使用 Bird 的标准 webhook 信封格式:
代码示例
{
  "data": { "channel": "presence-room-1", "member_id": "u_42" },
  "timestamp": "2026-07-31T09:00:00Z",
  "type": "realtime.member_added"
}
type 标识所投递的事件。例如,realtime.presence 组投递 realtime.member_addedrealtime.member_removed
投递的 typedata 字段
realtime.channel_occupiedchannel
realtime.channel_vacatedchannel
realtime.member_addedchannelmember_id
realtime.member_removedchannelmember_id
realtime.connection_countchannelconnection_count
realtime.cache_misschannel
realtime.<client event>channel_nameeventdataconnection_id,presence 频道还包含 member_id
对于客户端事件,事件后缀由客户端选择。触发 client-typing 会产生 realtime.client-typingdata.event 包含 client-typing。参阅客户端事件

验证投递

Realtime webhooks 遵循 Standard Webhooks 规范,并包含 webhook-idwebhook-timestampwebhook-signature 请求头。使用端点的签名密钥进行验证。
代码示例
import { BirdClient } from "@messagebird/sdk";

const bird = new BirdClient({
  apiKey: process.env.BIRD_API_KEY,
  webhooks: { secret: process.env.BIRD_WEBHOOK_SECRET },
});

app.post("/webhooks/bird", express.raw({ type: "*/*" }), (req, res) => {
  const event = bird.webhooks.unwrap(req.body, req.headers);
  res.sendStatus(200);

  switch (event.type) {
    case "realtime.channel_vacated":
      stopExpensiveWorkFor(event.data.channel);
      break;
    case "realtime.member_removed":
      markAway(event.data.member_id);
      break;
  }
});
请验证原始请求体,因为解析并重新序列化 JSON 可能会改变已签名的字节。在 default 分支中处理未知事件类型,以免新类型导致端点出错。参阅验证 webhook 签名了解完整约定。

Presence 事件按成员计数

member_addedmember_removed 跟随身份标识,因此与连接不是一一对应的。在三个标签页中打开你的应用的用户算作一个成员:
发生的事件Webhook
第一个标签页订阅realtime.member_added
第二个标签页订阅
第二个标签页关闭
最后一个标签页关闭realtime.member_removed
使用 member_removed 检测某个身份标识何时离开频道。单个会话结束时,如果另一个会话仍然存在,不会触发该事件。要跟踪连接,请订阅 realtime.connection_count。参阅 Presence 频道

Realtime webhook 投递行为

Realtime 投递遵循以下重试和可见性规则:
  • 在持久化接收事件后立即返回 2xx,然后异步处理。
  • 如果端点返回非 2xx 响应,Realtime 会以指数退避方式重试,最长持续 5 分钟。
  • Realtime 事件不支持重放,也不会出现在端点的投递尝试日志中。
  • 暂停端点会停止 Realtime 投递以及所有其他投递,重新启用后恢复。
投递是无序的,且不提供逐事件回执。将它们视为变更通知。使用查询频道状态在事件延迟或丢失后获取当前状态。

后续步骤