---
title: "管理 WhatsApp 群组"
description: "通过 API 创建 WhatsApp 群组，等待 WhatsApp 确认，分发邀请链接，处理加入请求，以及置顶、重命名或删除群组。"
canonical: "https://bird.com/zh-sg/wendang/guides/whatsapp/groups/management"
---

# 管理 WhatsApp 群组

[**Groups**](https://bird.com/dashboard/w/whatsapp/groups) 页面能做的一切，`/v1/whatsapp/groups` 下的十二个操作同样能做，因此群组的整个生命周期都可以用代码完成：创建群组、等待 WhatsApp 确认、分发邀请链接、决定谁能加入、维护群组详情和置顶消息，以及在对话结束后删除群组。

本页的每个调用都受两件事影响。**没有人可以被直接添加到群组**，因此邀请链接是唯一的加入方式，邀请操作发生在 API 之外。**大多数变更在 WhatsApp 端生效，而不是在响应中体现**，所以接受变更的调用并不是告知你变更已生效的调用；[变更如何生效](#变更如何生效)对每个适用的操作统一说明了这一点。

[WhatsApp 群组](/docs/guides/whatsapp/groups)介绍了群组的用途以及在控制面板中的相同生命周期。[向 WhatsApp 群组发送消息](/docs/guides/whatsapp/groups/sending)介绍了如何向群组发消息。

## 前提条件

你需要一个具有 `whatsapp_management` 访问权限的 API 密钥：本页的读取操作需要 read 级别，其他操作需要 write 级别。[用户、团队和角色](/docs/guides/users-teams-roles)介绍了如何授予权限。

你还需要一个持有 Official Business Account 状态的商业号码，WhatsApp 要求群组管理员具备该状态，[创建群组之前](/docs/guides/whatsapp/groups#before-you-create-a-group)介绍了如何获取。`GET /v1/whatsapp/numbers` 以 `is_official_business_account` 形式按号码报告该状态，因此请从那里读取，而不是通过 `412` 来发现。该标志截至号码的 `meta_synced_at`，因此几分钟前刚连接的号码可能尚未被回读。

使用 [TypeScript](/docs/sdks/typescript)、[Python](/docs/sdks/python)、[Go](/docs/sdks/go) 或 [PHP](/docs/sdks/php) SDK 指南为你的语言初始化客户端。对于 CLI 示例，请[安装并认证 CLI](/docs/cli#authenticate)。cURL 示例使用的是美国主机；如果你的密钥以 `bk_eu1_` 开头，请改为调用 `https://eu1.platform.bird.com`。SDK 会从你的密钥中读取区域，因此无需设置主机。

## 1. 创建群组

创建操作指定管理号码和主题，不指定其他人。有两个选项在群组的整个生命周期内固定，之后无法更改：号码，以及 `join_approval_mode`，它决定打开邀请链接时是直接加入（`auto_approve`，默认值）还是发起一个需要你决定的请求（`approval_required`）。

> **Note:** creating a group needs a business number with Official Business Account status, the blue check mark WhatsApp puts next to a business name in the chat. [WhatsApp Official Business Account](/docs/knowledge-base/whatsapp/official-business-account) covers what Meta requires and how to request it.

**TypeScript**

```typescript
const group = await bird.whatsapp.groups.create({
  whatsapp_number_id: "wan_01krdgeqcxet5s7t44vh8rt9mg",
  subject: "Norwood Fleet — Tuesday route",
  join_approval_mode: "approval_required",
});
console.log(group.id, group.status); // pending; read it back for the invite link
```

Examples: [TypeScript](/zh-sg/wendang/guides/whatsapp/groups/management.ts.md) · [Python](/zh-sg/wendang/guides/whatsapp/groups/management.py.md) · [Go](/zh-sg/wendang/guides/whatsapp/groups/management.go.md) · [PHP](/zh-sg/wendang/guides/whatsapp/groups/management.php.md) · [CLI](/zh-sg/wendang/guides/whatsapp/groups/management.cli.md) · [cURL](/zh-sg/wendang/guides/whatsapp/groups/management.curl.md)

API 返回 `202`，此时群组处于 `status` `pending` 状态且没有 `invite_link`：WhatsApp 会在确认群组时签发链接。主题最多 128 个字符，可选的 `description` 最多 2,048 个字符，两者都会展示给打开链接的人，因此请按群组用途命名，而非用作内部引用。

## 2. 等待 WhatsApp 确认

反复读取群组，直到其 `status` 离开 `pending`。无论状态如何，读取都返回 `200`，因此请根据 `status` 分支，而非根据调用是否成功。

**TypeScript**

```typescript
const group = await bird.whatsapp.groups.get("wag_01krdgeqcxet5s7t44vh8rt9mg");
console.log(group.status, group.invite_link);
```

Examples: [TypeScript](/zh-sg/wendang/guides/whatsapp/groups/management.ts.md) · [Python](/zh-sg/wendang/guides/whatsapp/groups/management.py.md) · [Go](/zh-sg/wendang/guides/whatsapp/groups/management.go.md) · [PHP](/zh-sg/wendang/guides/whatsapp/groups/management.php.md) · [CLI](/zh-sg/wendang/guides/whatsapp/groups/management.cli.md) · [cURL](/zh-sg/wendang/guides/whatsapp/groups/management.curl.md)

可能返回五种状态，其中只有一种表示可以使用的群组：

| 状态        | 含义                                                               |
| ----------- | ------------------------------------------------------------------ |
| `pending`   | WhatsApp 尚未确认群组。`invite_link` 为 null，此处没有可分享的内容 |
| `active`    | 群组已存在，邀请链接有效，可以接收消息和变更                       |
| `suspended` | WhatsApp 停止了群组中的活动。只有 WhatsApp 才能解除此状态          |
| `deleted`   | 群组已被删除，但仍可读取，因此已存储的引用仍可解析                 |
| `failed`    | WhatsApp 拒绝了创建请求，这是终态                                  |

`failed` 是脱离 `pending` 的另一条路径，`last_operation.last_error.description` 携带了 WhatsApp 自身给出的原因。切勿对同一群组重试失败的创建：请创建新群组，并修改被拒绝的内容。

## 3. 让用户加入群组

通过任何已能触达对方的渠道，将群组的 `invite_link` 发送给你想邀请的人。没有任何操作可以直接添加参与者，因此链接是唯一的入口，加入与否由他们自己决定。持有链接的人都可以加入，所以请将它当作凭据对待：[WhatsApp 群组](/docs/guides/whatsapp/groups#invite-people-to-the-group) 介绍了链接的传播范围。

在 `auto_approve` 群组中，持有链接的人直接加入，无需审批。在 `approval_required` 群组中，打开链接会产生一个加入请求。列出等待中的请求，然后分批处理，每批最多 50 个：

**TypeScript**

```typescript
const waiting = [];
for await (const request of bird.whatsapp.groups.joinRequests.list(
  "wag_01krdgeqcxet5s7t44vh8rt9mg",
)) {
  waiting.push(request.id);
}
const result = await bird.whatsapp.groups.joinRequests.approve("wag_01krdgeqcxet5s7t44vh8rt9mg", {
  join_request_ids: waiting.slice(0, 50),
});
console.log(result.decided.length, result.failed.length);
```

Examples: [TypeScript](/zh-sg/wendang/guides/whatsapp/groups/management.ts.md) · [Python](/zh-sg/wendang/guides/whatsapp/groups/management.py.md) · [Go](/zh-sg/wendang/guides/whatsapp/groups/management.go.md) · [PHP](/zh-sg/wendang/guides/whatsapp/groups/management.php.md) · [CLI](/zh-sg/wendang/guides/whatsapp/groups/management.cli.md) · [cURL](/zh-sg/wendang/guides/whatsapp/groups/management.curl.md)

WhatsApp 对每个请求独立处理，因此一个批次可以部分生效：响应将 `decided` 与 `failed` 分开列出，每个失败都在 `error.description` 中携带 WhatsApp 给出的原因。请读取响应而非仅看状态码。拒绝通常是因为当事人尚未接受 WhatsApp 的最新条款，重试无法解决此问题。

批准的人数超过群组剩余容量时，调用不会被拒绝：能容纳的请求会被处理，其余的在 `failed` 中返回，每个都说明该批准会使群组超过[参与者上限](/docs/guides/whatsapp/groups#what-whatsapp-limits)。拒绝操作同理，通过 `POST /v1/whatsapp/groups/{group_id}/join-requests/batch-reject` 返回。当事人自行取消请求也会使其从列表中消失，因此一个刚才还有效的 ID 到你使用时可能返回 `422` [`E15051`](/docs/api/errors/E15051)。

50 是 Bird 对单次请求的自身限制，而非 WhatsApp 的限制，因此拒绝操作不受群组可容纳人数的约束。

### 监听到达的加入请求

订阅 `whatsapp.group.join_request_created` 和 `whatsapp.group.join_request_revoked`，即可在有人申请加入或取消申请时收到通知，而无需轮询列表。如果一个请求在两次列表读取之间被提出并取消，列表中不会留下任何痕迹，因此这些事件是发现它的唯一途径。每个事件都携带批量操作所需的 `join_request.id`，你可以直接据此做出决定。[WhatsApp 群组 webhook](/docs/guides/whatsapp/webhooks/groups) 提供了两种载荷及所有字段的说明。

### 轮换邀请链接

轮换会签发一个新链接，并使该群组之前的所有链接失效，因此仍持有旧链接的人无法加入。当链接传播范围超出预期，或移除了不希望其重新加入的人时，执行轮换。新链接会在调用本身的响应中返回，响应状态为 `200`：

**TypeScript**

```typescript
const link = await bird.whatsapp.groups.inviteLink.rotate("wag_01krdgeqcxet5s7t44vh8rt9mg");
console.log(link.invite_link); // every earlier link has stopped working
```

Examples: [TypeScript](/zh-sg/wendang/guides/whatsapp/groups/management.ts.md) · [Python](/zh-sg/wendang/guides/whatsapp/groups/management.py.md) · [Go](/zh-sg/wendang/guides/whatsapp/groups/management.go.md) · [PHP](/zh-sg/wendang/guides/whatsapp/groups/management.php.md) · [CLI](/zh-sg/wendang/guides/whatsapp/groups/management.cli.md) · [cURL](/zh-sg/wendang/guides/whatsapp/groups/management.curl.md)

轮换不是读取当前链接的方式。群组本身携带其 `invite_link`，因此读取群组就是读取链接。

CLI 不会弹出确认提示，因此其破坏性命令改为要求 `--yes`：轮换链接、移除参与者、删除群组、取消置顶消息以及拒绝加入请求，缺少该参数时都会以 `confirmation_required` 拒绝。

## 变更如何生效

WhatsApp 对部分变更在响应中直接确认，对其余变更则通过 webhook 确认，状态码指示你看到的是哪一种：

| 操作                 | 响应状态 | 结果在哪里体现                                      |
| -------------------- | -------- | --------------------------------------------------- |
| 创建、更新、删除     | `202`    | 群组的 `last_operation`，在 WhatsApp 回报之后       |
| 移除参与者           | `202`    | 该参与者在 `participants` 中自己的 `last_operation` |
| 批准或拒绝加入请求   | `202`    | 响应本身中的 `decided` 和 `failed`                  |
| 轮换、置顶、取消置顶 | `200`    | 响应本身，即变更已生效                              |

对于前两行，`202` 表示请求已被接受，而非已生效。`last_operation.status` 在 WhatsApp 回报之前保持 `pending`，通常在数秒内完成，然后变为 `success` 或 `failed`，失败时 `last_error.description` 会携带原因。重新读取群组以查看实际生效的内容。

当一个操作处于 `pending` 状态时，对同一对象的另一个变更会返回 `409` [`E15054`](/docs/api/errors/E15054)。群组级变更共享群组的 `last_operation`，因此一个未完成的重命名会阻塞删除。每个参与者有各自独立的状态，因此同时移除多人时，每人有自己的状态和失败信息，只有该人的挂起移除才会阻塞对其的再次尝试。

两个 `409` 守护写操作，且 `status` 优先检查，因此非 `active` 状态的群组无论其 `last_operation` 如何，都会返回 [`E15047`](/docs/api/errors/E15047)。这对仍在创建中的群组尤为重要，因为它在两个维度上同时处于挂起状态。

每个写操作还需要一个 `Idempotency-Key` 请求头。[幂等性](/docs/guides/idempotency)介绍了如何安全地重试。

## 修改群组的主题、描述或图片

更新操作会改变参与者在群组顶部看到的内容。省略的字段保持不变；发送 `null` 可清除描述或图片，因为空字符串是 `422`，而不是清除的另一种方式。

**TypeScript**

```typescript
const group = await bird.whatsapp.groups.update("wag_01krdgeqcxet5s7t44vh8rt9mg", {
  subject: "Norwood Fleet — Wednesday route",
});
console.log(group.last_operation?.status); // pending until WhatsApp reports back
```

Examples: [TypeScript](/zh-sg/wendang/guides/whatsapp/groups/management.ts.md) · [Python](/zh-sg/wendang/guides/whatsapp/groups/management.py.md) · [Go](/zh-sg/wendang/guides/whatsapp/groups/management.go.md) · [PHP](/zh-sg/wendang/guides/whatsapp/groups/management.php.md) · [CLI](/zh-sg/wendang/guides/whatsapp/groups/management.cli.md) · [cURL](/zh-sg/wendang/guides/whatsapp/groups/management.curl.md)

WhatsApp 对每个字段独立应用，因此更新可能部分生效：一个字段被拒绝，其余字段仍生效。操作生效后，`last_operation.results` 会为更新所发送的每个字段携带一个条目，这样你可以将拒绝原因与引发拒绝的输入对应起来。

`profile_picture_url` 指定的是你工作区媒体库中的文件，而不是互联网上的任意地址，WhatsApp 接受至少 192×192 像素、最大 5 MB 的正方形 JPEG 图片。清除它会清除 Bird 存储的图片，但 WhatsApp 没有移除群组头像的操作，因此参与者会继续看到当前图片，直到另一张图片替换它。管理号码和 `join_approval_mode` 在创建时固定，无法在此处更改。

## 移除参与者

移除不可撤销。WhatsApp 会阻止被移除的人通过邀请链接重新加入群组，且该阻止跟随的是人而非链接，因此轮换链接也无法让其重新加入。由于没有与此操作配对的添加操作，一旦某人被移出该群组，没有任何方式能让其返回，要再次联系他们，只能创建另一个群组并邀请他们加入。

使用群组 `participants` 中列出的任一标识符来指定该人：其 `bsuid`（每人都有），或其 E.164 格式的 `phone_number`（仅在 WhatsApp 共享时才有）。在 URL 中，将开头的 `+` 百分号编码为 `%2B`，除非你的客户端已自动处理。

**TypeScript**

```typescript
const group = await bird.whatsapp.groups.participants.remove(
  "wag_01krdgeqcxet5s7t44vh8rt9mg",
  "+15550002222",
);
console.log(group.participants?.length);
```

Examples: [TypeScript](/zh-sg/wendang/guides/whatsapp/groups/management.ts.md) · [Python](/zh-sg/wendang/guides/whatsapp/groups/management.py.md) · [Go](/zh-sg/wendang/guides/whatsapp/groups/management.go.md) · [PHP](/zh-sg/wendang/guides/whatsapp/groups/management.php.md) · [CLI](/zh-sg/wendang/guides/whatsapp/groups/management.cli.md) · [cURL](/zh-sg/wendang/guides/whatsapp/groups/management.curl.md)

参与者的移除在其自身条目上保持 `pending` 状态，直到 WhatsApp 确认，且不会体现在 `success` 上：条目从 `participants` 中消失即表示移除成功。指定不在群组中的人会返回 `422` [`E15050`](/docs/api/errors/E15050)。

## 置顶消息

置顶会将群组自身的某条消息固定在聊天顶部，这样后来加入的人无需滚动查找对话中反复提及的内容。置顶持续 `duration_days`，范围为 1 到 30，默认为 7。

**TypeScript**

```typescript
const pin = await bird.whatsapp.groups.pins.create("wag_01krdgeqcxet5s7t44vh8rt9mg", {
  message_id: "wam_01kya19eknftrs2s6p82asmvnh",
  duration_days: 14,
});
console.log(pin.pinned_until);
```

Examples: [TypeScript](/zh-sg/wendang/guides/whatsapp/groups/management.ts.md) · [Python](/zh-sg/wendang/guides/whatsapp/groups/management.py.md) · [Go](/zh-sg/wendang/guides/whatsapp/groups/management.go.md) · [PHP](/zh-sg/wendang/guides/whatsapp/groups/management.php.md) · [CLI](/zh-sg/wendang/guides/whatsapp/groups/management.cli.md) · [cURL](/zh-sg/wendang/guides/whatsapp/groups/management.curl.md)

消息必须属于当前群组：其他群组的消息或一对一消息会返回 `422` [`E15053`](/docs/api/errors/E15053)。群组[同时最多只能有一定数量的置顶消息](/docs/guides/whatsapp/groups#what-whatsapp-limits)，超出上限时会取消最早的置顶而非失败；对已置顶的消息再次置顶会替换其过期时间。群组当前的置顶消息在群组本身上，字段为 `pinned_messages`。

WhatsApp 在天数到期后会自动取消置顶，因此仅在需要提前取消时才手动取消置顶。`DELETE /v1/whatsapp/groups/{group_id}/pinned-messages/{message_id}` 响应状态为 `200`，且重复调用是安全的：对群组中未被置顶的消息执行取消置顶不会产生任何变化，仍然返回 `200`。

## 删除群组

删除会在 WhatsApp 上移除群组。所有参与者（包括你的企业）都会失去访问权限，邀请链接也会停止工作。此操作不可撤销，要重新开展对话，只能创建新群组并发送其链接。

**TypeScript**

```typescript
const group = await bird.whatsapp.groups.delete("wag_01krdgeqcxet5s7t44vh8rt9mg");
console.log(group.last_operation?.status); // pending until WhatsApp confirms it
```

Examples: [TypeScript](/zh-sg/wendang/guides/whatsapp/groups/management.ts.md) · [Python](/zh-sg/wendang/guides/whatsapp/groups/management.py.md) · [Go](/zh-sg/wendang/guides/whatsapp/groups/management.go.md) · [PHP](/zh-sg/wendang/guides/whatsapp/groups/management.php.md) · [CLI](/zh-sg/wendang/guides/whatsapp/groups/management.cli.md) · [cURL](/zh-sg/wendang/guides/whatsapp/groups/management.curl.md)

删除后群组仍可在 `status` `deleted` 状态下被读取，因此已存储的引用仍可解析，不会变成 `404`。`failed` 状态的群组也可以删除，且不会触及任何外部系统：创建操作从未在 WhatsApp 上生成群组，因此清除该记录仅是 Bird 自身的内务处理。其他所有状态都会以 `409` [`E15047`](/docs/api/errors/E15047) 拒绝。

## 列出你的群组

列表返回你的工作区所创建的群组，按最新排列，采用游标分页。可按管理号码（`number`，E.164 号码或 `wan_` ID）、号码所属的 WhatsApp Business Account（`waba`）或 `status` 进行过滤，重复该参数可匹配多个值。`q` 对主题和描述进行不区分大小写的子字符串搜索。

**TypeScript**

```typescript
for await (const group of bird.whatsapp.groups.list({ status: ["active"] })) {
  console.log(group.id, group.subject, group.participant_count);
}
```

Examples: [TypeScript](/zh-sg/wendang/guides/whatsapp/groups/management.ts.md) · [Python](/zh-sg/wendang/guides/whatsapp/groups/management.py.md) · [Go](/zh-sg/wendang/guides/whatsapp/groups/management.go.md) · [PHP](/zh-sg/wendang/guides/whatsapp/groups/management.php.md) · [CLI](/zh-sg/wendang/guides/whatsapp/groups/management.cli.md) · [cURL](/zh-sg/wendang/guides/whatsapp/groups/management.curl.md)

已删除的群组仍以 `status` `deleted` 状态保留在列表中，因此按状态过滤即可只看到仍可发送消息的群组。

## 故障排查

- **`412` ([E15045](/docs/api/errors/E15045))**：该号码未持有 Official Business Account 状态，因此 WhatsApp 不允许其创建群组。此决定由 WhatsApp 做出：在 WhatsApp Manager 中该号码的配置文件上申请该状态，或使用已持有该状态的号码创建群组。
- **`404` ([E15046](/docs/api/errors/E15046))**：该 ID 未对应此工作区中的任何群组。群组属于创建它的工作区，因此来自其他工作区的 ID 在此处无法找到。
- **`409` ([E15047](/docs/api/errors/E15047))**：群组处于挂起、暂停、已删除或失败状态。只有活跃的群组才能接受变更。读取群组以查看其当前状态。
- **`409` ([E15049](/docs/api/errors/E15049))**：该号码已管理了 WhatsApp 允许的 10,000 个群组上限。删除已结束对话的群组，或使用另一个号码创建此群组。
- **`409` ([E15054](/docs/api/errors/E15054))**：对同一群组或同一参与者的变更仍在进行中。读取 `last_operation` 并等待其生效。
- **`422` ([E15050](/docs/api/errors/E15050))**：路径中指定的人不在群组中。读取群组的 `participants`，并使用其中报告的 `bsuid` 或 `phone_number`。
- **`422` ([E15051](/docs/api/errors/E15051))**：其中一个加入请求 ID 已不再等待决定。重新列出请求并使用返回的 ID。
- **`422` ([E15053](/docs/api/errors/E15053))**：该消息属于另一个群组或一对一对话。消息的 `to.group_id` 指示哪个群组可以置顶它。
- **一个始终未变为活跃状态的 `pending` 群组**：Bird 会放弃等待而非让其保持挂起状态，并将群组移至 `failed`，原因记录在 `last_operation.last_error` 中。创建一个替代群组，而非重试。

## 参考

完整的请求和响应结构在 API 参考中：[创建](/docs/api/reference/create-whatsapp-group)、[列出](/docs/api/reference/list-whatsapp-groups)、[获取](/docs/api/reference/get-whatsapp-group)、[更新](/docs/api/reference/update-whatsapp-group)、[删除](/docs/api/reference/delete-whatsapp-group)、[轮换邀请链接](/docs/api/reference/rotate-whatsapp-group-invite-link)、[移除参与者](/docs/api/reference/delete-whatsapp-group-participant)、[列出](/docs/api/reference/list-whatsapp-group-join-requests)、[批准](/docs/api/reference/approve-whatsapp-group-join-requests)和[拒绝](/docs/api/reference/reject-whatsapp-group-join-requests)加入请求，以及[置顶](/docs/api/reference/create-whatsapp-group-pinned-message)和[取消置顶](/docs/api/reference/delete-whatsapp-group-pinned-message)消息。

## 后续步骤

- [WhatsApp 群组](/docs/guides/whatsapp/groups)：群组的用途，以及在仪表板中的相同生命周期
- [向 WhatsApp 群组发送消息](/docs/guides/whatsapp/groups/sending)：群组寻址方式、所需条件及每位参与者的回执
- [接收 WhatsApp 群组消息](/docs/guides/whatsapp/groups/receiving)：哪位参与者发送了消息，以及如何回复群组
- [业务范围用户 ID](/docs/guides/whatsapp/business-scoped-user-ids)：当你没有电话号码时用于标识参与者的标识符
- [幂等性](/docs/guides/idempotency)：重试可能已被接受的写操作

## Related resources

- [Connecting WhatsApp to Bird: from buying a number to a live channel](/learn/whatsapp/connecting-whatsapp-to-bird) (video)
- [What is the 24-hour customer service window on WhatsApp?](/explained/whatsapp/what-is-the-24-hour-customer-service-window) (answer)
- [WhatsApp message builder](/tools/whatsapp-message-builder) (tool)
- [WhatsApp](/whatsapp-api) (product)

[Get an implementation brief](/learn/workspace?topic=whatsapp)
