---
title: "Update a WhatsApp conversation"
canonical: "https://bird.com/docs/api/reference/update-whatsapp-conversation"
---

# Update a WhatsApp conversation

`PATCH /v1/whatsapp/conversations/{conversation_id}`

Updates assignment, inbox status, labels, or shared workspace read state. Every field is optional and an omitted one is left unchanged.

`assigned_to` takes a user ID, `me` for the user making the request, or null to unassign. The user must be a member of this workspace. `me` needs a request made as a user: an API key has no user, so passing `me` with one returns a `422`.

`labels` replaces the conversation's labels with the set you send, so include every label you want to keep. Pass an empty array to clear them.

Pass `read` with a date-time cutoff for message `created_at` to acknowledge received inbound messages at or before it in the workspace inbox. Messages sharing the timestamp are included together; later arrivals remain unread. This does not send the customer a WhatsApp read receipt.

Labels are yours alone: Bird sets none of its own, and changing them does not mark the conversation read or unread.

Set `inbox_status` to `resolved` to finish the inbox work, or `open` to reopen it. New inbound messages reopen resolved conversations. Inbox status does not change read state or the customer-service window.

Control is not changed here. Moving a conversation between the agent and your application needs WhatsApp's agreement and can be refused, so you take and release control in the dashboard inbox.

## Servers

- `https://{region}.platform.bird.com`: Regional API endpoint. Use the host for the region your organization is hosted in. Official Bird SDKs and the CLI select it automatically from your API key, so you rarely need to set it by hand.
  - `region`: `us1`, `eu1`. Default: `us1`. The region your organization's data is hosted in.
- `https://platform.bird.com`: Region-independent endpoint for authentication and account administration.
- `http://localhost:8080`: Local development.

## Authentication

Use one authentication option:

- `BearerAuth`: HTTP bearer authentication. Pass the API key as a bearer token in the `Authorization` header. Workspace
keys use `bk_{region}_*`; organization master keys use `bm_{region}_*`.
The prefix identifies the region and selects the
API endpoint. Official Bird SDKs and the CLI derive the region from the key.

- `CookieAuth`: Send `bird_session` in cookie. Session cookie set after signing in to the Bird dashboard. The cookie
value is an opaque session token; no session data is stored in the cookie
itself.

## Code samples

**TypeScript**

```ts
// labels replaces the whole set, so send every label to keep.
const conversation = await bird.whatsapp.conversations.update("wacv_01krdgeqcxet5s7t44vh8rt9mg", {
  assigned_to: "usr_01krdgeqcxet5s7t44vh8rt9mg",
  labels: ["billing", "vip"],
  inbox_status: "resolved",
});
console.log(conversation.inbox_status);
```

Examples: [TypeScript](/docs/api/reference/update-whatsapp-conversation.ts.md) · [Python](/docs/api/reference/update-whatsapp-conversation.py.md) · [Go](/docs/api/reference/update-whatsapp-conversation.go.md) · [PHP](/docs/api/reference/update-whatsapp-conversation.php.md) · [CLI](/docs/api/reference/update-whatsapp-conversation.cli.md) · [MCP](/docs/api/reference/update-whatsapp-conversation.mcp.md) · [cURL](/docs/api/reference/update-whatsapp-conversation.curl.md)

## Example response `200`

```json
{
  "id": "wacv_01krdgeqcxet5s7t44vh8rt9mg",
  "business_phone_number": "+15550001234",
  "recipient": {
    "bsuid": "US.13491208655302741918",
    "phone_number": "+15550001111",
    "display_name": "Jamie Rivera",
    "username": "jamierivera"
  },
  "inbox_status": "open",
  "control": "bird",
  "assigned_to": "usr_01krdgeqcxet5s7t44vh8rt9mg",
  "service_window": {
    "status": "open",
    "ends_at": "2026-09-23T10:35:00Z"
  },
  "last_message": {
    "id": "wam_01krdgeqcxet5s7t44vh8rt9mg",
    "direction": "outbound"
  },
  "labels": [
    "billing",
    "vip"
  ]
}
```

## Path parameters

- `conversation_id` (string, required): Conversation identifier. Starts with `wacv_`.

## Header parameters

- `Idempotency-Key` (string, optional)

  Client-supplied key. On operations supporting request deduplication, a retained
  response is replayed for duplicate requests with the same key within the
  idempotency window (3 hours by default). This protection requires a workspace,
  organization, or staff-account scope. User-only and unscoped unauthenticated operations,
  streams, and operations with a separate replay contract do not use this
  response replay.

  On a supported operation, if idempotency protection is unavailable before execution, the API returns
  `503 IdempotencyUnavailable` (E01033) without executing this attempt. Retry with
  backoff using the same key and request. An operation that takes effect before
  its response is retained can still execute again on retry.

  Two distinct 409 errors signal misuse:

  - `request_in_progress` (E01004): The same key is currently being
    processed by a concurrent request. Wait briefly and retry. The lock expires within 30 seconds.
  - `idempotency_key_reuse` (E01005): The same key has already completed
    against a different request body or method. Generate a new key.

  Recommended key format is `<event-type>/<entity-id>` (for example `welcome-user/usr_abc123`).
