# Migrations & Deprecations

This page collects API migrations. Most map a deprecated endpoint to its replacement; some are
**data-model migrations** — new fields you should adopt now for a change arriving on an external
timeline, with no endpoint to swap. The [alpha usernames (BSUID)](#alpha-usernames-bsuid) migration
below is the latter kind.

## Deprecation policy

Deprecated endpoints are **still live** — they are marked `deprecated` in the reference (struck
through in the nav) but continue to work, so existing integrations keep running. Unless a removal
date is stated, there is none yet; migrate at your own pace. New integrations should use the
latest endpoints from the start. Each deprecated operation's description links to its replacement.

## Alpha usernames (BSUID)

WhatsApp is rolling out **alpha usernames**. Each customer now has a durable, business-scoped user
id (**BSUID**, e.g. `ZA.1021033720668862`) that is stable for your business even if the customer
changes their phone number, and that is present on inbound events **even when the phone number is
withheld**. Customers may also set an optional **username** (display only).

This is a forward-looking, **adopt-now** migration, not an endpoint deprecation: the phone number
remains the primary identifier today, nothing is being removed on our side, and the timeline is
driven by Meta. Store the BSUID now so you're ready as phone numbers become optional.

### What to change

- **Persist the BSUID as your durable customer key.** On incoming and chatbot webhooks it arrives as
`senderUserId` / `recipientUserId`, with the optional display `username` alongside. Key your CRM /
customer records on it rather than the phone number, which may change or be withheld.
- **Address sends by BSUID where you have it.** Send recipients accept `customerUserId` (the BSUID)
in addition to `to`. Supply both (the phone takes precedence, the BSUID rides along as a fallback),
or `customerUserId` alone to reach a recipient with no phone number.
- **Read the BSUID on chat participants.** The lean `ChatParticipantResponse` carries `userId` (the
customer BSUID) and `username`, so live-chat surfaces can match a customer even when the number is
absent.


### Where the fields appear

| Surface | Fields | Reference |
|  --- | --- | --- |
| Incoming & chatbot webhooks | `senderUserId`, `recipientUserId`, `username` | [Webhooks guide](/guides/webhooks#webhook-payload-schemas) |
| Send recipients | `customerUserId` | [WhatsApp Messaging](/guides/whatsapp-messaging), [Conversations](/guides/conversations) |
| Chat participants | `userId`, `username` | [Live Chat guide](/guides/live-chat#chat-participants) |


`userId` on agents means something different
On the customer-facing `ChatParticipant` / send surfaces, `userId` / `customerUserId` is the customer
**BSUID**. The `userId` on a `SystemUser` (agent) is your own external agent identifier — unrelated.
Don't conflate the two.

## Live Chat v2

The live-chat API has moved to a leaner **v2** surface. The v2 endpoints return curated payloads
(only the fields a chat UI needs), unify sending across channels, and add quoted-reply context.

### What changed

- **Lean payloads.** v1 returned the full internal entity; v2 returns curated DTOs
(`MessageResponse`, `ChatParticipantResponse`) with null fields omitted.
- **One send endpoint for every channel.** Instead of per-channel send operations, a single
[Send an agent message (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/sendmessagev2)
routes by a `channel` field (`WHATSAPP`, `WEB`, `FACEBOOK`).
- **Media is a two-step, channel-agnostic flow.** Upload once, then send the returned `mediaUrl` on
any channel.
- **Quoted replies.** `MessageResponse` carries `quotedExternalMessageId` and `quotedText` for
messages that reply to/quote an earlier message.
- **Scoped chat lists.** A single list endpoint selects the view with a `scope` filter rather than
separate per-tab operations.
- **Identity from context.** The agent is resolved from your API key / session — you no longer send
agent or participant objects in the request body.


### Endpoint mapping

| Deprecated (v1) | Replacement (v2) | Notes |
|  --- | --- | --- |
| [Get messages by chat participant](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/getmessagesbychatparticipant) | [Get messages for a chat participant (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/getmessagesv2) | Lean `MessageResponse`, includes quoted-reply fields |
| [Send WhatsApp agent reply](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/sendagentmessagewhatsapp) | [Send an agent message (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/sendmessagev2) | Set `channel: WHATSAPP` |
| [Send agent reply with attachment](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/sendagentmessagewithattachment) | [Upload media](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/uploadmediav2) → [Send an agent message (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/sendmessagev2) | Upload once, send the returned `mediaUrl` (content type defaults to `MEDIA`) |
| [Send typing indicator (Chat)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/sendchattypingindicator) | [Send typing indicator (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/sendtypingindicatorv2) | Pass only `participantId`; sender/recipient resolved server-side |
| [Mark message as read by agent](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/markreadbyagent) | [Mark a conversation as read (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/markasreadv2) | Clears the unread badge and sends the read receipt in one call |
| [Get chat participants](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/getchatparticipants) and the per-tab lists (`getMyParticipants`, `getTeamParticipants`, `getUnAssignedParticipants`, `getClosedParticipants`, `getMissedParticipants`, `getMissedAfterHoursParticipants`, `getMyMissedParticipants`) | [List chats (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/listchatsv2) | Pick the tab with `scope` (`my` / `team` / `unassigned` / `closed` / `missed-agent` / `missed-after-hours` / `my-missed` / `open` / `all`) |
| [Get conversations assigned to a specific agent](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/getparticipantsbyassignedto) | [List chats (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/listchatsv2) with `scope=my` | v2 uses the agent from your API key — returns **your** assigned chats; arbitrary-agent lookup is not carried forward |
| [Terminate or reopen a chat conversation](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/terminatechatparticipantchat) | [Terminate a chat (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/terminatechatv2) / [Reopen a chat (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/openchatv2) | Pass only the chat id; no full-object merge |
| [Get chat messages by tracking number](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/getchatmessagesbytrackingnumber) | [Get messages by tracking number (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/getmessagesbytrackingnumberv2) | Lean `MessageResponse`, scoped to your client |


There is also a new [Get a message by ctId (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/getmessagebyctidv2)
lookup (lean, tenant-checked), and [Get a chat (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/getchatv2)
to fetch a single chat.

### Chatbot webhook v2

The `v2` chatbot webhook payload no longer ships the nested `chatParticipant` object (it was
redundant and carried `SystemUser` credentials). Read agent identity and lifecycle from the flat
fields (`assignedAgentId`, `assignedAgentName`, `conversationStatus`, `conversationClosed`, …) and
reply with a single [Send an agent message (v2)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/live-chat/sendmessagev2)
call using the payload's `chatParticipantId`.

## User Management v1

User endpoints have moved to a **v1** surface under `/api/v1/users`. The v1 endpoints return a
credential-free [`UserResponse`](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management)
— never password, `apiKey`, or token fields — and user creation no longer accepts a
caller-supplied password.

### What changed in v1

- **Credential-free responses.** v1 endpoints return `UserResponse` / `CreateUserResponse` DTOs
with null fields omitted, instead of the credential-bearing `SystemUser` entity.
- **No caller-supplied password on create.** [Create a user](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/createuser)
generates a single-use `temporaryPassword`, returned once in the response; the user sets their
own password on first login.
- **Update by `id`.** [Update a user](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/updateuser)
identifies the target by `id` in the body and carries no credentials.
- **Identity from context.** The "my" endpoints (profile, password, credits) resolve the user from
your API key / session — you no longer pass a user object.


### Endpoint mapping (User Management)

| Deprecated (legacy) | Replacement (v1) | Notes |
|  --- | --- | --- |
| [Create a system user](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/createsystemuser) | [Create a user](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/createuser) | Takes no password; returns a one-time `temporaryPassword` |
| [Update a system user](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/updatesystemuser) | [Update a user](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/updateuser) | Identified by `id`; credential-free; returns `UserResponse` |
| [Get current logged-in user](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/getcurrentuser) | [Get my profile](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/getme) | Credential-free `UserResponse` |
| [Get current client users](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/getclientusers) | [List client users](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/listclientusers) | Credential-free `UserResponse` records |
| [Get users for a client](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/getusersforclient) | [List users (paginated)](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/getuserspage) | Paginated, credential-free `UserResponse` records |
| [Change available status](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/changeavailabilitystatus) | [Change availability](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/changeavailability) | Credential-free `UserResponse` |
| [Update agent chat limit](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/updateagentchatlimit) | [Set agent chat limit](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/setagentchatlimit) | Behaviour identical |
| [Change password](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/changepassword) | [Change my password](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/changemypassword) | Behaviour identical |
| [Get WhatsApp credits for current user](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/getwhatsappcreditsforcurrentloginuser) | [Get my WhatsApp credits](https://ecommunicate-api-docs.redocly.app/apis/omnichannel/user-management/getmycredits) | Behaviour identical |


### `UserResponse` fields

Beyond identity and live-chat fields, `UserResponse` carries the user's client context and account
status: `clientId`, `clientRef`, `countryTimezone`, and `popiaComplianceEnabled` (inherited from
the client), plus `resetPasswordEmailSent`, `emailVerified`, `tempPasswordValid`, and `validToken`.