Skip to main content

WhatsApp Business-scoped User IDs

WhatsApp is introducing optional usernames. When a user adopts a username, their phone number is no longer guaranteed to be shared with businesses. To let you keep addressing these users, Meta introduces the Business-scoped User ID (BSUID): an identifier that uniquely identifies a WhatsApp user within your business portfolio.

This page describes how the CM.com Business Messaging API supports BSUIDs for sending messages, incoming messages and status reports.

What changes at a glance
  • Sending (MT): to.number accepts a BSUID as well as a phone number. There is no new endpoint or field.
  • Incoming messages (MO): the from object contains a new whatsapp object with user_id, parent_user_id and username. If the phone number is not shared, from.number contains the BSUID instead.
  • Status reports (SR): the recipient object contains the same whatsapp object.
  • No breaking changes: integrations that only use phone numbers keep working. All new fields are additive.

About BSUIDs​

PropertyDescription
FormatAn ISO 3166 alpha-2 country code, a full stop and up to 128 alphanumeric characters, for example NL.84827364598365.
UniquenessGenerated automatically, unique per user and business portfolio.
ScopeValid from any phone number in any WABA within the same business portfolio. The same user has a different BSUID in every other portfolio.
LifetimeRegenerated when the user changes their phone number. See BSUID changes.
RestrictionsCannot be used for authentication templates (one_tap, zero_tap and copy_code). No fallback to other channels, such as SMS.

When is the phone number shared?​

The user's phone number is included in webhooks when either:

  • Your business phone number has interacted with the user in the last 30 days (sent to or received from)
  • The user is in your contact book.

Otherwise, only the BSUID is available. Make sure your integration can handle messages without a phone number.


Sending a message to a BSUID​

Place the BSUID in the existing to.number field. The platform recognises the identifier by its format:

FormatExampleTreated as
00 + country code + number00316012345678Phone number
<country code>.<alphanumeric>NL.84827364598365BSUID
<country code>.ENT.<alphanumeric>NL.ENT.11815799212886844830Parent BSUID
One identifier per recipient

Each to entry must contain either a phone number or a BSUID, not both.

Send to BSUID
{
"messages": {
"authentication": {
"productToken": "YOUR_PRODUCT_TOKEN"
},
"msg": [
{
"from": "00316098765432",
"to": [
{ "number": "NL.84827364598365" }
],
"body": {
"type": "auto",
"content": "Fallback text"
},
"allowedChannels": ["WhatsApp"],
"richContent": {
"conversation": [
{ "text": "Hello from CM.com" }
]
}
}
]
}
}

Keep in mind:

  • Set allowedChannels to ["WhatsApp"]. A BSUID cannot be used on other channels, so fallback is not possible.
  • Sending to a BSUID from a phone number in a different business portfolio fails. The rejection appears in your status report.
  • Authentication templates must be sent to a phone number.
  • Max price (bid_spec) is not supported for BSUID recipients.

Receiving messages​

The from object of every inbound WhatsApp message contains a whatsapp object. This applies to all inbound message types described in WhatsApp inbound.

FieldDescription
from.numberThe sender's phone number. If the phone number is not shared, this contains the BSUID instead.
from.whatsapp.user_idNew. The sender's BSUID.
from.whatsapp.parent_user_idNew. The sender's parent BSUID. Only present if parent BSUIDs are enabled for your account.
from.whatsapp.usernameNew. The sender's WhatsApp username, for example @samuelbeckett. Empty or absent unless the user has adopted a username.
Phone number shared
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUQxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "Samuel Beckett",
"whatsapp": {
"user_id": "NL.84827364598365"
}
},
"to": {
"number": "0031607453450"
},
"message": {
"text": "Hello, I'd like to know your opening hours.",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"meta_received_time": "2026-05-04T08:32:30"
}
},
"groupings": ["", "", ""],
"timeUtc": "2026-05-04T08:32:33",
"channel": "WhatsApp"
}
Phone number not shared
{
"reference": "wamid.HBgLMzE2MTIzNDU2NzgVAgASGBQzQUUxMjM0NTY3ODkwQUJDREVGAA==",
"messageContext": "",
"from": {
"number": "NL.84827364598365",
"name": "Samuel Beckett",
"whatsapp": {
"user_id": "NL.84827364598365",
"parent_user_id": "NL.ENT.20351749385746821093",
"username": "@samuelbeckett"
}
},
"to": {
"number": "0031607453450"
},
"message": {
"text": "How long do I have to wait for Godot?",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"meta_received_time": "2026-05-04T08:32:30"
}
},
"groupings": ["", "", ""],
"timeUtc": "2026-05-04T08:32:33",
"channel": "WhatsApp"
}

