Skip to main content
Webhook 把事件推送到你的服务器,实时事件流把事件推送到你的前端:一条长连接的 GET 请求即可实时收到每个事件;连接中断时还能保证重放。 用事件流保持仪表盘实时更新(余额、入金到账、出金结算、卡授权、面向管理员的 KYT 警报); 用 Webhook 处理那些即使用户关闭浏览器也必须完成的逻辑。两个通道传递 完全相同的事件、相同的载荷和相同的 event_id,因此你只需要写一套映射。

打开事件流

该端点使用与其余 API 相同的 Authorization: Bearer 凭证,因此浏览器原生的 EventSource(无法发送自定义请求头)不适用。请使用 fetch 并以流的方式读取响应体:
响应
每个事件帧包含三行:

无缝重连

连接中断后,携带最后处理的游标重新连接。服务端会先从日志中重放你错过的事件,再恢复实时推送, 因此不稳定的网络也不会丢事件。
重放上限为 1000 条事件。如果断线时间过长、错过的事件更多,事件流会发送控制事件 replay_truncated;此时应使用 ?snapshot=trueGET /v1/events/history 进行对账,而不要假设数据连续。

初始快照

?snapshot=true 打开会先发送当前状态,然后才是增量。这消除了经典的竞态问题 (“先读 REST 接口再订阅,中间发生的事件就丢了”):游标是在订阅已经建立之后取的, 不会有任何遗漏。
快照是绝对状态而非增量,重复应用不会产生副作用。账户凭证会得到 balances (字段与 GET /v1/balances 相同);组织管理员还会得到运营 health 计数。

按事件类型过滤

?types= 用于缩小接收范围。它只能收窄凭证已经可见的范围,绝不会扩大。未知类型会返回 400 invalid_event_type,而不是让你一直等待永远不会到达的事件。

范围:账户与组织管理员

一个账户永远看不到其他账户的事件,也看不到组织级合规视图。事件流绝不会返回该凭证通过 REST 无法读取的字段。

控制事件

除业务事件外,事件流还会发送协议事件。除 snapshot 外,它们不带 id:,因此不会推进重放游标。 每 20 秒会发送一条 : ping 注释,避免代理断开空闲连接——请忽略以 : 开头的行。

限制

超出并发上限会返回 429 too_many_streams;超出开流配额会返回 429 rate_limited——该配额统计尝试次数,因此即使没有打开任何流,紧密循环 重连的客户端也会耗尽它。请始终遵守 retry:(3 秒)并配合指数退避。

可查询的历史

驱动事件流的同一份日志也可以通过 REST 读取——适用于审计、“我错过了什么”视图,或重放被截断时的对账。
按公开 id 查询单个事件:
事件日志保留 90 天。它是通知缓冲区,不是财务记录:余额、入金、出金、转账和分类账分录 均不可变,会在各自的端点和对账单中按监管要求的期限继续保留。

错误

完整列表见错误

常见问题

不可以。事件流只在页面打开时存在;Webhook 即使无人在线也会送达你的后端。UI 使用事件流, 触发业务逻辑(对账、记账、通知)的部分使用 Webhook。
会。重连后的重放可能重复投递边界事件,而且两个通道(Webhook 与事件流)共享同一个 event_id。请按 event_id 去重,并把每个载荷视为绝对状态。
这是设计使然。没有寿命上限的流会掩盖连接泄漏。服务端会先发送 reconnect 控制事件, 携带 Last-Event-ID 重连即可从中断处继续。
不需要。事件流无需配置:它会推送凭证可见的全部事件。Webhook 订阅只控制发往你服务器的 HTTP 投递。
检查你的 HTTP 客户端是否缓冲了响应(在 fetch 中应以流方式读取 res.body,而不是等待 res.text()),以及你自己的代理是否缓冲了 text/event-stream。CBPay 侧已关闭缓冲。
可以,使用 ?account_id=。该过滤器只在你自己的组织内生效;其他情况返回 404。
最后修改于 2026年7月26日