What the Groups API Is
Meta's Groups API lets a Cloud API business phone number create WhatsApp groups, invite users with an invite link, and send and receive messages in those groups. Groups are invite-only: you can't add people directly. Each user decides whether to join from the invite link, which shows them what the group is about.
The Groups API works with groups created through the API. It is a different product from the groups and communities people run in the WhatsApp app.
Dualhook Boundary
Dualhook documents the Groups API but does not offer it. The Runtime API has no /groups, /<GROUP_ID>, invite-link, join-request, or participant routes. Its /messages route accepts only recipient_type: "individual", so you can't create, manage, or message groups with a dh_live_ key. There is nothing for groups in the dashboard.
Most Dualhook connections are Coexistence numbers, and Meta does not offer the Groups API on WhatsApp Business app numbers. Groups you run in the WhatsApp Business app stay in the app; they are not synced or exposed through any API.
On a Cloud-API-only number that qualifies, call the Groups API from your own Meta app with access to the number. Dualhook does not ingest group webhooks. Its Meta app subscribes to messages, so group messages events go straight to your endpoint through Webhook Override, but it does not subscribe to the four group_* fields; subscribe your own Meta app to receive those.
Eligibility
- The business must be an Official Business Account (OBA). The Groups API is open to all businesses with an OBA.
- The number must be in use with Cloud API. Groups are not available for WhatsApp Business app numbers (Coexistence) or numbers onboarded to Multi-solution Conversations.
- Your app must be subscribed to the number's Messaging account, have
whatsapp_business_messagingfor the number, and be subscribed to thegroup_lifecycle_update,group_participants_update,group_settings_update, andgroup_status_updatewebhook fields.
An ineligible number gets error 131215. Meta can also temporarily block group creation (131214) when the Messaging account sent too many marketing messages inside customer service windows over the past 7 days.
Limits and Supported Message Types
| Limit | Value |
|---|---|
| Participants per group | 8 |
| Groups per business phone number | 10,000 |
| Cloud API businesses per group | 1 |
| Group subject | 128 characters (whitespace trimmed) |
| Group description | 2,048 characters |
| Group profile picture | image/jpeg only, max 5 MB, square, at least 192 × 192 px |
| Pinned messages | Max 3 at a time, 1–30 days each |
Supported message types are text, media, text-based templates, and media-based templates. Not supported: calling, disappearing messages, view-once, authentication templates, commerce messages, and interactive messages. You can't edit or delete messages, or hide the participant list.
Meta shows no performance metrics for templates used in groups. Create separate templates for groups instead of reusing your one-to-one templates.
How a Group Gets Started
- Create the group with
POST /<PHONE_NUMBER_ID>/groups. Agroup_lifecycle_updatewebhook withtype: "group_create"returns theinvite_link. - Send the invite link to users, typically with the invite link template.
- When a user joins, you get a
group_participants_updatewebhook withtype: "group_participants_add". - Send messages to the group with the
/messagesendpoint. Status webhooks and participant replies arrive on themessagesfield.
Group Management Endpoints
| Action | Request |
|---|---|
| Create group | POST /<PHONE_NUMBER_ID>/groups with subject, optional description and join_approval_mode |
| List active groups | GET /<PHONE_NUMBER_ID>/groups (limit 1–1024, default 25; cursor paging) |
| Get group info | GET /<GROUP_ID>?fields=subject,description,participants,join_approval_mode,suspended,creation_timestamp,total_participant_count |
| Update group settings | POST /<GROUP_ID> with subject, description, and/or profile_picture_file |
| Delete group | DELETE /<GROUP_ID> |
| Get / reset invite link | GET / POST /<GROUP_ID>/invite_link |
| Remove participants | DELETE /<GROUP_ID>/participants with participants: [{ "user": "<PHONE_OR_WA_ID>" }] |
| List / approve / reject join requests | GET / POST / DELETE /<GROUP_ID>/join_requests |
join_approval_modeisauto_approve(default) orapproval_required. With approval required, users who open the invite link submit a join request that you approve or reject. Approve and reject accept severaljoin_requestsIDs at once and list failures infailed_join_requests.- Get group info returns only the group ID if you pass no
fields.total_participant_countexcludes your business. - Resetting the invite link invalidates every previous link. Links always start with
https://chat.whatsapp.com/. - A removed participant can no longer join through the invite link.
- Deleting a group removes every participant, including your business.
For BSUID-related changes to group info, join requests, and participant removal, see BSUID API changes → Groups API.
Invite Link Template
Template Library has a utility template for group invite links. In WhatsApp Manager, open Template Library, choose Group invite link → Group invite upon request, pick a template, name it, and submit. Through the API, find it with:
GET /message_template_library?category=utility&topic=group_invite_link&language=en
You can't modify the template when you copy it, or it loses utility pricing. Approval can take up to 24 hours. Send it with a group_id body parameter; Meta replaces it with the group's invite link on delivery:
{
"messaging_product": "whatsapp",
"to": "<WHATSAPP_USER_PHONE_NUMBER>",
"type": "template",
"template": {
"name": "<TEMPLATE_NAME>",
"language": { "code": "<TEMPLATE_LANGUAGE>" },
"components": [
{
"type": "body",
"parameters": [{ "type": "group_id", "group_id": "<GROUP_ID>" }]
}
]
}
}
Send and Receive Group Messages
Send with the normal /messages endpoint, setting recipient_type to group and to to the group ID:
{
"messaging_product": "whatsapp",
"recipient_type": "group",
"to": "<GROUP_ID>",
"type": "text",
"text": { "body": "Your order is ready for pickup." }
}
You can't send to a group that only has one member (131020). Incoming group messages include a group_id field, and from identifies the participant who sent it. Message types groups don't support arrive with type: "unsupported" and error 130501. You can mark group messages as read with the Messages API, one message at a time: unlike a 1:1 chat, marking a group message as read does not mark earlier ones.
Pin and Unpin Messages
Only the group admin can pin. Each request pins one message, up to 3 pinned messages at a time. If three are already pinned, the oldest is unpinned automatically.
{
"messaging_product": "whatsapp",
"recipient_type": "group",
"to": "<GROUP_ID>",
"type": "pin",
"pin": {
"type": "pin",
"message_id": "wamid.HBgLM...",
"expiration_days": 4
}
}
Use "type": "unpin" to unpin; expiration_days (1–30) is required only when pinning. recipient_type and to must match, or the request fails. Pin and unpin trigger only a sent status webhook, never delivered or read.
Group Webhooks
Each group webhook carries a groups array; the entry's type says what happened.
| Field | type values | Notes |
|---|---|---|
group_lifecycle_update | group_create, group_delete | group_create includes invite_link, subject, and join_approval_mode. Failures carry an errors array. |
group_participants_update | group_participants_add, group_participants_remove, group_join_request_created, group_join_request_revoked | Adds list added_participants with reason: "invite_link". Removals list removed_participants and failed_participants, with initiated_by set to business or participant (a participant who left). |
group_settings_update | group_settings_update | profile_picture, group_subject, and group_description each report update_successful, with errors on failure. |
group_status_update | group_suspend, group_suspend_cleared | Sent when WhatsApp suspends a group you manage for policy reasons, or lifts the suspension. |
Requests you initiate (create, delete, remove, settings) echo a request_id in the matching webhook.
Group Message Status Webhooks
Group status webhooks use recipient_type: "group" and set recipient_id to the group ID. The participant's number is in a separate field; Meta's samples spell it both recipient_participant_id and participant_recipient_id, so read both.
WhatsApp may combine several statuses into one webhook: several participants for one message, or one participant for several messages. Combining is not guaranteed. A single webhook always covers one group and one status type, never different groups or status types. If a message is read almost immediately, the delivered webhook can be skipped because read implies it.
Pricing
Groups use per-message pricing, charged per delivered recipient. A billable marketing template delivered to 4 of a group's 5 members is charged 4 times, each at the rate for that recipient's country calling code.
When any participant messages you, a customer service window opens (or refreshes) for the whole group. Through September 30, 2026, utility and non-template messages inside that window were free. From October 1, 2026, utility messages inside the group window are charged, and non-template messages are free only while the phone number is within its free tier. That 1,000-message monthly free tier is shared with one-to-one service messages, and each group send uses one unit per delivered recipient.
Status webhooks report group pricing with pricing_model: "PMP":
pricing.type | pricing.category | Meaning (from October 1, 2026) |
|---|---|---|
regular | group_marketing | Billable marketing template |
regular | group_utility | Billable utility template, including inside a group window |
regular | group_service | Non-template message after the free tier is used up |
free_group_customer_service | group_service | Free non-template message within the free tier |
In Meta's analytics, product_types values 101 (group notification), 102 (group customer support), and 103 (inbound group) filter group messages; 103 must be queried on its own. pricing_analytics adds the GROUP_MARKETING, GROUP_UTILITY, and GROUP_SERVICE categories and the FREE_GROUP_CUSTOMER_SERVICE type. See Pricing for one-to-one rates.
GET /<WABA_ID>/group_analytics returns daily counts for one group at a time, up to 90 days back. It requires start, end, group_ids (one ID), and metric_types: SENT (messages the business sent to the group), DELIVERED and READ (per participant), PARTICIPANTS_JOINED, and PARTICIPANTS_LEFT. Data points report them as sent, delivered, read, joined, and left.
Error Codes
| Code | HTTP | Meaning |
|---|---|---|
130501 | — | Unsupported message type received in a group (webhook) |
131020 | 400 | Can't send messages to single-member groups |
131041 | 400 | Group not found, or your business isn't a member |
131059 | 400 | Pagination cursor expired or corrupted; restart paging |
131201 | 206 | Request partially succeeded; some participant-level operations failed |
131202 | 400 | Duplicate participants in the request |
131203 | — | Can't add the user: they haven't accepted WhatsApp's latest Terms of Service (join request approval) |
131204 | 400 | Group participant limit exceeded |
131207 | 403 | Group suspended for violating platform policies |
131208 | 429 | Too many group operations from this number in a short period |
131209 | 400 | Group profile picture isn't square |
131210 | 400 | Group profile picture is under 192 px |
131211 | 400 | Group creation limit for this number reached |
131212 | 400 | Participant isn't part of the group |
131213 | 400 | Join request doesn't exist |
131214 | 400 | Group creation temporarily disabled after excessive marketing messages in customer service windows over 7 days |
131215 | 400 | Number isn't eligible for the Groups API |