Status reports​

The recipient object of WhatsApp status reports, in both JSON and XML, contains a whatsapp object. The to field still echoes the identifier you used when sending (phone number or BSUID).

FieldDescription
toThe identifier you used in the original message: a phone number or a BSUID.
recipient.numberThe recipient's phone number, or the BSUID if the phone number is not shared.
recipient.whatsapp.user_idNew. The recipient's BSUID, regardless of how you addressed the message. Included in accepted, delivered and read status reports. In failed status reports for messages sent to a phone number, whatsapp is null.
recipient.whatsapp.parent_user_idNew. The recipient's parent BSUID. Empty unless parent BSUIDs are enabled.
recipient.whatsapp.usernameNew. The recipient's WhatsApp username. Empty unless the user has adopted a username.

Status codes are unchanged: 0 accepted, 1 rejected, 2 delivered, 3 failed, 4 read. BSUID-related failures are reported in the existing errorCode and errorDescription fields, like any other failure.

JSON​

Phone number
{
"messages": {
"msg": {
"received": "2026-05-04T15:38:56",
"reference": "reference2",
"to": "0031612345678",
"recipient": {
"number": "0031612345678",
"whatsapp": {
"user_id": "NL.84827364598365"
}
},
"status": {
"code": "2",
"errorCode": "",
"errorDescription": "Delivered"
},
"operator": ""
}
}
}
With username
{
"messages": {
"msg": {
"received": "2026-05-04T15:38:56",
"reference": "reference2",
"to": "0031612345678",
"recipient": {
"number": "0031612345678",
"whatsapp": {
"user_id": "NL.84827364598365",
"username": "@pablomorales"
}
},
"status": {
"code": "2",
"errorCode": "",
"errorDescription": "Delivered"
},
"operator": ""
}
}
}
With parent BSUID
{
"messages": {
"msg": {
"received": "2026-05-04T15:38:56",
"reference": "reference2",
"to": "0031612345678",
"recipient": {
"number": "0031612345678",
"whatsapp": {
"user_id": "NL.84827364598365",
"parent_user_id": "NL.ENT.20351749385746821093",
"username": "@pablomorales"
}
},
"status": {
"code": "2",
"errorCode": "",
"errorDescription": "Delivered"
},
"operator": ""
}
}
}
Phone number not shared
{
"messages": {
"msg": {
"received": "2026-05-04T15:38:56",
"reference": "reference2",
"to": "NL.84827364598365",
"recipient": {
"number": "NL.84827364598365",
"whatsapp": {
"user_id": "NL.84827364598365"
}
},
"status": {
"code": "2",
"errorCode": "",
"errorDescription": "Delivered"
},
"operator": ""
}
}
}
Failed
{
"messages": {
"msg": {
"received": "2026-06-17T13:57:13",
"reference": "reference2",
"to": "0031612345678",
"recipient": {
"number": "",
"whatsapp": null
},
"status": {
"code": "1",
"errorCode": "87",
"errorDescription": "Message marked as failed by CM after 24 hours without receiving final status from the operator"
},
"operator": ""
}
}
}

XML​

