---
title: "Update a WhatsApp group"
method: PATCH
path: "/v1/whatsapp/groups/{group_id}"
tags: ["whatsapp-groups"]
---

# Update a WhatsApp group

`PATCH /v1/whatsapp/groups/{group_id}`

## Request

- Base URL: `https://us1.platform.bird.com`
- URL: `https://us1.platform.bird.com/v1/whatsapp/groups/{group_id}`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `bird_session`

Changes what participants see at the top of the group: its subject, its
description, and its picture. Fields you omit are left as they are; send
`null` to clear the description. A `null` picture clears the one Bird
stores, but WhatsApp offers no way to take a group's photo down, so
participants keep seeing the current one until a new picture replaces it.

WhatsApp applies each field separately, so a change can be part-applied:
one field refused while the others take effect. The `202` response is the
change accepted, not applied: it echoes the group as Bird holds it, with
`last_operation` at `pending`. WhatsApp reports the outcome on the
`group_settings_update` webhook, which settles `last_operation` to `success`
or `failed` and fills its `results` with one entry per field, so a part-apply
says which field was refused and why. Re-read the group to see what took
effect.

Two `409`s guard this, and `status` is checked first: a group that is not
`active` returns `WhatsAppGroupNotActive`, whatever its `last_operation` says.
That matters for a group still being created, which is `pending` on both counts
at once, and the group-level answer is the more useful one, since no change can
land until it exists. Once the group is `active`, a change already outstanding
returns `WhatsAppGroupUpdateInProgress` while `last_operation.status` is
`pending`.

The picture names a file in your workspace's media library, and WhatsApp
takes only a square JPEG. `join_approval_mode` and the administering number
are fixed when the group is created and cannot be changed here.

## Path parameters

- `group_id` string, required

## Headers

- `Idempotency-Key` string
- `X-Workspace-Id` string
- `X-Organization-Id` string

## Request body

- WhatsAppGroupUpdate: The changes to make. Fields you omit are left as they are. WhatsApp applies each field separately, so one can be rejected while the others take effect; the group's `updated_at` moves when a change lands.
  - `subject` string: A new name for the group. Participants see the change in the group's chat.
  - `description` string, nullable: A new description for the group. Send `null` to clear it; an empty string is a `422` rather than a second way to clear.
  - `profile_picture_url` string, nullable: A new picture for the group, naming a file in your workspace's media library. WhatsApp takes a square JPEG of at least 192 by 192 pixels and up to 5 MB; anything else returns a `422`. Sending `null` clears the picture Bird stores, and an empty string is a `422` rather than a second way to clear it; WhatsApp has no operation for removing a group's photo, so the one participants see stays until another picture replaces it.

## Response `202`

Change accepted; the group as Bird holds it. Re-read for what WhatsApp applied.

