---
title: "Remove a participant from a WhatsApp group"
method: DELETE
path: "/v1/whatsapp/groups/{group_id}/participants/{participant_ref}"
tags: ["whatsapp-groups"]
---

# Remove a participant from a WhatsApp group

`DELETE /v1/whatsapp/groups/{group_id}/participants/{participant_ref}`

## Request

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

Removes one person from the group. Name them by either identifier the
group's `participants` list them under: `bsuid`, which everyone has, or
`phone_number`, which is there only when WhatsApp shares it.

**Removal cannot be undone.** WhatsApp blocks a removed person from joining
the group by invite link, and the block follows the person rather than the
link they were removed under: rotating the invite link does not let them
back in. There is no add operation to pair with this one either, because
WhatsApp lets nobody be added directly and people join only by opening the
link. So nothing returns someone to this group once they are out, and
reaching them again means creating another group and inviting them to it.

The `202` response is the removal accepted, not applied: WhatsApp can still
refuse it, which arrives on the `group_participants_update` webhook. The
outcome lands on that participant's own `last_operation`, `pending` until the
webhook settles it, so removing several people at once gives each their own
state and their own failure rather than one shared verdict. Re-read the group
to see who is left.

A second removal of the same participant while theirs is `pending` returns a
`409` `WhatsAppGroupUpdateInProgress`; removing a different participant does
not. Only an `active` group can be changed; any other status returns a `409`
`WhatsAppGroupNotActive`.

## Path parameters

- `group_id` string, required
- `participant_ref` string, required

## Headers

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

## Response `202`

Removal accepted; the group as Bird holds it. Re-read for who is left.

- 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/6cec81ac4862?raw)