Phone number
<messages>
<msg>
<received>2026-05-04T15:38:56</received>
<to>0031612345678</to>
<recipient>
<number>0031612345678</number>
<whatsapp>
<user_id>NL.84827364598365</user_id>
<parent_user_id></parent_user_id>
<username></username>
</whatsapp>
</recipient>
<reference>reference2</reference>
<status>
<code>2</code>
<errorCode></errorCode>
<errorDescription>Delivered</errorDescription>
</status>
<operator></operator>
</msg>
</messages>
Sent to BSUID
<messages>
<msg>
<received>2026-05-04T15:38:56</received>
<to>NL.84827364598365</to>
<recipient>
<number>0031612345678</number>
<whatsapp>
<user_id>NL.84827364598365</user_id>
<parent_user_id></parent_user_id>
<username>@pablomorales</username>
</whatsapp>
</recipient>
<reference>reference2</reference>
<status>
<code>2</code>
<errorCode></errorCode>
<errorDescription>Delivered</errorDescription>
</status>
<operator></operator>
</msg>
</messages>

Identifier reference​

FlowYour identifier fieldPhone numberwhatsapp.user_idwhatsapp.parent_user_idwhatsapp.username
Sending (MT)to.number: phone number or BSUIDn/an/an/an/a
Incoming (MO)to.number: your business numberfrom.number, or the BSUID if not sharedAlways populatedEmpty unless parent BSUIDs are enabledEmpty unless the user has one
Status (SR)to: echo of what you sentrecipient.number, or the BSUID if not sharedPopulated for accepted, delivered and readEmpty unless parent BSUIDs are enabledEmpty unless the user has one

BSUID changes​

When a user changes their WhatsApp phone number, their BSUID is regenerated. CM.com notifies you with a system message on your MO webhook:

  • message.custom.message_type is system.
  • message.text contains the old and the new BSUID.

When you receive this event, extract both BSUIDs from message.text, replace the old BSUID in your records and stop sending to it.

BSUID change
{
"reference": "wamid.HBgLZjk3MmRhYjZjFQIAEhgKQTI3MzU0Q0Y4QTRGMzRBNjAA",
"messageContext": "",
"from": {
"number": "0031612345678",
"whatsapp": {
"user_id": "NL.84827364598365",
"parent_user_id": "",
"username": "@pablomorales"
}
},
"to": {
"number": "0031607453450"
},
"message": {
"text": "User A changed BSUID from NL.84827364598365 to NL.99999999999999",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"meta_received_time": "2026-05-06T20:12:05",
"message_type": "system"
},
"error": ""
},
"groupings": ["", "", ""],
"time": "2026-05-06 22:12:07",
"timeUtc": "2026-05-06T20:12:07",
"channel": "WhatsApp"
}

Parent BSUIDs​

Businesses that operate WABAs across several linked business portfolios can opt in to parent BSUIDs. A parent BSUID has the format <country code>.ENT.<alphanumeric>, for example NL.ENT.11815799212886844830, and can be used from any business phone number in any WABA across the linked portfolios.

If parent BSUIDs are enabled for your account:

  • Inbound messages contain from.whatsapp.parent_user_id.
  • Status reports contain recipient.whatsapp.parent_user_id.
  • When sending, you can put either the BSUID or the parent BSUID in to.number. The platform routes the message based on the ENT segment.

Migration guide​

  1. Parse tolerantly. Make sure your MO and status report handlers accept the new whatsapp object and handle messages without a phone number.
  2. Store the BSUID. Save the BSUID with your user records as soon as it appears in inbound traffic. Treat it as the durable identifier, since the phone number may not be shared in future.
  3. Keep using phone numbers where required. Authentication templates must still be sent to phone numbers.
  4. Send to BSUIDs. For users whose phone number is no longer shared, place the BSUID in to.number.
  5. Handle BSUID changes. Process the BSUID change system message and replace stored BSUIDs.

Business usernames​

Your business can also adopt a username. Users can then find your business by searching for the exact username, and it is shown on your profile.

Some usernames may already be reserved for you. Once your request is approved, the username becomes active as soon as usernames are available in your country.

The following requests are made directly to Meta's Graph API.

Check available usernames​

