# Group chats

Create WhatsApp groups owned by your business number, manage participants, invite links and join requests, and message the group from the inbox.

Your business number can own real WhatsApp groups: a support room with a client, a cohort for a course, a coordination group for a delivery team. Pozy creates the group, manages who is in it, and routes every group message through the same inbox endpoints you use for one-to-one chats.

Groups are not contact lists. To send the same message to many people individually, use a [broadcast](https://pozy.ai/docs/whatsapp/broadcasts).

## Requirements

| Requirement | Why |
| --- | --- |
| A Cloud API-only number | Meta turns the Groups API off for numbers in coexistence with the WhatsApp Business app. Connect with `onboarding=api` (see [Connect WhatsApp](https://pozy.ai/docs/whatsapp#cloud-api-only-or-coexistence)). |
| Official Business Account status on the number | Meta only grants group creation to numbers it has marked as an official business account. The `is_official_business_account` field of [number info](https://pozy.ai/docs/api/getWhatsAppNumberInfo) tells you. |

Meta's limits on groups:

| Limit | Value |
| --- | --- |
| Participants per group | 8 in total |
| Groups per number | 10,000 |
| `subject` | 128 characters |
| `description` | 2,048 characters |

## Create a group

Call [`POST /v1/whatsapp/wa-groups`](https://pozy.ai/docs/api/createWhatsAppGroupChat) with a `subject` and, optionally, a `description` and a `joinApprovalMode`:

- `approval_required`: people who open the invite link wait until you approve them.
- `auto_approve`: anyone with the link joins straight away.

```bash cURL
curl -X POST https://api.pozy.ai/v1/whatsapp/wa-groups \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "6712a9d4c0e3b58f1a7d2e64",
    "subject": "Acme x Northwind launch",
    "description": "Launch week coordination. Questions go here.",
    "joinApprovalMode": "approval_required"
  }'
```
```ts Node
const res = await fetch("https://api.pozy.ai/v1/whatsapp/wa-groups", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.POZY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    accountId: "6712a9d4c0e3b58f1a7d2e64",
    subject: "Acme x Northwind launch",
    description: "Launch week coordination. Questions go here.",
    joinApprovalMode: "approval_required",
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);

console.log(data.group.groupId, data.group.inviteLink);
```
```python Python
import os
import requests

H = {"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"}
resp = requests.post(
    "https://api.pozy.ai/v1/whatsapp/wa-groups",
    headers=H,
    json={
        "accountId": "6712a9d4c0e3b58f1a7d2e64",
        "subject": "Acme x Northwind launch",
        "description": "Launch week coordination. Questions go here.",
        "joinApprovalMode": "approval_required",
    },
    timeout=30,
)
group = resp.json()["group"]
print(group["groupId"], group["inviteLink"])
```

The response returns `201` with the `groupId` and an `inviteLink` (`https://chat.whatsapp.com/...`). List the number's active groups with [`GET /v1/whatsapp/wa-groups`](https://pozy.ai/docs/api/listWhatsAppGroupChats), which pages with `after`.

## Bring people in

WhatsApp treats groups as invite-only, so the invite link is the normal way in. You can also add numbers directly.

| Task | Call |
| --- | --- |
| Add people | [`POST /v1/whatsapp/wa-groups/{groupId}/participants`](https://pozy.ai/docs/api/addWhatsAppGroupParticipants) with `phoneNumbers` in E.164 (`?accountId=` in the query) |
| Remove people | [`DELETE .../participants`](https://pozy.ai/docs/api/removeWhatsAppGroupParticipants) with the same body |
| Get a fresh invite link | [`POST .../invite-link`](https://pozy.ai/docs/api/createWhatsAppGroupInviteLink). The previous link stops working. |
| See who is waiting | [`GET .../join-requests`](https://pozy.ai/docs/api/listWhatsAppGroupJoinRequests). Each entry has the phone and a Unix timestamp. |
| Let them in | [`POST .../join-requests`](https://pozy.ai/docs/api/approveWhatsAppGroupJoinRequests) with `phoneNumbers` |
| Turn them away | [`DELETE .../join-requests`](https://pozy.ai/docs/api/rejectWhatsAppGroupJoinRequests) with `phoneNumbers` |

```bash cURL
curl -X POST "https://api.pozy.ai/v1/whatsapp/wa-groups/120363401234567890/participants?accountId=6712a9d4c0e3b58f1a7d2e64" \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "phoneNumbers": ["+351912345678", "+447700900123"] }'
```

> **The 8-person cap is per group, not per request:**
> 
> Splitting a long list across several calls does not get a group past 8 participants. A `400` on add usually means the group is full.

Change the subject, description or join mode later with [`POST /v1/whatsapp/wa-groups/{groupId}`](https://pozy.ai/docs/api/updateWhatsAppGroupChat). [`GET`](https://pozy.ai/docs/api/getWhatsAppGroupChat) on the same path reads the group, and [`DELETE`](https://pozy.ai/docs/api/deleteWhatsAppGroupChat) removes it.

## Talk in the group

A group shows up in the inbox as a conversation once the first message arrives in it. There is no call to open a group conversation from your side, so ask a participant to say hello first (or share the invite link with a prompt to introduce themselves).

When that message arrives, `message.received` carries the `conversationId`. From then on, send to the group with [`POST /v1/inbox/conversations/{conversationId}/messages`](https://pozy.ai/docs/api/sendInboxMessage), exactly as you would in a one-to-one chat:

```bash cURL
curl -X POST "https://api.pozy.ai/v1/inbox/conversations/6714c1f6e2a5d70b3c9f4a86/messages" \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "6712a9d4c0e3b58f1a7d2e64",
    "message": "Welcome everyone. The launch checklist is pinned in the description."
  }'
```
```ts Node
const res = await fetch("https://api.pozy.ai/v1/inbox/conversations/6714c1f6e2a5d70b3c9f4a86/messages", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.POZY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    accountId: "6712a9d4c0e3b58f1a7d2e64",
    message: "Welcome everyone. The launch checklist is pinned in the description.",
  }),
});
if (!res.ok) throw new Error((await res.json()).error);
```
```python Python
requests.post(
    "https://api.pozy.ai/v1/inbox/conversations/6714c1f6e2a5d70b3c9f4a86/messages",
    headers=H,
    json={
        "accountId": "6712a9d4c0e3b58f1a7d2e64",
        "message": "Welcome everyone. The launch checklist is pinned in the description.",
    },
    timeout=30,
).raise_for_status()
```

Every participant's messages land in that conversation, so inbox webhooks and [workflows](https://pozy.ai/docs/automations/workflows) see group messages like any other.

## Common errors

| Error | Cause | Fix |
| --- | --- | --- |
| `400` with `type: platform_error` on any group call | The number is in coexistence, so Meta refuses group calls. Meta's own code is in `platformError`. | Reconnect the number with `onboarding=api` |
| `400` when adding participants | The group already has 8 people | Remove someone, or use a broadcast to reach more people |
| No conversation in the inbox | Nobody has written in the group yet | Wait for the first participant message |

## Endpoints

| Endpoint | What it does |
| --- | --- |
| [`GET /v1/whatsapp/wa-groups`](https://pozy.ai/docs/api/listWhatsAppGroupChats) | List active groups |
| [`POST /v1/whatsapp/wa-groups`](https://pozy.ai/docs/api/createWhatsAppGroupChat) | Create group |
| [`GET /v1/whatsapp/wa-groups/{groupId}`](https://pozy.ai/docs/api/getWhatsAppGroupChat) | Get group info |
| [`POST /v1/whatsapp/wa-groups/{groupId}`](https://pozy.ai/docs/api/updateWhatsAppGroupChat) | Update group settings |
| [`DELETE /v1/whatsapp/wa-groups/{groupId}`](https://pozy.ai/docs/api/deleteWhatsAppGroupChat) | Delete group |
| [`POST /v1/whatsapp/wa-groups/{groupId}/participants`](https://pozy.ai/docs/api/addWhatsAppGroupParticipants) | Add participants |
| [`DELETE /v1/whatsapp/wa-groups/{groupId}/participants`](https://pozy.ai/docs/api/removeWhatsAppGroupParticipants) | Remove participants |
| [`POST /v1/whatsapp/wa-groups/{groupId}/invite-link`](https://pozy.ai/docs/api/createWhatsAppGroupInviteLink) | Create invite link |
| [`GET /v1/whatsapp/wa-groups/{groupId}/join-requests`](https://pozy.ai/docs/api/listWhatsAppGroupJoinRequests) | List join requests |
| [`POST /v1/whatsapp/wa-groups/{groupId}/join-requests`](https://pozy.ai/docs/api/approveWhatsAppGroupJoinRequests) | Approve join requests |
| [`DELETE /v1/whatsapp/wa-groups/{groupId}/join-requests`](https://pozy.ai/docs/api/rejectWhatsAppGroupJoinRequests) | Reject join requests |
| [`POST /v1/inbox/conversations/{conversationId}/messages`](https://pozy.ai/docs/api/sendInboxMessage) | Send message |

## Webhook events

| Event | When it fires |
| --- | --- |
| [`message.received`](https://pozy.ai/docs/webhooks/events#message-received) | Message received. |
| [`conversation.started`](https://pozy.ai/docs/webhooks/events#conversation-started) | Conversation started. |
| [`message.sent`](https://pozy.ai/docs/webhooks/events#message-sent) | Message sent. |