- `X-Workspace-Id` (string, optional): Workspace context for the request. Required for dashboard authentication and master keys. Workspace keys and access tokens already identify their workspace; send that workspace or omit the header. A different one is rejected.
- `X-Organization-Id` (string, optional): Organization context for the request. Required for dashboard authentication. An API key or access token carries its own organization, so send either that organization or no header at all; a different one is rejected.

## Request body

- `assigned_to` (nullable string): User to assign this conversation to. Pass a workspace member's user ID, `me` for the signed-in user, or null to unassign it. An API key cannot use `me` and receives a `422` response.
- `inbox_status` (string)

  Whether the conversation needs attention in the workspace inbox. Set it to `resolved` when the work is finished. A new inbound message reopens the same conversation. Changing inbox status preserves message history and does not change the channel's permission to send messages or mark messages read.

  Possible values: `open`, `resolved`
- `labels` (array of string)

  Labels chosen by your workspace. On update, this replaces the full set; pass an empty array to clear every label. Labels do not change read state or inbox status.

  Each label must contain 1 to 64 characters, with no commas, control characters, or leading or trailing whitespace. Duplicate labels are rejected. The names `all`, `archived`, `assigned`, `closed`, `deleted`, `draft`, `drafts`, `flagged`, `important`, `inbox`, `junk`, `muted`, `none`, `open`, `pinned`, `read`, `snoozed`, `spam`, `starred`, `trash`, and `unread` are reserved in every casing.
- `read` (string): Mark received inbound messages with created_at at or before this timestamp as read in the shared workspace inbox. Messages sharing the timestamp are included together. Later arrivals remain unread until another read update. This does not send a read receipt to the customer or change inbox status. Omit to leave read state unchanged.

## Response body

- `id` (string, required): Conversation ID.
- `business_phone_number` (nullable string, required): Your WhatsApp business phone number this conversation runs on, in E.164 format. It stays the same when you remove the number and connect it again. Null when Bird holds no phone number for it.
- `recipient` (object, required): The other side of the conversation: the contact, or the group it takes place in. A group conversation carries `group_id` and null contact identity fields.
- `recipient.bsuid` (nullable string, required): Meta's business-scoped user ID for the contact, or null when unknown.
- `recipient.phone_number` (nullable string, required): Contact phone number in E.164 format, or null when unknown.
- `recipient.display_name` (nullable string, required): Display name from the contact's WhatsApp profile, or null when none has been recorded.
- `recipient.username` (nullable string, required): Contact's WhatsApp username without a leading `@`, or null when none has been recorded. Messages cannot be addressed by username.
- `recipient.group_id` (string): Group this conversation belongs to. Omitted for a conversation with one contact.
- `inbox_status` (string, required)

  Whether the conversation needs attention in the workspace inbox. Set it to `resolved` when the work is finished. A new inbound message reopens the same conversation. Changing inbox status preserves message history and does not change the channel's permission to send messages or mark messages read.

  Possible values: `open`, `resolved`
- `control` (string, required)

  Who answers this conversation right now. You take and release control in the dashboard inbox.

  Possible values (may grow over time): `bird`, `meta_business_agent`
- `assigned_to` (nullable string, required): The user this conversation is assigned to. Null when unassigned. Assignment is not rechecked against workspace membership on read, so it can still name a user whose access was removed.
- `service_window` (nullable object, required): Customer-service window for a contact. Null for group conversations.
- `service_window.status` (string, required)

  Whether the customer-service window is open right now.

  - `open`: the contact wrote within the last 24 hours, so free-form messages are accepted.
  - `closed`: the window has passed, or the contact has never written, so only a template can be sent.

  Possible values: `open`, `closed`
- `service_window.ends_at` (nullable string, required): When the window closes, or closed. Null when no inbound message has been recorded, in which case `status` is `closed`.
- `last_message` (nullable object, required): A pointer to the most recent message in this conversation. It names the message; read its content through the conversation's message list. Null when the conversation has no message yet.
- `last_message.id` (string, required): ID of the message.
- `last_message.direction` (string, required)

  `inbound` for a message received from the contact, `outbound` for one your workspace or the agent sent.

  Possible values: `outbound`, `inbound`
- `last_message.created_at` (string, required): The message's `created_at`: when it was accepted (outbound) or received (inbound). The conversation list is ordered by it. It only moves forward: a message that arrives late and belongs earlier in the conversation does not pull it back.
- `unread_count` (integer, required): Number of inbound messages the workspace has not acknowledged. Shared across the workspace. Sending a reply does not mark messages read.
- `labels` (array of string, required): Workspace labels on this conversation. Labels do not change read state or inbox status.
- `created_at` (string, required): When Bird opened this conversation.
- `updated_at` (string, required): When this conversation last changed.

## Related resources

- [Should I use a Bird SDK or call the API directly?](/explained/platform/should-i-use-an-sdk-or-call-the-api-directly) (answer)
- [Build your first integration](/learn/paths/integration) (course)
- [Send your first email](/docs/get-started/send-your-first-email) (docs)

[Get an implementation brief](/learn/workspace?topic=api-basics)
