Sign inGet Started

向 WhatsApp 群组发送消息

群组发送就是一条普通的 POST /v1/whatsapp/messages,只是 to 指定的是群组而非个人:一次请求、一条消息,群聊中的每位参与者都会收到并可以在其他人可见的地方回复。不同之处在于报告方式。消息会携带计数器,显示有多少人收到了消息,投递确认则按参与者逐一到达。

创建和管理群组与向群组发送消息是分开的。管理 WhatsApp 群组介绍了如何通过 API 创建群组并分享邀请链接,WhatsApp 群组介绍了群组的用途以及 WhatsApp 对其施加的限制。

前提条件

你需要一个具有 WhatsApp 写入权限的 API 密钥,以及一个 Active 状态群组的 ID(wag_…)。可以从 Groups 页面群组的 Details 选项卡中复制,从通过该群组收到的消息上的 to.group_id 中读取,或列出你的群组。

将示例中的群组 ID 替换为你自己的。使用 TypeScript、Python、Go 或 PHP SDK 指南为你的语言初始化客户端。对于 CLI 示例,请安装并认证 CLI,授予 WhatsApp 写权限。在 cURL 请求中使用与你的工作区区域对应的 API 主机。

1. 发送消息

将群组 ID 放入 to,不要设置 from。群组绑定到创建它时使用的商业号码,因此消息只能从该号码发出;指定发送者会返回 422 E15018。

const msg = await bird.whatsapp.send({
  to: "wag_01krdgeqcxet5s7t44vh8rt9mg",
  text: { body: "The route sheet for Tuesday is up." },
});
console.log(msg.id, msg.status);

API 返回 202,群组信息回显在 to.group_id 上,以及 status: accepted 和 recipient_count:发送被接受时群组中有多少人。该计数是第 3 步中所有内容的分母,并在此刻固定。在消息传输过程中通过邀请链接加入的人不会收到该消息,也不会改变计数。

2. 群组支持的内容

群组支持文本、图片、视频、音频、贴纸、文档、位置、联系人名片,以及你的工作区创建的除身份验证类别外任何类别的模板。两种内容会在消息创建或计费之前被拒绝,返回 422 E15052,因为 WhatsApp 不会将这两种内容投递到群聊中:

  • 任何交互式内容:回复按钮、列表菜单、链接按钮、轮播卡片,以及位置和联系信息请求。
  • 身份验证模板。 请将一次性验证码直接发送给参与者。

Bird 托管模板从 Bird 拥有的号码发送,该号码永远不是群组绑定的号码,因此向群组发送托管模板会返回 422 E15001。

自由格式内容仍然需要一个打开的客服服务窗口,群组有自己的服务窗口:任何参与者向群组发送消息都会为整个群组打开一个 24 小时窗口,而该参与者在群组外向你发送消息不会打开此窗口。窗口过期后,只有模板才能到达群组。

3. 跟踪扇出

检索消息以查看投递进度。三个计数器报告扇出情况:

字段报告内容
recipient_count接受时的参与者数,其余两个计数器的分母
delivered_countWhatsApp 已确认消息送达的人数,包括仅报告了已读的人
read_count已打开消息的人数

在群组消息中,status 报告的是每位收件人到达的最远状态:只有当 delivered_count 等于 recipient_count 时才会变为 delivered,在部分人已确认而其他人尚未确认时保持 sent。WhatsApp 消息没有 read 状态,因此已读通过 read_count 和 read_at 体现。delivered_at 和 read_at 取自第一个收件人,而非最后一个。failed 和 rejected 不按参与者区分,因为只有一次向 WhatsApp 的交接,也只有一种被拒绝的方式。

向一个尚无人加入的群组发送消息时,不会携带任何计数器,因为没有可报告的分母。因此用 to.group_id 而非计数器来区分群组消息和一对一消息。

要查看某条确认对应的是哪位参与者,请列出该消息的事件。群发消息会为每位参与者展开为最多一个 whatsapp.delivered 和最多一个 whatsapp.read,每个都在 recipient 中携带该参与者的电话号码、其业务范围用户 ID,或两者兼有。两者对任何人都不保证一定出现:如果参与者已在查看聊天,WhatsApp 会跳过送达回执;已读回执仅在对方打开消息时才会到达。统计实际收到的回执,而不是等待每位参与者各收到一条,总数请读取计数器。单个 whatsapp.sent 事件不携带 recipient:那是一次向 WhatsApp 的交接,不会指明任何人。whatsapp.delivered 和 whatsapp.read webhooks 携带相同的字段,这也是区分其他方面完全相同的回调的方式。

4. 读取一个群组的对话

将 group_id 传给消息列表以获取一个群组的双向消息记录:

for await (const msg of bird.whatsapp.list({ group_id: "wag_01krdgeqcxet5s7t44vh8rt9mg" })) {
  console.log(msg.id, msg.direction, msg.status);
}

入站群组消息读取时会在 from 上显示发送者,以及一个同时携带你的商业号码和 group_id 的 to:接收号码以它所在的群组为限定条件。to 和 from 都无法匹配群组,因此 group_id 是唯一能将列表缩小到单个群组的筛选条件。相同的消息也在控制台的WhatsApp 日志中。

费用

群组发送按发送 WhatsApp 消息中描述的两个组成部分计费,每个部分的定价方式有所不同。Bird 的费用按一次发送收取一次,按消息发出所用商业号码所在国家定价,因为群组可能跨越多个国家,没有单一的收件人国家。Meta 的份额按消息送达的每位参与者累计,每位按该参与者所在国家的普通一对一费率定价,因此 passthrough_amount 随着回执到达而增长。从 2026 年 10 月 1 日起,该份额还涵盖发送到群组的自由格式内容,Meta 按每位送达的参与者收费,从发送号码每月 1,000 条免费服务消息中扣除:2026 年 10 月定价变更。

故障排除

  • 404 (E15046):该群组 ID 未指向此工作区持有的任何群组。群组属于创建它的工作区,因此来自其他工作区的 ID 在此处找不到。
  • 409 (E15047):群组处于待处理、暂停、已删除或失败状态。只有 Active 状态的群组才能接收消息,群组在 WhatsApp 确认之前一直处于待处理状态。
  • 422 (E15018):移除 from。群组使用创建时绑定的号码发送。
  • 422 (E15052):交互式内容或身份验证模板。参阅群组支持的内容。
  • 422 (E15044):群组的服务窗口已关闭。发送模板,或等待参与者向群组发送消息。
  • status 停留在 sent:少于 recipient_count 位参与者已确认投递。查看消息的事件以了解哪些人尚未确认。

后续步骤