curl 'https://graph.facebook.com/<API_VERSION>/<BUSINESS_PHONE_NUMBER_ID>/username_suggestions' \
-H 'Authorization: Bearer <ACCESS_TOKEN>'

Request a username​

curl -X POST 'https://graph.facebook.com/<API_VERSION>/<BUSINESS_PHONE_NUMBER_ID>/username' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
-d '{
"username": "<DESIRED_USERNAME>",
"transfer_action": "none"
}'
FieldRequiredDescription
usernameYesThe username you want.
transfer_actionNoWhat to do if the username is already assigned to another phone number in your portfolio. none (default): the request fails with error 147005. force_transfer: the username is moved to this phone number.

A successful response contains a status:

StatusMeaning
approvedThe username is approved and becomes visible once usernames are generally available.
reservedThe username is reserved and approved, but not yet visible. It becomes visible on general rollout.

Error codes​

CodeDescriptionCause and solution
10App lacks permissionThe token's system user needs Full control, or Partial access (phone numbers), on the WABA.
33Invalid IDInvalid phone number ID, deleted WABA or missing whatsapp_business_management permission.
100Invalid parameterThe username does not match the required format.
147001Username not availableThe username is already taken, failed internal checks or is not available. Try a different username.
147002Account not eligibleThe business portfolio needs a higher tier.
147003Facebook Page not linkedLink the phone number to the Facebook Page that already holds this username.
147004Instagram account not linkedLink the phone number to the Instagram account that already holds this username.
147005Username transfer requiredThe username is assigned to another phone number in your portfolio. Resend the request with "transfer_action": "force_transfer".
133010Account not registeredRegister the business phone number for API use first.

Request phone number from users​

If you only have a user's BSUID, you can ask them to share their phone number with a request contact info button. The button can be added to Utility and Marketing templates or sent as an interactive message.

When the user taps the button, their phone number is shared in the conversation and you receive a contact message with origin set to contact_request. If the contact book feature is enabled, the number is also added to your contact book.

Request contact info message

Sending the request​

The examples show the conversation item. For the template version, the button is defined in the approved template.

Interactive
{
"interactive": {
"type": "request_contact_info",
"body": {
"text": "To continue assisting you, we'd like to save your contact details. Please tap the button below to share your phone number securely."
},
"action": {
"name": "request_contact_info"
}
}
}
Template
{
"template": {
"whatsapp": {
"element_name": "request_contact_info",
"language": { "policy": "deterministic", "code": "en" },
"components": []
}
}
}

Receiving the phone number​

Contact webhook
{
"reference": "wamid.HBgLMzQ2OD14aef4EAFzNEFCMzREOAA=",
"messageContext": "",
"from": {
"number": "0031612345678",
"name": "John Doe",
"whatsapp": {
"user_id": "NL.84827364598365"
}
},
"to": {
"number": "0031607453450"
},
"message": {
"text": "",
"media": {
"mediaUri": "",
"contentType": "",
"title": ""
},
"custom": {
"contacts": [
{
"vcard": "QkVHSU46VkNBUkQKVkVSU0lPTjozLjAKTjo7SmVzczs7OwpGTjpKZzClRFTDt0eXBlPU1vYmlsZTt3YWlkPTM0Njg1MTIwNDczOiszNCA2ODUgMTIgMDQgNzMKRU5EOlZDQVJE",
"origin": "contact_request",
"addresses": null,
"birthday": null,
"emails": null,
"name": {
"formatted_name": "John Doe",
"first_name": "John",
"last_name": "Doe",
"middle_name": null,
"suffix": null,
"prefix": null
},
"org": null,
"phones": [
{
"phone": "+31 6 12345678",
"type": "MOBILE",
"wa_id": "31612345678"
}
],
"urls": null
}
],
"meta_received_time": "2026-07-24T08:26:53",
"message_type": "contacts"
},
"error": ""
},
"groupings": ["", "", ""],
"time": "2026-07-24 10:26:54",
"timeUtc": "2026-07-24T08:26:54",
"channel": "WhatsApp"
}