Table of Contents

Action required: WhatsApp usernames and BSUIDs — what you need to know

Raquel Updated by Raquel

WhatsApp is rolling out a major change in 2026: end-users will be able to hide their phone number when messaging businesses, identifying themselves with a username instead (for example, @alice_smith).

That means that the user's phone number will stop being their main identifier. Meta is introducing a new identifier called the BSUID (Business-Scoped User ID). Over the coming months, BSUIDs will start appearing alongside phone numbers across the WhatsApp Business API.

This article gives you an early heads-up on: what is changing, what stays the same, and how to get prepared for this change — as this potentially requires you to make changes to your systems.

Meta's rollout is ongoing and some pieces are still being enabled on their side (docs). We'll keep this article updated as things evolve.

What is a BSUID?

A BSUID is an identifier that uniquely represents a user within your business portfolio. It looks like this:

US.13491208655302741918
IN.26329079733414951

The format is a country code (ISO 3166 alpha-2) followed by an alphanumeric string.

A few important properties:

  • Portfolio-scoped: the same end-user will have a different BSUID for each business portfolio they message.
  • Stable across username changes: even if a user changes their @username, their BSUID stays the same.
  • Regenerated on phone number change: if a user switches phone numbers, their BSUID is reissued.
  • Always present: BSUIDs are included in every webhook, whether or not the user has chosen to use a username.

What stays the same

Nothing breaks for your existing contacts. You'll still have the phone numbers of people who already messaged you. Every contact you have today will continue to work exactly as before.

You'll also still receive the user's phone number in webhooks in many common scenarios, even after they adopt a username.

What is changing

  • You won't have access to the phone number of new users who chose to hide it
  • The main identifier for users will be their BSUID, not their whatsapp_id (their phone number).

In Turn.io, these changes will be rolled out progressively:

  • Contacts will have new fields
  • Sending messages by BSUID
  • New journey expressions
  • Behaviour change for @contact.whatsapp_id
  • CSV imports and exports
  • Authentication templates
  • BigQuery / data warehouse customers

Getting prepared

Over the years, everyone built their services assuming that the main identifier for a user would be their phone number. This means that, across your entire system, you might be relying on the phone number. Here's an exhaustive list of things you should review, and how to transition them to using BSUID's.

1. API Changes

1.1 Contact Endpoints — BSUID as Identifier

All contact endpoints now accept a BSUID as the contact_id path parameter, in addition to phone numbers.

Before: Only phone numbers accepted.

GET /v1/contacts/918609840467/profile

After: Either phone number or BSUID accepted. Format is auto-detected.

GET /v1/contacts/918609840467/profile          # by phone


GET /v1/contacts/IN.26329079733414951/profile  # by BSUID

Affected endpoints:

  • GET /v1/contacts/<contact_id> — get or create a contact
  • POST /v1/contacts/<contact_id> — create a contact by identifier
  • PUT /v1/contacts/<contact_id> — update a contact
  • GET /v1/contacts/<contact_id>/profile — get contact profile
  • PUT /v1/contacts/<contact_id>/profile — replace contact profile
  • PATCH /v1/contacts/<contact_id>/profile — partial update contact profile
  • DELETE /v1/contacts/<contact_id>/profile — delete contact profile
  • GET /v1/contacts/<contact_id>/messages — list messages for a contact
  • GET/POST/PUT/DELETE /v1/contacts/<contact_id>/claim — manage chat assignment

1.2 Contact Response — New Fields

GET /v1/contacts/<contact_id> now includes the contact's BSUID and username when known:

{

  "id": "uuid",

  "type": "DEFAULT",

  "is_fallback_active": false,

  "failure_count": 0,

  "bsuid": "IN.26329079733414951",

  "username": "alice_smith"

}

Field

Type

Description

bsuid

string, omitted when not set

The user's Business-Scoped User ID

username

string, omitted when not set

The user's WhatsApp username (e.g. alice_smith)

1.3 Webhooks You Receive from Turn

If you consume Turn's webhooks, BSUID fields now appear in the payloads, and phone-based fields can be absent for users who have hidden their phone number. Any code that assumes from, to, or wa_id is always present must handle them being missing.

1.3.1  Inbound message webhooks

Field

Change

from

Omitted when the sender's phone is unavailable (was always present)

from_bsuid

New — the sender's BSUID. Not present on messages received before BSUID support

contacts[] entry

Mirrors Meta's format: wa_id (phone) when available, user_id (BSUID) when available, or both

Example message fragment for a BSUID-only user:

{

  "id": "wamid.xxx",

  "type": "text",

  "from_bsuid": "IN.26329079733414951",

  "text": { "body": "Hello" }

}

with the contact entry: { "profile": { "name": "Alice" }, "user_id": "IN.26329079733414951" }

1.3.2  Outbound message webhooks

Field

Change

to

null when the recipient has no phone number (was always the phone)

recipient

New - the recipient's BSUID, included whenever the conversation has one (can appear alongside to)

1.4 Sending Messages — New recipient Field

POST /v1/messages now accepts a recipient field for BSUID-based sending, as an alternative to the to field.

Before:

{

  "to": "918609840467",

  "type": "text",

  "text": { "body": "Hello" }

}

After — send by BSUID:

{

  "recipient": "IN.26329079733414951",

  "type": "text",

  "text": { "body": "Hello" }

}

After — send with both (phone takes precedence):

{

  "to": "918609840467",

  "recipient": "IN.26329079733414951",

  "type": "text",

  "text": { "body": "Hello" }

}

Rules:

  • At least one of to or recipient must be provided
  • When both are provided, phone (to) takes precedence
  • to accepts phone numbers only (no + prefix)
  • recipient accepts BSUIDs only