- WhatsAppGroup: A WhatsApp group your business created and administers. People join by opening its invite link, not by being added.
  - `id` string, required
  - `whatsapp_number_id` string, required
  - `waba` string, nullable, required: Meta's identifier for the WhatsApp Business Account recorded when the group was created. This is a historical snapshot, not a live account directory projection. Null for a number we operate on your behalf, whose account is not yours to see.
  - `subject` string, required: The group's name, shown to participants and to anyone who opens the invite link.
  - `description` string, nullable: The group's description, shown alongside the subject. Null when the group has none.
  - `status` 'pending' | 'active' | 'suspended' | 'deleted' | 'failed', required: Where the group stands. Values, in lifecycle order: - `pending` means the request to create the group has been accepted and WhatsApp has not confirmed it yet. The group has no invite link, and it cannot be messaged or changed. - `active` means the group exists at WhatsApp and carries an invite link. Only an active group can be messaged. - `suspended` means WhatsApp has stopped activity in the group, which it does when a group breaks its policies. Sends fail while it lasts, and WhatsApp can lift it on its own. - `deleted` means the group is gone, either because you deleted it or because WhatsApp removed it. Every participant lost access, and the state is terminal. - `failed` means WhatsApp refused to create the group; `last_operation.last_error` says why. The state is terminal, so create another group rather than retrying this one.
  - `join_approval_mode` 'auto_approve' | 'approval_required', required: How someone opening the invite link gets in: - `auto_approve` means they join the moment they open the link. This is the default when the group is created. - `approval_required` means opening the link raises a join request you approve or reject. Fixed when the group is created.
  - `invite_link` string, nullable: The link that lets someone join the group, which is the only way in. A group has one link at a time. Null while the group is `pending`, since WhatsApp issues the link when it confirms the group. Rotating it through `POST /v1/whatsapp/groups/{group_id}/invite-link/rotate` replaces it, and every link the group had before then stops working.
  - `participants` WhatsAppGroupParticipant[]: Who is in the group, as of the last update WhatsApp sent, and the whole set rather than a page: WhatsApp holds a group to a handful of people, so there is never a page's worth to return. The business number that created the group is its admin and is not listed.
    - `bsuid` string, required: Business-scoped user ID, Meta's identifier for this person against your business. The one identifier every participant has: WhatsApp always sends it, and it is stable for as long as they are in the group.
    - `phone_number` string: Phone number in E.164 format. Absent when WhatsApp withholds it, which it does for anyone who has not shared their number with your business, so a group is normally a mix of participants with one and without.
    - `username` string: The WhatsApp username this person chose. Absent when they have none, and not an identifier to address them by: it is theirs to change, so it names them in a list rather than keying anything.
    - `last_operation` WhatsAppGroupOperation: The last change asked of this group or participant, and where it got to. WhatsApp confirms a change on a webhook rather than in its reply, so an operation is `pending` until that arrives. While it is, another change to the same thing is refused with a `409` `WhatsAppGroupUpdateInProgress`; a change to a different participant is not, so several removals can be in flight at once. Absent on something nothing has been asked of yet.
      - `type` 'create' | 'settings_update' | 'delete' | 'remove', required: What was asked of the thing carrying the operation: - `create` and `delete` act on the group itself. - `settings_update` changes the group's subject, description or picture. - `remove` takes one participant out of the group.
      - `status` 'pending' | 'success' | 'failed', required: How the operation ended: - `pending` means WhatsApp accepted the request and has not reported back. Another operation on the same thing is refused while this lasts. - `success` means WhatsApp applied everything asked of it. A change whose success removes its own carrier is never seen in this state: a removed participant and an unpinned message leave their lists, and the entry going away is the confirmation. - `failed` means WhatsApp applied none of it, or only part: `last_error` says why, and on a `settings_update` the per-field `results` say which fields did apply.
      - `requested_at` string, date-time, required: When Bird accepted the request.
      - `settled_at` string, date-time, nullable: When WhatsApp reported the outcome. Null while `pending`.
      - `results` WhatsAppGroupOperationResult[]: Per-field outcomes, on a `settings_update` that has settled. One entry per field the update carried, so a client can put a refusal next to the input it came from. Absent on every other operation type, which change one thing and report it on `status`.
        - `field` 'subject' | 'description' | 'profile_picture_url', required: Which of the group's settings a `settings_update` result reports on.
        - `applied` boolean, required: Whether WhatsApp applied this field. False when it refused this one, whatever it did with the others.
        - `error` WhatsAppGroupError: Why a change to a group did not take effect. Meta documents no code vocabulary for a group refusal, since every sample payload carries an undocumented `code` beside its message, so this relays what it said rather than classifying it, the way a template submission failure does.
          - `description` string, required: WhatsApp's own explanation of the refusal, passed through. Show it to the person who asked for the change; never match on its text. Carries Bird's own words instead when the failure was Bird's verdict, such as a confirmation that never arrived.
          - `meta_error_code` string, nullable: WhatsApp's most specific code for the refusal: its error subcode where it sent one, otherwise its top-level code. Treat it as an opaque string. Null when the failure was Bird's own verdict rather than a WhatsApp refusal.
      - `last_error` WhatsAppGroupError: Why a change to a group did not take effect. Meta documents no code vocabulary for a group refusal, since every sample payload carries an undocumented `code` beside its message, so this relays what it said rather than classifying it, the way a template submission failure does.
        - `description` string, required: WhatsApp's own explanation of the refusal, passed through. Show it to the person who asked for the change; never match on its text. Carries Bird's own words instead when the failure was Bird's verdict, such as a confirmation that never arrived.
        - `meta_error_code` string, nullable: WhatsApp's most specific code for the refusal: its error subcode where it sent one, otherwise its top-level code. Treat it as an opaque string. Null when the failure was Bird's own verdict rather than a WhatsApp refusal.
  - `participant_count` integer, required: How many people are in the group, excluding your business.
  - `pinned_messages` WhatsAppGroupPinnedMessage[]: The group's pins, newest first. WhatsApp holds a few at once, and pinning past that unpins the oldest rather than refusing. No entry here is merely requested. An entry stays listed until it is unpinned, so one whose `pinned_until` has passed is still listed after WhatsApp has taken it off the chat.
    - `message_id` string, required
    - `pinned_until` string, date-time, required: When the pin is due to lapse, projected from the `duration_days` the pin was asked for. An entry stays listed until it is unpinned, so a time in the past means WhatsApp has already taken the message off the chat.
  - `profile_picture_url` string, nullable: Address of the group's picture, as WhatsApp serves it. Null when the group has none.
  - `last_operation` WhatsAppGroupOperation: The last change asked of this group or participant, and where it got to. WhatsApp confirms a change on a webhook rather than in its reply, so an operation is `pending` until that arrives. While it is, another change to the same thing is refused with a `409` `WhatsAppGroupUpdateInProgress`; a change to a different participant is not, so several removals can be in flight at once. Absent on something nothing has been asked of yet.
    - `type` 'create' | 'settings_update' | 'delete' | 'remove', required: What was asked of the thing carrying the operation: - `create` and `delete` act on the group itself. - `settings_update` changes the group's subject, description or picture. - `remove` takes one participant out of the group.
    - `status` 'pending' | 'success' | 'failed', required: How the operation ended: - `pending` means WhatsApp accepted the request and has not reported back. Another operation on the same thing is refused while this lasts. - `success` means WhatsApp applied everything asked of it. A change whose success removes its own carrier is never seen in this state: a removed participant and an unpinned message leave their lists, and the entry going away is the confirmation. - `failed` means WhatsApp applied none of it, or only part: `last_error` says why, and on a `settings_update` the per-field `results` say which fields did apply.
    - `requested_at` string, date-time, required: When Bird accepted the request.
    - `settled_at` string, date-time, nullable: When WhatsApp reported the outcome. Null while `pending`.
    - `results` WhatsAppGroupOperationResult[]: Per-field outcomes, on a `settings_update` that has settled. One entry per field the update carried, so a client can put a refusal next to the input it came from. Absent on every other operation type, which change one thing and report it on `status`.
      - `field` 'subject' | 'description' | 'profile_picture_url', required: Which of the group's settings a `settings_update` result reports on.
      - `applied` boolean, required: Whether WhatsApp applied this field. False when it refused this one, whatever it did with the others.
      - `error` WhatsAppGroupError: Why a change to a group did not take effect. Meta documents no code vocabulary for a group refusal, since every sample payload carries an undocumented `code` beside its message, so this relays what it said rather than classifying it, the way a template submission failure does.
        - `description` string, required: WhatsApp's own explanation of the refusal, passed through. Show it to the person who asked for the change; never match on its text. Carries Bird's own words instead when the failure was Bird's verdict, such as a confirmation that never arrived.
        - `meta_error_code` string, nullable: WhatsApp's most specific code for the refusal: its error subcode where it sent one, otherwise its top-level code. Treat it as an opaque string. Null when the failure was Bird's own verdict rather than a WhatsApp refusal.
    - `last_error` WhatsAppGroupError: Why a change to a group did not take effect. Meta documents no code vocabulary for a group refusal, since every sample payload carries an undocumented `code` beside its message, so this relays what it said rather than classifying it, the way a template submission failure does.
      - `description` string, required: WhatsApp's own explanation of the refusal, passed through. Show it to the person who asked for the change; never match on its text. Carries Bird's own words instead when the failure was Bird's verdict, such as a confirmation that never arrived.
      - `meta_error_code` string, nullable: WhatsApp's most specific code for the refusal: its error subcode where it sent one, otherwise its top-level code. Treat it as an opaque string. Null when the failure was Bird's own verdict rather than a WhatsApp refusal.
  - `suspended_at` string, date-time: When WhatsApp suspended the group. Present only while the group is `suspended`, and gone once WhatsApp lifts the suspension.
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required

## Other responses

- `400`: Bad request
- `401`: Authentication required
- `403`: Insufficient permissions
- `404`: Resource not found
- `409`: Resource conflict
- `422`: The request has invalid field values, violates a business rule, or carries a query parameter the endpoint does not declare. Field validation errors use `type: validation_error` and include the affected fields in `details`. Business-rule errors identify the failed rule in `type`.
- `429`: Rate limit exceeded
- `500`: Internal server error
- `503`: The service is temporarily unavailable. If `Retry-After` is present, wait for that delay before retrying; otherwise, retry with exponential backoff. Reuse the same idempotency key and request when retrying a mutation.

---

[API](https://skmtc.dev/messagebird/apis/bird-api.md) · [All operations](https://skmtc.dev/messagebird/apis/bird-api/llms.txt) · [OpenAPI document](https://skmtc.dev/messagebird/apis/bird-api/revisions/6dfce1179799?raw)
