Sign inGet Started

WhatsApp 消息状态事件

Bird 为入站和出站 WhatsApp 消息记录事件。出站时间线展示发送返回 202 后发生的情况:接受、移交至 WhatsApp、投递、已读或失败。入站时间线记录 Bird 收到消息的时间。
本页介绍如何通过 API 读取该时间线。如需 Bird 在每个事件发生时将其推送到您的端点,请参阅消息状态 Webhook。回应(Reaction)有独立的历史记录,详见回应事件。

生命周期事件

事件按时间顺序排列。出站消息可能终止于 whatsapp.failed 或 whatsapp.rejected,其 whatsapp.read 事件仅在收件人打开消息时才出现。入站时间线从 whatsapp.received 开始,并可在您的工作区将消息标记为已读后记录 whatsapp.read。
事件含义
whatsapp.acceptedBird 接受了发送请求。这是 202 报告的结果。
whatsapp.sentBird 已将消息移交至 WhatsApp 网络。
whatsapp.deliveredWhatsApp 确认消息已投递至收件人的设备。
whatsapp.read收件人打开了消息。
whatsapp.failed消息未能投递。error.code 说明了阻止原因。
whatsapp.rejectedBird 在发送前拒绝了消息,未产生费用。
whatsapp.receivedBird 收到了来自联系人的入站消息。
适用的 delivered 或 read 回调可触发 Meta 的费用分成。WhatsApp 事件载荷不包含费用信息。使用 GET /v1/whatsapp/messages/{message_id} 回读消息以查看其费用。请参阅费用与计费。
将入站消息标记为已读会在其时间线中记录 whatsapp.read,但不会触发已读确认 webhook。入站消息保持其 received 状态,并在 WhatsApp 接受确认后记录 read_at。
whatsapp.read 不会更改消息的 status。已投递的消息仍保持 delivered;消息同时在 read_at 中记录已读。
whatsapp.delivered 可能被完全跳过。 当收件人的设备上已打开聊天窗口时,Meta 会报告已读而不报告投递,因此时间线显示为 whatsapp.accepted → whatsapp.sent → whatsapp.read,中间没有 whatsapp.delivered。应将 read 视为投递证明:等待 delivered 后才认为消息送达的消费者,恰好会卡在最快看到消息的收件人上;而仅根据 delivered 计算投递率会导致低估。在这种情况下,消息 status 保持 sent,因为只有投递回执才会推进状态。
仅已读的回调仍可触发适用的 Meta 费用。Bird 在投递和已读路径上使用同一个费用标识;缺少投递事件并不意味着 Meta 部分免费。请参阅费用与计费。
事件类型列表是开放的:新类型可能随时添加,因此请将未识别的值视为未来事件而非错误。

失败事件

whatsapp.failed 和 whatsapp.rejected 是终态。拒绝表示 Bird 在将消息发送至 WhatsApp 之前阻止了它,因此不会产生费用。原因包括被屏蔽或已退订的收件人、钱包余额不足或目标地址未配置价格。失败表示消息未能投递,error.code 说明了决策方。大多数错误码携带的是 WhatsApp 的判定,映射自其报告的代码。internal_error 是例外:它记录缺少可用的发送方凭据或处理重试已耗尽。不确定的传输尝试并不能证明 Meta 从未收到请求。meta_error_code 在可用时包含 WhatsApp 的代码,而 internal_error 类型的失败在设计上不包含代码。
两种事件都包含一个 error 对象,该对象带有稳定的 Bird code、可读的 description、可选的 meta_error_code 以及 occurred_at。该对象仅在这些事件类型的 API 记录和 webhook 载荷中出现。

从 API 读取事件

GET /v1/whatsapp/messages/{message_id}/events 按时间顺序返回时间线。有界列表不分页。读取事件需要具有 whatsapp:read 的 API 密钥:
const { data } = await bird.whatsapp.listEvents("wa_abc123");
for (const event of data) console.log(event.type, event.occurred_at);
一条经历了接受、发送、投递和已读的消息会返回四个事件:
代码示例
{
  "data": [
    {
      "id": "ev_01ky7q6a1fejfbvs0myn41hj41",
      "occurred_at": "2026-07-23T14:48:34.71Z",
      "type": "whatsapp.accepted"
    },
    {
      "id": "ev_01ky7q6a2denvtd6jg1vqwmg13",
      "occurred_at": "2026-07-23T14:48:35.671Z",
      "type": "whatsapp.sent"
    },
    {
      "id": "ev_01ky7q6a2zff9r2qm74mmg1g6z",
      "occurred_at": "2026-07-23T14:48:36.642Z",
      "type": "whatsapp.delivered"
    },
    {
      "id": "ev_01ky7q6c21frssf0vj8h50qysw",
      "occurred_at": "2026-07-23T14:48:38.65Z",
      "type": "whatsapp.read"
    }
  ]
}
传入 type 可返回一种精确的公共事件类型,例如 ?type=whatsapp.failed 或 ?type=whatsapp.read。省略该参数则返回完整时间线。
该时间线与您在 WhatsApp 日志页面打开消息时看到的内容相同。
Bird 仪表板中的 WhatsApp 消息详情面板,打开了一条已投递的 bird_delivery_update 消息:Events 标签页显示每条消息的生命周期时间线,包含 Accepted、Sent、Delivered 和 Read,各附有经过时间和时间戳,消息列表在背景中变暗

后续步骤