1.5 Contact CSV Export — New Columns

CSV exports now include two additional columns alongside whatsapp_phone_number:

New column

Description

Example

bsuid

Business-Scoped User ID

IN.26329079733414951

username

WhatsApp username

alice_smith

1.6 Block/Unblock — BSUID Support

Blocking and unblocking contacts now works with BSUID identifiers. The API auto-detects whether the identifier is a phone number or BSUID. When sending the block request to Meta, the system uses user_id (BSUID) when phone is unavailable.

1.7 Outbound Calling — New recipient Field

Business-initiated outbound calls now include a recipient field for BSUID-based call initiation, alongside the existing to field.

2. Journey Changes

2.1 New Contact Fields

Two new expressions are available in journeys:

Expression

Type

Description

Example value

@contact.bsuid

string

The user's BSUID

IN.26329079733414951

@contact.username

string

The user's WhatsApp username

@alice_smith

These are available in the Journey builder under the Contact variables menu.

2.2 New Chat Field

Expression

Type

Description

@chat.owner_bsuid

string

The BSUID of the chat owner

Available under the Chat variables menu.

2.3 Behavior Change for @contact.whatsapp_id

@contact.whatsapp_id remains phone-only. For BSUID-only contacts (users who have hidden their phone number), this expression returns nil.

Action required: 

Journeys that depend on @contact.whatsapp_id should be updated to use @contact.bsuid where appropriate, or add nil checks — see below how.

Here's an example expression to check if someone's whatsapp_id is nil:

is_nil_or_empty(@contact.whatsapp_id)

Here's an example of it in use on a Code card:

card CodeBlock_1 do
user_id = if(is_nil_or_empty(@contact.whatsapp_id), @contact.bsuid, @contact.whatsapp_id)
text("User id: @user_id")
end

3. Requesting the user's phone number (coming soon)

To collect phone numbers from username-only users, Meta provides a new message type called Request Contact Info.

You can request the user's phone number from multiple places in the product:

Location

As a template

From the inbox

From journeys

The result is always the same: you get access to the user's phone number.

4. Authentication Templates (OTP)

Authentication templates cannot use BSUIDs. Attempting to send an auth template to a BSUID-only contact returns Meta error code 131062. A phone number is required.

This applies to all authentication template types:

  • One-time passwords (OTP)
  • One-tap authentication
  • Zero-tap authentication
  • Copy code authentication

These errors will show up in the journey logs or the inbox when trying to send an auth template to a contact without a phone number:

To send authentication templates, you need to first collect the user's phone number by using the Request Contact Info message mentioned earlier on this article.

5. BigQuery / Data Warehouse Changes

5.1 New Columns

The following new columns are automatically exported to BigQuery:

Table

New Column

Type

Description

contacts

bsuid

STRING

Business-Scoped User ID

contacts

username

STRING

WhatsApp username

messages

from_bsuid

STRING

BSUID of the message sender — inbound messages only, NULL on outbound

messages

urn_bsuid

STRING

BSUID of the customer on either side of the message (sender for inbound, recipient for outbound) — the BSUID counterpart of the existing urn_phone_number; use this for join queries

chats

owner_bsuid

STRING

BSUID of the conversation owner

5.2 Nullable Phone Fields

For BSUID-only contacts (users who have hidden their phone number), the phone-based columns will be NULL:

Column

Behavior for BSUID-only contacts

contacts.urn

NULL (was +phone)

messages.from_addr

NULL (was phone number)

messages.urn_phone_number

NULL for both directions (inbound: no from_addr to derive from; outbound: no phone recipient to derive from)

chats.owner

NULL (was phone number)

5.3 Impact on Existing Queries

Queries that JOIN on phone-based fields will silently return no rows for BSUID-only contacts. You must update JOINs to use BSUID fields as well.

(Note: urn_phone_number and urn_bsuid are denormalized columns on the messages table that normalize the customer's identifiers across directions. urn_phone_number: from_addr for inbound, addressees[0] for outbound — NULL when the phone is unavailable. urn_bsuid: sender's BSUID for inbound, the conversation's BSUID for outbound.)

Before (phone-only JOIN — breaks for BSUID-only contacts):

-- Fetch all messages for a contact (only accounts for phone number)

SELECT m.*, c.details

FROM messages m

JOIN contacts c ON m.urn_phone_number = c.urn

After (phone + BSUID JOIN):

-- Fetch all messages for a contact (accounts for both phone number and bsuid)

SELECT m.*, COALESCE(cp.details, cb.details) AS details

FROM messages m

-- Messages can be linked their contact by either phone OR bsuid OR both

LEFT JOIN contacts cp ON m.urn_phone_number = cp.urn

LEFT JOIN contacts cb ON m.urn_bsuid = cb.bsuid

-- Optional: only keep messages that matched a contact 

WHERE cp.urn IS NOT NULL OR cb.bsuid IS NOT NULL

New filtering capabilities:

-- Find all BSUID-only contacts (no phone number)

WHERE contacts.bsuid IS NOT NULL AND contacts.urn IS NULL

-- Filter by specific BSUID

WHERE contacts.bsuid = 'US.13491208655302741918'

-- All messages exchanged with a specific BSUID user (both directions) 

WHERE messages.urn_bsuid = 'US.13491208655302741918'

-- Filter by username

WHERE contact.username = 'alice_smith'

We suggest you get started as soon as possible on making your systems make use of the new BSUID and resilient to users who chose to hide their phone number.

If you have questions in the meantime, reach out to us. We're here to help.

Was this article helpful?

15 Jul 2026: New Reply Box

Contact