API Cloud (GROUPS)
The Groups API enables you to manage WhatsApp groups for messaging and collaboration.
Eligibility: The Groups API is now open to all businesses with an Official Business Account (OBA).
How it works
Groups are an invite-only experience where participants join using a group invite link you send them. This invite link provides context about the group, helping the user decide whether they want to join.
Quick facts
- Max group participants: 8
- Supported message types: Text, media, text-based templates, and media-based templates
- Max groups you can create: 10,000 per business number
- Max Cloud API businesses per group: 1
Analytics
Note: Performance metrics are not available for message templates used in Groups.
Create new templates specifically for Groups use instead of repurposing templates used for one-to-one messaging.
Limits
Warning: To qualify for groups features, your business must be an Official Business Account (OBA).
Groups are not available for:
- WhatsApp Business app phone numbers
- Phone numbers onboarded to Multi-solution Conversations
The Calling API is not supported in groups.
Non-supported message types:
- Calling
- Disappearing messages
- View-once
- Auth
- Commerce messages
- Interactive messages
Non-supported actions:
- Admin hide group participant list
- Edit message
- Delete message
Pricing
The Groups API uses per-message pricing.
Learn more about Groups API pricing here.
Get started
Groups are invite-only, meaning that potential group participants are ultimately in control of whether they want to join the group or not.
When you create a group, a unique invite link is generated which you can share to potential group participants. This link includes information about the group, enabling users to make an informed decision about whether or not they want to join the group.
Once a user joins the group, a webhook is triggered, signaling that you are now eligible to send messages to the group.
Prerequisites
Before you get started with the Groups API, ensure that:
- Your business number is in use with Cloud API (not the WhatsApp Business app).
- Your webhook server is set up for use with Cloud API.
- Your app is subscribed to the following groups webhook fields:
group_lifecycle_updategroup_participants_updategroup_settings_updategroup_status_update
- Your app is subscribed to the WhatsApp Business account of your business phone number.
- Your app has the
whatsapp_business_messagingpermission for the business number.
Step 2: Create a group
Use the Create Group endpoint to create a group, providing a subject and an optional description. Once a group has been successfully created, a group_lifecycle_update webhook for successful group creation will be returned. This webhook will include an invite_link field with the invite link that you can now share with potential group participants.
Step 3: Invite WhatsApp users to the group
3.1 Add a group invite link template in Template Library to your account templates
- Navigate to Template Library.
- On the left, click the Group invite link dropdown, then click the Group invite upon request checkbox.
- Select the template you want to use, give it a name, and click Submit.
3.2 Send the invite link to potential group participants
Once the template has been approved, use the template to invite members to the group using the invite link provided in the webhook from Step 2.
You can follow the instructions in the Send Group Invite Link Template Message reference to send the invite link with the template you just added to your account.
3.3 Notification of when participants join the group
When a participant joins, a group_participants_update webhook for a group participant joining will be triggered.
Step 4: Send and receive messages
You can now use the Cloud API send message endpoint to send messages to the group.
Sent, delivered, and read status webhooks will be triggered when there are updates in the group. Replies from participants will also trigger webhooks.
Learn more about how to send and receive group messages
Features and reference
Group management
The Groups API gives you simple functions to control groups through their lifecycle.
When you create a new group, an invite link is created for inviting participants to the group.
Since you cannot manually add participants to the group, simply send a message with your invite link to WhatsApp users who you would like to join the group.
ISV group management endpoints (the component resolves the token and phone number from the {did}):
| Operation | ISV endpoint |
|---|---|
| Create group | POST /groups/{v}/{did} |
| Get active groups | GET /groups/{v}/{did} |
| Get group info | GET /groups/{v}/{did}/{group_id}?fields= |
| Update group settings | POST /groups/{v}/{did}/{group_id} |
| Delete group | DELETE /groups/{v}/{did}/{group_id} |
| Get join requests | GET /groups/{v}/{did}/{group_id}/join_requests |
| Approve join requests | POST /groups/{v}/{did}/{group_id}/join_requests |
| Reject join requests | DELETE /groups/{v}/{did}/{group_id}/join_requests |
| Get invite link | GET /groups/{v}/{did}/{group_id}/invite_link |
| Reset invite link | POST /groups/{v}/{did}/{group_id}/invite_link |
| Remove participants | DELETE /groups/{v}/{did}/{group_id}/participants |
Group endpoint requirements:
- All endpoints require authentication (Bearer token) and channel validation.
- Required fields (
did,group_id,join_requests,participants) are validated before any Meta call, returning400if missing. - Requests are forwarded to Meta unchanged and Meta’s response is returned as-is.
Subscribe to groups metadata webhooks
In order to receive webhook notifications for metadata about your groups, please subscribe to the following webhook fields:
group_lifecycle_updategroup_participants_updategroup_settings_updategroup_status_update
Warning: For a full reference of webhooks for the Groups API, please visit our Webhooks for Groups API reference.
Create group
Use this endpoint to create a new group and generate a group invite link.
Once the group is created, you will receive a webhook with an invite_link parameter that contains an invite link for the group. You can send this invite link to WhatsApp users interested in joining the group.
Optionally, you can create a group that requires join approval. This means that if a WhatsApp user wants to join your group, you can approve or reject their request.
Request syntax
Create a group with an initial group invite link:
POST /groups/{v}/{did}
Request body
{
"messaging_product": "whatsapp",
"subject": "<GROUP_SUBJECT>",
"description": "<GROUP_DESCRIPTION>",
"join_approval_mode": "<JOIN_APPROVAL_MODE>"
}Request parameters
| Placeholder | Description | Sample Value |
|---|---|---|
<BUSINESS_PHONE_NUMBER_ID>String | Required Business phone number ID. | 12784358810 |
<GROUP_SUBJECT>String | Required Group subject. Maximum 128 characters. Whitespace is trimmed. | New Purchase Inquiry |
<GROUP_DESCRIPTION>String | Optional Group description. Maximum 2048 characters. | Jim, an existing client, would like to learn about new car purchase options for current year models. |
<JOIN_APPROVAL_MODE>String | Optional Indicates if WhatsApp users who click the invitation link can join the group with or without being approved first. Values can be: - approval_required — Indicates WhatsApp users must be approved via join request before they can access the group.- auto_approve — Indicates WhatsApp users can join the group without approval.If omitted, join_approval_mode is set to auto_approve by default. | auto_approve |
Webhooks
A group_lifecycle_update webhook is triggered.
- View the “Group create succeed” sample webhook
- View the “Group create fail” sample webhook
- View the “User joins group using invite link” sample webhook
Groups with join requests
You can create groups that require join request approval. Once enabled, WhatsApp users who click the group invitation link can submit a request to join the group, or cancel a prior request:
When a WhatsApp user joins the group using a join request, a group_participants_update webhook for a user accepting the join request is triggered. You can also get a list of open join requests via API. Use the contents of the webhook or API response to approve or reject requests.
Get join requests
Request syntax
GET /groups/{v}/{did}/{group_id}/join_requests
Request parameters
| Placeholder | Description | Sample Value |
|---|---|---|
<GROUP_ID>String | Required. Group ID. | Y2FwaV9ncm91cDoxNzA1NTU1MDEzOToxMjAzNjM0MDQ2OTQyMzM4MjAZD |
Response syntax
Upon success:
{
"data": [
{
"join_request_id": "<JOIN_REQUEST_ID>",
"wa_id": "<WHATSAPP_USER_ID>",
"creation_timestamp": "<JOIN_REQUEST_CREATION_TIMESTAMP">
},
//Additional join request objects would follow, if any
],
"paging": {
"cursors": {
"before": "<BEFORE_CURSOR>",
"after": "<AFTER_CURSOR>"
}
}
}Response parameters
| Placeholder | Description | Sample Value |
|---|---|---|
<JOIN_REQUEST_ID>String | Join request ID. | MTY0NjcwNDM1OTU6MTIwMzYzNDA0Njk0MjMzODIw |
<WHATSAPP_USER_ID>String | WhatsApp user ID. | 16505551234 |
<JOIN_REQUEST_CREATION_TIMESTAMP>Integer | Unix timestamp indicating when the join request was created. | 1755548877 |
<BEFORE_CURSOR>String | Before cursor. See Paginated Results. | eyJvZAmZAzZAXQiOjAsInZAlcnNpb25JZACI6IjE3NTU1NTM3MDUxNzUwNTQ1MTAifQZDZD |
<AFTER_CURSOR>String | After cursor. See Paginated Results. | eyJvZAmZAzZAXQiOjAsInZAlcnNpb25JZACI6IjE3NTU1NTM3MDUxNzUwNTQ1MTAifQZDZD |
Approve join requests
Request syntax
POST /groups/{v}/{did}/{group_id}/join_requests
Request body
{
"messaging_product": "whatsapp",
"join_requests": [
"<JOIN_REQUEST_ID>",
// Additional join request IDs would go here, if approving in bulk
]
}Request parameters
| Placeholder | Description | Sample Value |
|---|---|---|
<GROUP_ID>String | Required. Group ID. | Y2FwaV9ncm91cDoxNzA1NTU1MDEzOToxMjAzNjM0MDQ2OTQyMzM4MjAZD |
Response syntax
Upon success, the API will respond with the following JSON payload, and WhatsApp users whose join requests were approved will be able to access the group when tapping the invite link.
{
"messaging_product": "whatsapp",
"approved_join_requests": [
"<JOIN_REQUEST_ID>",
// Additional join request IDs would go here, it approved in bulk
],
//Only included if unable to approve one or more join requests
"failed_join_requests": [
{
"join_request_id": "<JOIN_REQUEST_ID>",
"errors": [
{
"code": "<ERROR_CODE>",
"message": "<ERROR_MESSAGE>",
"title": "<ERROR_TITLE>",
"error_data": {
"details": "<ERROR_DETAILS>"
}
}
]
}
],
"errors": [
{
"code": "<ERROR_CODE>",
"message": "<ERROR_MESSAGE>",
"title": "<ERROR_TITLE>",
"error_data": {
"details": "<ERROR_DETAILS>"
}
}
]
}Response parameters
| Placeholder | Description | Sample Value |
|---|---|---|
<JOIN_REQUEST_ID>String | ID of approved join request, or ID of failed join request, if the request could not be approved. | MTY0NjcwNDM1OTU6MTIwMzYzNDA0Njk0MjMzODIw |
<ERROR_CODE>Integer | Error code, if unable to approve. | 131203 |
<ERROR_MESSAGE>String | Error message, if unable to approve. | (#131203) Recipient has not accepted our new Terms of Service and Privacy Policy. |
<ERROR_TITLE>String | Error title, if unable to approve. | Unable to add participant to group |
<ERROR_DETAILS>String | Error details, if unable to approve. | Recipient has not accepted our new Terms of Service and Privacy Policy. |
Webhook
A group_participants_update webhook is triggered.
View the “User accepts join request” sample webhook
Reject join requests
Request syntax
DELETE /groups/{v}/{did}/{group_id}/join_requests
Request body
{
"messaging_product": "whatsapp",
"join_requests": [
"<JOIN_REQUEST_ID>",
//Additional join request IDs would go here, it rejecting in bulk
]
}Request parameters
| Placeholder | Description | Sample Value |
|---|---|---|
<GROUP_ID>String | Required. Group ID. | Y2FwaV9ncm91cDoxNzA1NTU1MDEzOToxMjAzNjM0MDQ2OTQyMzM4MjAZD |
<JOIN_REQUEST_ID>String | Required. ID of join request to reject. | MTY0NjcwNDM1OTU6MTIwMzYzNDA0Njk0MjMzODIw |
Response syntax
Upon success, the API will respond with the following JSON payload, and the WhatsApp user will see the Request to join button again when accessing the group invite link.
{
"messaging_product": "whatsapp",
"rejected_join_requests": [
"<JOIN_REQUEST_ID>",
//Additional join request IDs would go here, it rejecting in bulk
],
//Only included if unable to reject one or more join requests
"failed_join_requests": [
{
"join_request_id": "<JOIN_REQUEST_ID>",
"errors": [
{
"code": "<ERROR_CODE>",
"message": "<ERROR_MESSAGE>",
"title": "<ERROR_TITLE>",
"error_data": {
"details": "<ERROR_DETAILS>"
}
}
]
}
],
"errors": [
{
"code": "<ERROR_CODE>",
"message": "<ERROR_MESSAGE>",
"title": "<ERROR_TITLE>",
"error_data": {
"details": "<ERROR_DETAILS>"
}
}
]
}Response parameters
| Placeholder | Description | Sample Value |
|---|---|---|
<JOIN_REQUEST_ID>String | ID of rejected join request, or ID of failed join request, if the request could not be rejected. | MTY0NjcwNDM1OTU6MTIwMzYzNDA0Njk0MjMzODIw |
<ERROR_CODE>Integer | Error code, if unable to reject. | 131203 |
<ERROR_MESSAGE>String | Error message, if unable to reject. | (#131203) Recipient has not accepted our new Terms of Service and Privacy Policy. |
<ERROR_TITLE>String | Error title, if unable to reject. | Unable to add participant to group |
<ERROR_DETAILS>String | Error details, if unable to reject. | Recipient has not accepted our new Terms of Service and Privacy Policy. |
Webhook
None.
Get and reset group invite link
Warning: Once an invite link is reset, all previous invite links will become invalid.
An invite link for the group is generated when the group is created. Use these endpoints to get and reset group invite links.
For each endpoint, you will need your group ID in order to get or reset a link for the correct group as follows:
| Placeholder | Description | Sample Value |
|---|---|---|
<GROUP_ID>String | Required The ID of the group you want to get or reset an invite link for. | Y2FwaV9ncm91cDoxOTUwNTU1MDA3OToxMjAzNjMzOTQzMjAdOTY0MTUZD |
Get group invite link
Request syntax
GET /groups/{v}/{did}/{group_id}/invite_link
Response body
{
"messaging_product": "whatsapp",
"invite_link": "https://chat.whatsapp.com/<LINK_ID>"
}Note that invite_link always begins with the prefix https://chat.whatsapp.com/. The only variable portion is <LINK_ID>.
Reset group invite link
Request syntax
POST /groups/{v}/{did}/{group_id}/invite_link
Request body
{
"messaging_product": "whatsapp",
}Response body
{
"messaging_product": "whatsapp",
"invite_link": "https://chat.whatsapp.com/<LINK_ID>"
}Send group invite link template message
Template Library contains a utility message template for sending group invite links to WhatsApp users. Use these pre-defined templates to send group invitations as utility messages.
Warning: In order to keep the template priced as utility, you cannot modify it when you copy it from template library to your WABA.
To send the template message:
Step 1. Add a group invite link template in Template Library to your account templates
In WhatsApp Manager
- Navigate to Template Library.
- On the left, click the Group invite link dropdown, then click the Group invite upon request checkbox.
- Select the template you want to use, give it a name, and click Submit.
Via the API
You can query template libraries applicable to group invite links using the request below:
GET /message_template_library?category=utility&topic=group_invite_link&language=en
Read more about finding and adding the template to your WABA via the API
Note: Template approval may require up to 24 hours. You’ll be able to send messages with this template after its approval.
Step 2. Send the template message
- Send the template using the request syntax and body below, substituting your group ID, the name you gave your template, and other applicable values.
When you provide the group ID in the API request, it will be automatically translated into the corresponding group invite link upon message delivery.
Request syntax
POST /{v}/{did}/messages
Endpoint parameters
| Placeholder | Description | Sample Value |
|---|---|---|
{v}String | API version. | v21.0 |
{did}String | Business phone number ID (the component resolves the token and number from the did). | 12784358810 |
Request body
curl --location 'https://channels.chattigo.com/bsp-cloud-chattigo-isv/{v}/{did}/messages' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <JWT>' \
--data '{
"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>"
},
{
...additional parameters
}
]
}
]
}
}'Learn more about Template Library
Webhooks
Delete group
This endpoint deletes the group and removes all participants, including the business. No request body is required.
Request syntax
DELETE /groups/{v}/{did}/{group_id}
Request properties
| Placeholder | Description | Sample Value |
|---|---|---|
<GROUP_ID>String | Required The ID of the group you want to delete. | Y2FwaV9ncm91cDoxOTUwNTU1MDA3OToxMjAzNjMzOTQzMjAdOTY0MTUZD |
Webhooks
A group_lifecycle_update webhook is triggered.
Remove group participants
Use this endpoint to remove participants from the group.
Note: If a participant is removed from a group, they can no longer join the group via an invite link.
Request syntax
DELETE /groups/{v}/{did}/{group_id}/participants
Request body
{
"messaging_product": "whatsapp",
"participants": [
{ "user": "<WHATSAPP_USER_PHONE_NUMBER> or <WHATSAPP_USER_ID>" },
{ "user": "<WHATSAPP_USER_PHONE_NUMBER> or <WHATSAPP_USER_ID>"" },
...
]
}Request properties
| Placeholder | Description | Sample Value |
|---|---|---|
"participants": []Array | Optional Specifies an array of phone numbers or WhatsApp IDs of WhatsApp accounts. The business phone number used to create the group is always added to the group as the creator and admin. - Maximum 8 participants. - The array cannot be empty. | ``` |
| { “user”: “+17865347866” }, | ||
| { “user”: “+7669992245” }, | ||
| … |
##### Webhooks
A `group_participants_update` webhook is triggered.
- [View the "Group participant leaves" sample webhook](https://developers.facebook.com/documentation/business-messaging/whatsapp/groups/webhooks#delete-group-succeed)
#### Get group info
Use this endpoint to retrieve metadata about a single group.
**Note:** Specifying no fields in the query parameters will just return the group ID and messaging product.
##### Request syntax
`GET /groups/{v}/{did}/{group_id}?fields=<FIELDS>`
##### Endpoint parameters
| Placeholder | Description | Sample Value |
| --- | --- | --- |
| `<GROUP_ID>`<br><br>_String_ | **Required**<br><br>The ID of the group you are querying info from. | `Y2FwaV9ncm91cDoxOTUwNTU1MDA3OToxMjAzNjMzOTQzMjAdOTY0MTUZD` |
| `<FIELDS>`<br><br>_String_ | **Optional**<br><br>A comma-separated list of fields to return. If no fields are passed in, only the group ID is returned. | `"subject,description,participants,join_approval_mode"`<br><br>[Learn more about Graph API fields here](https://developers.facebook.com/docs/graph-api/overview#fields) |
##### Available fields
| Field | Description | Sample Return Value |
| --- | --- | --- |
| `join_approval_mode`<br><br>_String_ | Indicates if WhatsApp users who click the invitation link can join the group with or without being approved first.<br><br>Values can be:<br><br>- `approval_required` — Indicates WhatsApp users must be approved via [join request](#groups-with-join-requests) before they can access the group.<br>- `auto_approve` — Indicates WhatsApp users can join the group without approval. | `auto_approve` |
| `subject`<br><br>_String_ | The subject for the group. | `"Artificial Intelligence Insights"` |
| `description`<br><br>_String_ | The group description, if set during creation time. | `"Explore AI developments, share knowledge, and discuss the future of artificial intelligence with fellow enthusiasts and experts."` |
| `suspended`<br><br>_Boolean_ | Returns `true` if the group has been suspended by WhatsApp. | `false` |
| `creation_timestamp`<br><br>_Integer_ | UNIX timestamp in seconds at which the group was created. | `683731200` |
| `participants`<br><br>_List_ | A list of objects `{"wa_id": "<WA_ID>"}`, where `<WA_ID>` is a participant in the group being queried. | `[{"wa_id": "2228675309"}, {"wa_id": "7693349922"}]` |
| `total_participant_count`<br><br>_Integer_ | The total number of participants in the group, excluding your business. | `6` |
##### Sample response
```curl
{
"messaging_product": "whatsapp",
"id": "<GROUP_ID>",
"subject": "<SUBJECT>",
"creation_timestamp": "<TIMESTAMP>",
"suspended": "<SUSPENDED>",
"description": "<DESCRIPTION>",
"total_participant_count": "<TOTAL_PARTICIPANT_COUNT>",
"participants": [
{
"wa_id": "<WA_ID>"
},
{
"wa_id": "<WA_ID>"
}
],
"join_approval_mode": "<JOIN_APPROVAL_MODE>"
}Get active groups
Use this endpoint to retrieve a list of active groups for a given business phone number.
Request syntax
GET /groups/{v}/{did}
Query parameters
?limit=<LIMIT>, // Optional
&after=<AFTER_CURSOR>, // Optional
&before=<BEFORE_CURSOR> // Optional| Parameter | Description |
|---|---|
<LIMIT>Optional | Number of groups to fetch in the request. Min: 1 | Default: 25 | Max: 1024 |
<BEFORE_CURSOR>Optional | Cursor that points to the beginning of a page of data. Learn more about Paginated Results in Graph API here |
<AFTER_CURSOR>Optional | Cursor that points to the end of a page of data. Learn more about Paginated Results in Graph API here |
Response object
{
"data": {
"groups": [
{"id": "GROUP_ID", "subject": SUBJECT, "created_at": "TIMESTAMP"},
{"id": "GROUP_ID", "subject": SUBJECT, "created_at": "TIMESTAMP"}
…
]
},
"paging": {
"cursors": {
"after": "MTAxNTExOTQ1MjAwNzI5NDE=",
"before": "NDMyNzQyODI3OTQw"
},
"previous": "https://channels.chattigo.com/bsp-cloud-chattigo-isv/groups/VERSION/{did}?limit=10&before=NDMyNzQyODI3OTQw",
"next": "https://channels.chattigo.com/bsp-cloud-chattigo-isv/groups/VERSION/{did}?limit=25&after=MTAxNTExOTQ1MjAwNzI5NDE="
}
}Note: the ISV rewrites the pagination URLs (paging.previous/paging.next) to point to the ISV itself with your {did} instead of the Meta API. You can use them directly to paginate.
Response parameters
| Parameter | Description |
|---|---|
data[groups]List | A list of groups, each containing the group ID, group subject, and UNIX timestamp for group creation. |
pagingObject | A pagination object. Learn more about Paginated Results in Graph API here |
Update group settings
Use this endpoint to update your group’s subject, description, and photo.
Request syntax
POST /groups/{v}/{did}/{group_id}
Request body
{
"messaging_product": "whatsapp",
"subject": "<GROUP_SUBJECT>",
"profile_picture_file": "<FILE_PATH>",
"description": "<GROUP_DESCRIPTION>"
}Request properties
| Placeholder | Description | Sample Value |
|---|---|---|
<FILE_PATH>String | Optional A path to an image file stored in your local directory. To upload a file: Follow the same request structure as the Upload Media endpoint. Sample file upload cURL: ``` | |
| curl ‘https://channels.chattigo.com/bsp-cloud-chattigo-isv/{v}/{did}/uploads' \ | ||
| -X POST \ | ||
| -H ‘Authorization: Bearer | ||
| -F ‘messaging_product=whatsapp’ \ | ||
| -F ‘file=@/media/pictures/square_pic.png’ | ||
| ``` Group profile picture requirement: * Only support mime type image/jpeg * Maximum size: 5MB * Image should be in square, that is, height = width. * Minimum size: 192 x 192 | /local/path/file.jpg | |
<GROUP_SUBJECT>String | Optional The new subject for the group. - Maximum length: 128 characters. - Must not be empty if provided. | "Watch Enthusiasts" |
<GROUP_DESCRIPTION>String | Optional The new description for the group. - Max length: 2048 characters | "Join our community to discuss the latest timepieces, share watch reviews, and connect with fellow horology enthusiasts." |
Webhooks
A group_settings_update webhook is triggered.
- View the “Group settings update succeed” sample webhook
- View the “Group settings update partial fail” sample webhook
- View the “Group settings update total fail” sample webhook
Group message status webhooks
When you send a message to a group, you receive a status messages webhook when the message is delivered or read by group participants.
Status webhooks for individual group participants may be aggregated into a single webhook containing multiple status objects in the statuses array. However, aggregation is not guaranteed. If multiple participants’ statuses are generated at approximately the same time, they may be combined into a single webhook. If statuses are generated at different times, you may receive separate webhooks for each participant.
Each webhook only ever references a single message sent to a single group and a single status type (for example, delivered). Statuses for different messages, groups, or status types are never combined into a single webhook.
For the full webhook payload reference, see the status messages webhook reference.
Pricing information
Status messages webhooks that contain pricing information will have <CONVERSATION_CATEGORY> set to one of:
group_marketing— Indicates a group marketing conversation.group_utility— Indicates a group utility conversation.group_service— Indicates a group service conversation.
Group messaging
This section describes the APIs and webhooks for sending and receiving messages within groups. Supported message types include:
- Text messages
- Media messages
- Text-based templates
- Media-based templates
Subscribe to groups metadata webhooks
To receive webhook notifications for metadata about your groups, subscribe to the following webhook fields:
group_lifecycle_updategroup_participants_updategroup_settings_updategroup_status_update
Warning: For a full reference of webhooks for the Groups API, see the Webhooks for Groups API reference.
Send group message
To send a group message, use the Messages API.
This endpoint has been extended to support group messages in the following way:
- The
recipient_typefield now supportsgroupas well asindividual. - The
tofield now supports thegroup IDthat is obtained when using the Groups API.
Example group message send
curl 'https://channels.chattigo.com/bsp-cloud-chattigo-isv/{v}/{did}/messages' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <JWT>' \
-d '
{
"messaging_product": "whatsapp",
"recipient_type": "group",
"to": "Y2FwaV9ncm91cDoxNzA1NTU1MDEzOToxMjAzNjM0MDQ2OTQyMzM4MjAZD",
"type": "text",
"text": {
"preview_url": true,
"body": "This is another destination option: https://www.luckytravel.com/DDLmU5F1Pw"
}
}'Webhooks
Group message sent example
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "<WHATSAPP_BUSINESS_ACCOUNT_ID>",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "<BUSINESS_DISPLAY_PHONE_NUMBER>",
"phone_number_id": "<BUSINESS_PHONE_NUMBER_ID>"
},
"statuses": [
{
"id": "<WHATSAPP_MESSAGE_ID>",
"recipient_id": "<GROUP_ID>",
"recipient_type": "group",
"status": "sent",
"timestamp": "<WEBHOOK_TRIGGER_TIMESTAMP>",
}
]
},
"field": "messages"
}
]
}
]
}Group message failed example
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "<WHATSAPP_BUSINESS_ACCOUNT_ID>",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "<BUSINESS_DISPLAY_PHONE_NUMBER>",
"phone_number_id": "<BUSINESS_PHONE_NUMBER_ID>"
},
"statuses": [
{
"id": "<WHATSAPP_MESSAGE_ID>",
"recipient_id": "<GROUP_ID>",
"recipient_type": "group",
"status": "failed",
"timestamp": "<WEBHOOK_TRIGGER_TIMESTAMP>",
"errors": [
{
"code": "<ERROR_CODE>",
"title": "<ERROR_TITLE>",
"message": "<ERROR_MESSAGE>",
"error_data": {
"details": "<ERROR_DETAILS>",
},
"href": "/documentation/business-messaging/whatsapp/support/error-codes"
}
]
}
]
},
"field": "messages"
}
]
}
]
}Receive group messages
You can use the following webhooks to receive statuses on messages received in the group.
The message object includes a group_id field to indicate this is a group message. The from field in the message object and the contact object point to the same participant who sends this message.
Webhooks
Receive group message webhook sample
{
"object": "whatsapp_business_account",
"entry": [{
"id": "<WHATSAPP_BUSINESS_ACCOUNT_ID>",
"changes": [{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "<BUSINESS_DISPLAY_PHONE_NUMBER>",
"phone_number_id": "<BUSINESS_PHONE_NUMBER_ID>"
},
"contacts": [{
"profile": {
"name": "<WHATSAPP_USER_NAME>"
},
"wa_id": "<WHATSAPP_USER_PHONE_NUMBER>"
}],
"messages": [{
"from": "<GROUP_PARTICIPANT_PHONE_NUMBER>",
"group_id": "<GROUP_ID>",
"id": "<WHATSAPP_MESSAGE_ID>",
"timestamp": "<WEBHOOK_TRIGGER_TIMESTAMP>",
"text": {
"body": "<MESSAGE_BODY>"
},
"type": "text"
}]
},
"field": "messages"
}]
}]
}Receive unsupported group message webhook sample
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "<WHATSAPP_BUSINESS_ACCOUNT_ID>",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "<BUSINESS_DISPLAY_PHONE_NUMBER>",
"phone_number_id": "<BUSINESS_PHONE_NUMBER_ID>",
},
"contacts": [
{
"profile": {
"name": "<WHATSAPP_USER_NAME>"
},
"wa_id": "<WHATSAPP_USER_PHONE_NUMBER>"
}
],
"messages": [
{
"from": "<GROUP_PARTICIPANT_PHONE_NUMBER>",
"group_id": "<GROUP_ID>",
"id": "<WHATSAPP_MESSAGE_ID>",
"timestamp": "<WEBHOOK_TRIGGER_TIMESTAMP>",
"errors": [
{
"code": 130501,
"message": "Message type is not currently supported",
"title": "Unsupported message type",
"error_data": {
"details": "<ERROR_DETAILS>"
}
}
],
"type": "unsupported"
}
]
},
"field": "messages"
}
]
}
]
}Pin and unpin group message
Pinning a message highlights its relevance.
The display order of the pinned messages is based on the chronological order of parent messages, newest first. If three messages are already pinned when a new pin request is made, the oldest pinned message will be automatically unpinned.
Limits
- When calling the API, only one message can be pinned at a time.
- Only the group admin can pin or unpin messages.
- A maximum of 3 pinned messages can exist at any time.
Request syntax
POST /{v}/{did}/messages
Note: You will receive an error in the sync response if the recipient_type and to type do not match.
Request body
{
"messaging_product": "whatsapp",
"recipient_type": "group",
"to": "<GROUP_ID>",
"type": "pin",
"pin": {
"type": "<PIN_OPERATION>",
"message_id": "<MESSAGE_ID>",
"expiration_days": "<EXPIRATION>"
}
}Body parameters
| Placeholder | Description | Sample Value |
|---|---|---|
<GROUP_ID>String | Required The group in which you are pinning a message. | Y2FwaV9ncm91cDoxOTUwNTU1MDA3OToxMjAzNjMzOTQzMjAdOTY0MTUZD |
<PIN_OPERATION>String | Required The pinning operation you are performing on the group. Can either be "pin" or "unpin" | pin |
<MESSAGE_ID>String | Required A unique identifier for the message you are pinning or unpinning in the group. | wamid.HBgLM... |
<EXPIRATION>Integer | Required when PIN_OPERATION is pinPin duration in days. Can be 1 to 30 days. | 4 |
Response body
{
"messaging_product": "whatsapp",
"contacts": [
{
"input": "Y2FwaV9ncm91cDo....",
"wa_id": "Y2FwaV9ncm91cDo...."
}
],
"messages": [
{
"id": "wamid.HBgLM..."
}
]
}Webhooks
Subscribe to the messages webhook topic to receive message status notifications. Standard sent and delivered statuses webhooks will be received for the message_id in the response.
Learn more about the messages status webhook object here
Group message status webhooks
When you send messages to a group, you will receive a webhook when the message is delivered or read.
You receive a single aggregated webhook instead of multiple webhooks.
This means that if you send a message and are set to receive several read or delivered statuses, you receive a single aggregated webhook containing multiple status objects.
Each webhook you receive is only ever in reference to a single message sent to a single group and a single status type.
Learn more about the Group Message Status webhook
Webhooks for Groups API
In order to receive webhook notifications for metadata about your groups, please subscribe to the following webhook fields:
group_lifecycle_updategroup_participants_updategroup_settings_updategroup_status_update
group_lifecycle_update webhooks
A group_lifecycle_update webhook is triggered when a group is either created or deleted.
Group create succeed
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID"
},
"groups": [
{
"timestamp": "TIMESTAMP",
"group_id": "GROUP_ID",
"type": "group_create",
"request_id": "REQUEST_ID",
"subject": "test invite link",
"invite_link": "https://chat.whatsapp.com/LINK_ID",
"join_approval_mode": "JOIN_APPROVAL_MODE"
}
]
},
"field": "group_lifecycle_update"
}
]
}
]
}Group create fail
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID",
},
"groups": [
{
"timestamp": "TIMESTAMP",
"type": "group_create",
"subject": "GROUP_SUBJECT",
"description": "GROUP_DESCRIPTION",
"request_id": "REQUEST_ID",
"group_id": "GROUP_ID",
"errors": [
{
"code": "ERROR_CODE",
"message": "ERROR_MESSAGE",
"title": "ERROR_TITLE",
"error_data": {
"details": "ERROR_DETAILS"
}
}
]
}
]
},
"field": "group_lifecycle_update"
}
]
}
]
}Delete group succeed
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID",
},
"groups": [
{
"timestamp": "TIMESTAMP",
"group_id": "GROUP_ID",
"type": "group_delete",
"request_id": "REQUEST_ID",
}
]
},
"field": "group_lifecycle_update"
}
]
}
]
}Delete group fails
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID",
},
"groups": [
{
"timestamp": "TIMESTAMP",
"group_id": "GROUP_ID",
"type": "group_delete",
"request_id": "REQUEST_ID",
"errors": [
{
"code": "ERROR_CODE",
"message": "ERROR_MESSAGE",
"title": "ERROR_TITLE",
"error_data": {
"details": "ERROR_DETAILS"
}
}
]
}
]
},
"field": "group_lifecycle_update"
}
]
}
]
}group_participants_update webhooks
A group_participants_update webhook is triggered when a WhatsApp user joins a group with an invite link, requests to join a group, cancels their request, or when one or more join requests are approved.
User joined group using invite link succeed
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID",
},
"groups": [
{
"timestamp": "TIMESTAMP",
"group_id": "GROUP_ID",
"type": "group_participants_add",
"reason": "invite_link",
"added_participants": [
{
"wa_id": "WHATSAPP_ID",
},
]
}
]
},
"field": "group_participants_update"
}
]
}
]
}User accepts or cancels join request
- For join requests:
GROUP_REQUEST_TYPEis set togroup_join_request_created. - For cancel requests:
GROUP_REQUEST_TYPEis set togroup_join_request_revoked.
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "BUSINESS_DISPLAY_PHONE_NUMBER",
"phone_number_id": "BUSINESS_PHONE_NUMBER_ID"
},
"groups": [
{
"timestamp": "WEBHOOK_TRIGGER_TIMESTAMP",
"group_id": "GROUP_ID",
"type": "GROUP_REQUEST_TYPE",
"reason": "REASON_FOR_REQUEST_OUTCOME",
"join_request_id": "JOIN_REQUEST_ID",
"wa_id": "WHATSAPP_USER_ID"
}
]
},
"field": "group_participants_update"
}
]
}
]
}Join request approved
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "BUSINESS_DISPLAY_PHONE_NUMBER",
"phone_number_id": "BUSINESS_PHONE_NUMBER_ID"
},
"groups": [
{
"timestamp": WEBHOOK_TRIGGER_TIMESTAMP,
"group_id": "GROUP_ID",
"type": "group_participants_add",
"reason": "invite_link",
"added_participants": [
{
"input": "WHATSAPP_USER_PHONE_NUMBER",
"wa_id": "WHATSAPP_USER_ID"
}
]
}
]
},
"field": "group_participants_update"
}
]
}
]
}Group participant remove succeed
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID",
},
"groups": [
{
"timestamp": "TIMESTAMP",
"group_id": "GROUP_ID",
"type": "group_participants_remove",
"request_id": "REQUEST_ID",
"removed_participants": [
{
"input": "PHONE_NUMBER or WHATSAPP_ID"
},
{
"input": "PHONE_NUMBER or WHATSAPP_ID"
}
],
"initiated_by": "business"
}
]
},
"field": "group_participants_update"
}
]
}
]
}Group participant remove with participants partially fails
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID",
},
"groups": [
{
"timestamp": "TIMESTAMP",
"group_id": "GROUP_ID",
"type": "group_participants_remove",
"request_id": "REQUEST_ID",
"initiated_by": "business",
"removed_participants": [
{
"input": "PHONE_NUMBER or WHATSAPP_ID"
}
],
"failed_participants": [
{
"input": "PHONE_NUMBER or WHATSAPP_ID",
"errors": [
{
"code": "ERROR_CODE",
"message": "ERROR_MESSAGE",
"title": "ERROR_TITLE",
"error_data": {
"details": "ERROR_DETAILS"
}
}
]
}
],
"errors": [
{
"code": "ERROR_CODE",
"message": "Failed to remove some participants from the group",
"title": "Not All Participants Remove Succeeded",
"error_data": {
"details": "ERROR_DETAILS"
}
}
]
}
]
},
"field": "group_participants_update"
}
]
}
]
}Group participant remove fails
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID",
},
"groups": [
{
"timestamp": "TIMESTAMP",
"group_id": "GROUP_ID",
"type": "group_participants_remove",
"request_id": "REQUEST_ID",
"failed_participants": [
{
"input": "PHONE_NUMBER or WHATSAPP_ID"
},
{
"input": "PHONE_NUMBER or WHATSAPP_ID"
}
],
"errors": [
{
"code": "ERROR_CODE",
"message": "ERROR_MESSAGE",
"title": "ERROR_TITLE",
"error_data": {
"details": "ERROR_DETAILS"
}
}
],
"initiated_by": "business"
}
]
},
"field": "group_participants_update"
}
]
}
]
}Group participant leaves webhook
This webhook is sent when a group participant leaves the group. The initiated_by field and only the wa_id in the removed_participants list will point to the participant who left the group.
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID",
},
"groups": [
{
"timestamp": "TIMESTAMP",
"group_id": "GROUP_ID",
"type": "group_participants_remove",
"removed_participants": [
{
"wa_id": "WHATSAPP_ID",
}
],
"initiated_by": "participant"
}
]
},
"field": "group_participants_update"
}
]
}
]
}group_settings_update webhooks
Group settings update succeed
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "<ID>",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID"
},
"groups": [
{
"timestamp": "TIMESTAMP",
"group_id": "GROUP_ID",
"type": "group_settings_update",
"request_id": "REQUEST_ID",
"profile_picture": {
"mime_type": "image/jpeg",
"update_successful": true,
"sha256": "PHOTO_HASH",
},
"group_subject": {
"text": "Test Subject",
"update_successful": true,
},
"group_description": {
"text": "Test Description",
"update_successful": true,
}
}
]
},
"field": "group_settings_update"
}
]
}
]
}Group settings update partial fail
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID"
},
"groups": [
{
"timestamp": "TIMESTAMP",
"group_id": "GROUP_ID",
"type": "group_settings_update",
"request_id": "REQUEST_ID",
"profile_picture": {
"mime_type": "image/jpeg",
"update_successful": true,
"sha256": "PHOTO_HASH",
},
"group_subject": {
"text": "Test Subject",
"update_successful": false,
"errors": [
{
"code": "ERROR_CODE",
"message": "ERROR_MESSAGE",
"title": "ERROR_TITLE",
"error_data": {
"details": "ERROR_DETAILS"
}
}
]
},
"group_description": {
"text": "Test Description",
"update_successful": false,
"errors": [
{
"code": "ERROR_CODE",
"message": "ERROR_MESSAGE",
"title": "ERROR_TITLE",
"error_data": {
"details": "ERROR_DETAILS"
}
}
]
},
"errors": [
{
"code": "ERROR_CODE",
"message": "ERROR_MESSAGE",
"title": "ERROR_TITLE",
"error_data": {
"details": "ERROR_DETAILS"
}
}
]
}
]
},
"field": "group_settings_update"
}
]
}
]
}Group settings update total fail
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "<ID>",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER"
},
"groups": [
{
"timestamp": "TIMESTAMP",
"group_id": "GROUP_ID",
"request_id": "REQUEST_ID",
"type": "group_settings_update",
"profile_picture": {
"mime_type": "image/jpeg",
"sha256": "PHOTO_HASH",
"update_successful": false,
"errors": [
{
"code": "ERROR_CODE",
"message": "ERROR_MESSAGE",
"title": "ERROR_TITLE",
"error_data": {
"details": "ERROR_DETAILS"
}
}
]
},
"group_subject": {
"text": "Test Subject",
"update_successful": false,
"errors": [
{
"code": "ERROR_CODE",
"message": "ERROR_MESSAGE",
"title": "ERROR_TITLE",
"error_data": {
"details": "ERROR_DETAILS"
}
}
]
},
"group_description": {
"text": "Test Description",
"update_successful": false,
"errors": [
{
"code": "ERROR_CODE",
"message": "ERROR_MESSAGE",
"title": "ERROR_TITLE",
"error_data": {
"details": "ERROR_DETAILS"
}
}
]
},
"errors": [
{
"code": "ERROR_CODE",
"message": "ERROR_MESSAGE",
"title": "ERROR_TITLE",
"error_data": {
"details": "ERROR_DETAILS"
}
}
]
}
]
},
"field": "group_settings_update"
}
]
}
]
}group_status_update webhooks
WhatsApp uses advanced machine learning technology to evaluate group information including group subjects, profile photos, and group descriptions. We also provide simple options for users to make reports to us from any chat.
We may prevent further activity in chat groups to comply with our legal obligations. We may also prevent further chat activity when a group admin is in violation of our Terms of Service.
You may receive a webhook if a group you manage is suspended. You may also receive a webhook if a suspended group you manage becomes clear of suspensions.
Group suspended
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID"
},
"groups": [
{
"timestamp": "TIMESTAMP",
"type": "group_suspend",
"group_id": "GROUP_ID"
}
]
},
"field": "group_status_update"
}
]
}
]
}Group suspension cleared
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "DISPLAY_PHONE_NUMBER",
"phone_number_id": "PHONE_NUMBER_ID"
},
"groups": [
{
"timestamp": "TIMESTAMP",
"type": "group_suspend_cleared",
"group_id": "GROUP_ID"
}
]
},
"field": "group_status_update"
}
]
}
]
}Group message status webhooks
When you send messages to a group, you will receive a status webhook when the message is sent, delivered, and read. Instead of sending multiple webhooks for each status update, WhatsApp may send an aggregated webhook.
There are two types of aggregated message status webhooks you can receive.
Multiple participants, single message
If you send a message and are set to receive several read or delivered statuses from participants, you receive a single, aggregated webhook that contains multiple status objects.
Each webhook you receive will be in reference to a single message sent to a single group and a single status type, that is, single group, single status by multiple participants for a single message.
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "BUSINESS_DISPLAY_PHONE_NUMBER",
"phone_number_id": "BUSINESS_PHONE_NUMBER_ID"
},
"statuses": [
{
"id": "WHATSAPP_MESSAGE_ID",
"status": "read",
"timestamp": "WEBHOOK_TRIGGER_TIMESTAMP",
"recipient_id": "GROUP_ID",
"recipient_type": "group",
"recipient_participant_id": "GROUP_PARTICIPANT_PHONE_NUMBER_1",
"conversation": {
"id": "CONVERSATION_ID",
"origin": {
"type": "CONVERSATION_CATEGORY"
},
"pricing": {
"billable": IS_BILLABLE,
"pricing_model": "PRICING_MODEL",
"category": "CONVERSATION_CATEGORY"
}
}
},
{
"id": "WHATSAPP_MESSAGE_ID",
"status": "read",
"timestamp": "WEBHOOK_TRIGGER_TIMESTAMP",
"recipient_id": "GROUP_ID",
"recipient_type": "group",
"recipient_participant_id": "GROUP_PARTICIPANT_PHONE_NUMBER_2",
"conversation": {
"id": "CONVERSATION_ID",
"origin": {
"type": "CONVERSATION_CATEGORY"
},
"pricing": {
"billable": IS_BILLABLE,
"pricing_model": "PRICING_MODEL",
"category": "CONVERSATION_CATEGORY"
}
}
}
]
},
"field": "messages"
}
]
}
]
}Multiple messages, single participant
If you send multiple messages to a group and are set to receive several read or delivered statuses from a single participant, WhatsApp may send you a single, aggregated webhook that contains multiple status objects.
Each webhook you receive will be in reference to multiple messages sent to a single group and a single status type, that is, single group, single status by single participant for multiple messages.
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "BUSINESS_DISPLAY_PHONE_NUMBER",
"phone_number_id": "BUSINESS_PHONE_NUMBER_ID"
},
"statuses": [
{
"id": "WHATSAPP_MESSAGE_ID_1",
"status": "delivered",
"timestamp": "WEBHOOK_TRIGGER_TIMESTAMP",
"recipient_id": "GROUP_ID",
"recipient_type": "group",
"recipient_participant_id": "GROUP_PARTICIPANT_PHONE_NUMBER",
"conversation": {
"id": "CONVERSATION_ID",
"origin": {
"type": "CONVERSATION_CATEGORY"
},
"pricing": {
"billable": IS_BILLABLE,
"pricing_model": "PRICING_MODEL",
"category": "CONVERSATION_CATEGORY"
}
}
},
{
"id": "WHATSAPP_MESSAGE_ID_2",
"status": "delivered",
"timestamp": "WEBHOOK_TRIGGER_TIMESTAMP",
"recipient_id": "GROUP_ID",
"recipient_type": "group",
"recipient_participant_id": "GROUP_PARTICIPANT_PHONE_NUMBER",
"conversation": {
"id": "CONVERSATION_ID",
"origin": {
"type": "CONVERSATION_CATEGORY"
},
"pricing": {
"billable": IS_BILLABLE,
"pricing_model": "PRICING_MODEL",
"category": "CONVERSATION_CATEGORY"
}
}
}
]
},
"field": "messages"
}
]
}
]
}Group message delivered
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "BUSINESS_DISPLAY_PHONE_NUMBER",
"phone_number_id": "BUSINESS_PHONE_NUMBER_ID"
},
"statuses": [
{
"id": "WHATSAPP_MESSAGE_ID",
"status": "delivered",
"timestamp": "WEBHOOK_TRIGGER_TIMESTAMP",
"recipient_id": "GROUP_ID",
"recipient_type": "group",
"participant_recipient_id": "GROUP_PARTICIPANT_PHONE_NUMBER",
"conversation": {
"id": "CONVERSATION_ID",
"origin": {
"type": "CONVERSATION_CATEGORY"
}
},
"pricing": {
"billable": IS_BILLABLE,
"pricing_model": "PRICING_MODEL",
"category": "CONVERSATION_CATEGORY"
}
}
]
},
"field": "messages"
}
]
}
]
}Pricing information
Status messages webhooks that contain pricing information will have:
CONVERSATION_CATEGORYset to one of:group_marketing— Indicates a marketing conversation.group_utility— Indicates a utility conversation.group_service— Indicates a service conversation.
IS_BILLABLEset to one of:true— Indicates a billable conversation.false— Indicates a non-billable conversation.
PRICING_MODELset toPMP.
Learn more about Groups API pricing
Group message read (With pricing)
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "BUSINESS_DISPLAY_PHONE_NUMBER",
"phone_number_id": "BUSINESS_PHONE_NUMBER_ID"
},
"statuses": [
{
"id": "WHATSAPP_MESSAGE_ID",
"status": "read",
"timestamp": "WEBHOOK_TRIGGER_TIMESTAMP",
"recipient_id": "GROUP_ID",
"recipient_type": "group",
"participant_recipient_id": "GROUP_PARTICIPANT_PHONE_NUMBER",
"conversation": {
"id": "CONVERSATION_ID",
"origin": {
"type": "CONVERSATION_CATEGORY"
}
},
"pricing": {
"billable": IS_BILLABLE,
"pricing_model": "PRICING_MODEL",
"category": "CONVERSATION_CATEGORY"
}
}
]
},
"field": "messages"
}
]
}
]
}Group message read (Without pricing)
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WHATSAPP_BUSINESS_ACCOUNT_ID",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "BUSINESS_DISPLAY_PHONE_NUMBER",
"phone_number_id": "BUSINESS_PHONE_NUMBER_ID"
},
"statuses": [
{
"id": "WHATSAPP_MESSAGE_ID",
"status": "read",
"timestamp": "WEBHOOK_TRIGGER_TIMESTAMP",
"recipient_id": "GROUP_ID",
"recipient_type": "group",
"participant_recipient_id": "GROUP_PARTICIPANT_PHONE_NUMBER"
}
]
},
"field": "messages"
}
]
}
]
}Groups API Error Codes
| Code | Description | HTTP Status Code |
|---|---|---|
131020Bad Group | Cannot send messages to single member groups. | 400Bad Request |
131041Group unknown | The group was not found, either because it doesn’t exist or you are not a member. | 400Bad Request |
131059Invalid cursor | The cursor has either expired or become corrupted. Start pagination from the beginning again. | 400Bad Request |
131201Request partially succeeded | Not all participant-level operations in the request succeeded. | 206Partial Content Success |
131202Duplicate participant | Duplicate participants in the participant array input. | 400Bad Request |
131204Participant overlimit | Group participant size exceeds limit. | 400Bad Request |
131207Group suspended | The group violates platform policies. | 403Forbidden |
131208Group Rate Limit Hit | Group operation failed because there were too many group operations from this phone number in a short period. | 429Too Many Requests |
131209Invalid Group Profile Picture Aspect Ratio | Width and height of the image must be equal. | 400Bad Request |
131210Image is Too Small to Process | Image width and height must be greater than 192px. | 400Bad Request |
131211Group create limit reached | Reached the limit for the maximum number of groups that can be created for this number. | 400Bad Request |
131212Participant is not a part of the group | Participant is not a part of the group. | 400Bad Request |
131213Group join request does not exist | Group join request does not exist. | 400Bad Request |
131214Group creation is temporarily disabled | Group creation is temporarily disabled due to excessive marketing messages sent by the WABA in customer service window over the past 7 days. | 400Bad Request |
131215This phone number is not eligible to access Groups APIs | Groups APIs are only available for eligible phone numbers. Check eligibility for Groups APIs in our documentation - /documentation/business-messaging/whatsapp/groups/get-started | 400Bad Request |
Groups API Pricing
Per-message pricing on Groups API
Groups API uses Cloud API’s per-message pricing model to determine if a given message is billable. However, you are charged each time a billable message is delivered to someone in the group.
For example, if you send a (billable) marketing template message to a group with 5 WhatsApp users and it is delivered to all 5 users, you would be charged for 5 delivered messages at the going marketing message rate for each recipient’s country calling code.
If the message was delivered to only 4 of the 5 users, you would only be charged for the 4 delivered messages.
How customer service windows work with Groups API
Customer service windows work differently when using Groups API.
When any WhatsApp user in the group messages you, a customer service window is opened between you and the entire group (or is refreshed, if one already exists). This allows you to send utility and marketing template messages, or free form messages, for free.
This is different from 1:1 messaging, where when a WhatsApp user messages you, a customer service window is opened between you and that customer (or is refreshed, if one already exists).
Everything else about customer service windows remains the same.
Pricing information in message status webhook
Pricing information for messages sent using Groups API is included in messages status webhooks.
How read and delivered message status webhooks are processed
In order for a message status to be considered read, it must have been at least delivered.
In some scenarios, such as when a user is present in the chat thread when a message arrives, the message is marked delivered and read nearly simultaneously. In this and other similar scenarios, the delivered webhook is not sent back. This is because it is implied that the message was delivered since it has been read.
How pricing data is displayed in the Message Status webhook
Not all Message Status webhooks include pricing information.
With the introduction of Per-message Pricing, pricing data can be present in sent, delivered or read status webhook. If a message is charged, you can expect that at least one webhook (delivered or read) will contain the pricing information.
Sent message status webhook
// All versions
"pricing": {
"billable": "<IS_BILLABLE>",
"pricing_model": "<PRICING_MODEL>", // new value, see table below
"type": "<PRICING_TYPE>", // new property, see table below
"category": "<CONVERSATION_CATEGORY>"
}Delivered / Read message status webhook
// Version 24.0 and higher
"pricing": {
"billable": "<IS_BILLABLE?>",
"pricing_model": "<PRICING_MODEL>", // new value, see table below
"type": "<PRICING_TYPE>", // new property, see table below
"category": "<CONVERSATION_CATEGORY>"
}
// Version 23.0 and lower
"conversation": {
"id": "<CONVERSATION_ID>", // new behavior, see table below
"expiration_timestamp": "<CONVERSATION_EXPIRATION_TIMESTAMP>",
"origin": {
"type": "<CONVERSATION_CATEGORY>"
}
},
"pricing": {
"billable": "<IS_BILLABLE?>",
"pricing_model": "PMP", // Value is now "PMP" instead of "CBP"
"type": "<PRICING_TYPE>", // new property, see table below
"category": "<PRICING_CATEGORY>"
}Parameters
| Placeholder | Description |
|---|---|
<CONVERSATION_ID> | Version 24.0 and higher: - The conversation object will be omitted entirelyVersion 23.0 and lower: - Value will now be set to a unique ID per-message, instead of per-conversation. |
<CONVERSATION_CATEGORY> | Not changing. |
<CONVERSATION_EXPIRATION_TIMESTAMP> | Not changing. |
<IS_BILLABLE?> | Not changing. However, the billable property will be deprecated in a future versioned release. Start using pricing.type and pricing.category together to determine if a message is billable, and if so, its billing rate. |
<PRICING_TYPE> | New property. Values can be: - regular — indicates the message is billable.- free_group_customer_service — indicates the message is free because it was either a utility template message or non-template message sent within a customer service window. |
<PRICING_CATEGORY> | Values are not changing, but can now be interpreted as follows: * group_marketing — indicates a marketing template message.* group_utility — indicates a utility template message.* group_service — indicates a non-template message. |
Identifying billable messages
Billable messages have pricing.type set to regular. The pricing.category value indicates the rate (group_marketing or group_utility).
Identifying free messages
Free messages have pricing.type set to free_group_customer_service. The pricing.category value tells you why it was free:
group_utility— the message was sent within an open group customer service window.group_service— all non-template messages are free.
Messaging analytics for Groups API
The analytics field provides the number and type of messages sent and delivered by the phone numbers associated with a specific WABA — for conversation metrics, see Conversation Analytics.
You can get analytics for messages sent using Groups API through the ISV metrics endpoint, which forwards the filters to Meta:
GET /metrics/{v}/{did}The component resolves the token and WABA from the {did} and queries Meta with fields=analytics.<FILTER_PARAMETER>.<FILTER_PARAMETER>....
Filter parameters for messaging analytics
For a full list of messaging analytics filter parameters, view the Messaging Analytics reference.
Changes to filter parameters for Groups API
| Name | Description |
|---|---|
product_typestype: Array | Optional. The types of messages (notification messages and/or customer support messages) for which you want to retrieve notifications. Provide an array and include: * 101 for group notification messages* 102 for group customer support messages.* 103 for inbound group messagesIf the above values are not provided, the API call will return analytics for all messages together. Inbound product type cannot be queried together with other product types, or you will see an error similar to the one below: ```https |
| { | |
| “error”: { | |
| “message”: “Invalid parameter”, | |
| “type”: “OAuthException”, | |
| “code”: 100, | |
| “error_subcode”: 2388077, | |
| “is_transient”: false, | |
| “error_user_title”: “Insight Invalid Product Type Combination”, | |
| “error_user_msg”: “Unable to query this combination of product types. Please query individually and try again.”, | |
| } | |
| } |
#### Response value
Successful responses to the analytics API when querying Groups API message data will return an object similar to the following:
**Note: The country code filter is not supported for group sent messages.**
```https
With Country code filter
{
"analytics": {
"phone_numbers": [
"16505550111",
"16505550112",
"16505550113"
],
"country_codes": [
"US",
"BR"
],
"granularity": "DAY",
"data_points": [
{
"start": 1543543200,
"end": 1543629600,
"sent": 196093,
"delivered": 179715,
"groups_delivered": 4
},
{
"start": 1543629600,
"end": 1543716000,
"sent": 147649,
"delivered": 139032
}
# more data points
]
},
"id": "102290129340398"
}
Without Country code filter
{
"analytics": {
"phone_numbers": [
"16505550111",
"16505550112",
"16505550113"
],
"granularity": "DAY",
"data_points": [
{
"start": 1543543200,
"end": 1543629600,
"sent": 196093,
"delivered": 179715,
"groups_sent": 2,
"groups_delivered": 4
},
{
"start": 1543629600,
"end": 1543716000,
"sent": 147649,
"delivered": 139032
}
# more data points
]
},
"id": "102290129340398"
}Pricing analytics for Groups API
The pricing_analytics field allows you to get pricing breakdowns for any messages delivered within a specified date range.
You can get it through the ISV metrics endpoint, which forwards the filters to Meta:
GET /metrics/{v}/{did}The component resolves the token and WABA from the {did} and queries Meta with fields=pricing_analytics and the following filters:
.start(<START>)
.end(<END>)
.granularity(<GRANULARITY>)
.phone_numbers(<PHONE_NUMBERS>)
.country_codes(<COUNTRY_CODES>)
.metric_types(<METRIC_TYPES>)
.pricing_types(<PRICING_TYPES>)
.pricing_categories(<PRICING_CATEGORIES>)
.dimensions(<DIMENSIONS>)Filter parameters for pricing analytics
For a full list of messaging analytics filter parameters, view the Messaging Analytics reference.
Changes to filter parameters for Groups API
| Name | Description |
|---|---|
<PRICING_CATEGORIES>Array of strings | Optional. Array of pricing categories. If you send an empty array, you receive results for all pricing categories. Values can be: * GROUP_MARKETING: Group messages charged the marketing rate.* GROUP_SERVICE: Group messages that were not charged. Includes all non-template messages and utility messages sent inside of a customer service window.* GROUP_UTILITY: Group messages charged the utility rate. |
<PRICING_TYPES>Array of strings | Optional. Array of pricing types. If you send an empty array, you receive results for all pricing types. Values can be: * FREE_GROUP_CUSTOMER_SERVICE: Free group messages. These are non-template messages and utility messages sent within group customer service windows.* REGULAR: Billable messages. Includes all authentication and marketing template messages, and any utility template messages sent outside of a customer service window. |
Rate cards
Warning: Group utility messages are not eligible for volume tiers.
Messaging rates for Groups API are the same as per-messaging pricing rates for 1 to 1 messaging.
View per-message pricing rate cards
Groups API FAQ
What happens when I delete a group?
- No members, including you, will be able to message the group.
- Cloud API delivers any messages or statuses it received before you deleted the group, so you may still receive webhooks for those messages or statuses.
Why can’t a participant join the group using my invite link?
Some possible reasons include:
- The invite link might have been deleted.
- You removed the participant from the group previously.
- The group is already full.
How can I send my invite link to users?
- You can send the invite link over a 1:1 conversation.
- A new utility template is available in the Template Library to send group invite links.
- You can also create custom, free-form marketing templates.
What countries is Groups available in?
- Groups is available in all countries Cloud API is available in.