Skip to main content
This guide shows how to send messages to a BSUID (Business-Scoped User ID), the phone-less identifier Meta uses on official WhatsApp (WABA). The send uses the same POST /v1/wa/messages endpoint, changing only the value of the recipient field.

What a BSUID is

BSUID stands for Business-Scoped User ID. It is an identifier Meta generates to represent a WhatsApp user without exposing their phone number. It exists because of WhatsApp’s username rollout, planned for 2026. When a user chooses to chat by username, or opts to keep their number hidden, your business stops receiving the phone number and receives a BSUID instead. This identifier lets you continue the conversation normally, except the real phone number is never revealed. A BSUID is scoped to a business portfolio. The same user shows up with a different BSUID for each portfolio, so a BSUID is only valid inside the portfolio that received it (see Limitations and errors).
The BSUID is exclusive to the official channel (WABA). On the unofficial channel (QR code), the analogous identifier is the LID, which flows through the normal JID path. A BSUID sent to an unofficial instance is rejected with the waba_bsuid_requires_waba error.

Format

A BSUID has two forms: Format rules:
  • The prefix is the ISO 3166 alpha-2 country code (two letters, such as US, BR, PT).
  • Then comes a dot (.).
  • Parent BSUIDs insert the ENT segment (also followed by a dot) between the country code and the identifier.
  • The final identifier is up to 128 alphanumeric characters and is opaque: treat it as a meaningless string and never alter it.

How to send

Sending is identical to a regular WABA message. You use the same POST /v1/wa/messages endpoint and the same request signature. The only difference is that the recipient field takes the BSUID instead of a phone number. Zapster detects the BSUID format automatically and builds the Meta Cloud API payload with the correct field. Before you start, you need a connected WABA instance. In every example, replace YOUR_API_TOKEN with your API token and YOUR_INSTANCE_ID with the WABA instance ID. The example BSUID (US.13491208655302741918) stands for the recipient; use the real BSUID that arrived in your webhook.
As with any free WABA message, text, media, and buttons are only delivered inside the 24-hour conversation window. Outside the window, use an approved template (see further below). The full breakdown is in Sending WhatsApp messages with WABA.

Plain text

Media (image, video, or document)

Send the media by public URL or base64 in the media field. The type is detected automatically from the file.

Interactive buttons

The WABA button rules also apply to BSUID: up to 3 reply buttons, or exactly 1 url button, without mixing the two types. The full matrix is in Messages with buttons.

Template (outside the 24h window)

Templates work with BSUID, with one important exception: one-tap, zero-tap, and copy-code authentication templates are not supported for BSUID and are rejected by Meta with error 131062 (see Limitations and errors). Utility and marketing templates, and authentication templates with a text code, work normally. The template object is a mirror of Meta’s format. Details of components, positional variables, and named variables are in Sending WhatsApp messages with WABA.

Where the BSUID comes from

You do not invent a BSUID: it arrives through incoming webhooks. Zapster normalizes every webhook before delivering it, so you never deal with Meta’s raw fields. The contact always arrives in the same shape, with id, phone_number, and bsuid. In a message.received event, the customer’s contact comes in sender (and, in one-to-one conversations, also in recipient, which mirrors sender). The id field is the primary identifier and follows a simple rule: phone number when it exists, BSUID when it does not.
  • Phone number visible: phone_number carries the number and bsuid carries the BSUID (Meta sends both). id points to phone_number.
  • Phone number hidden (a privacy-conscious user): phone_number is null, bsuid carries the BSUID, and id takes the BSUID value.
See message.received in both scenarios. In both, the contact’s id is the value you use in recipient to reply within the 24-hour window:
phone_number is null, bsuid carries the BSUID, and id takes the BSUID value.
phone_number and bsuid are both filled in, and id points to phone_number.
In status events (message.sent, message.delivered, message.read), the customer’s contact comes in recipient in the same shape, so the BSUID appears in recipient.bsuid (and in recipient.id when the phone number is hidden). The practical flow is: the customer messages your number, you receive the webhook, you read the contact’s id (which is already the BSUID when the phone number is hidden), you store that value, and you use it in the recipient of POST /v1/wa/messages to reply within the 24-hour window. See Available events for the webhook catalog.

Limitations and errors

When the payload uses a feature the Cloud API does not support with BSUID, Zapster rejects the request right away with a 400 error, without silently dropping anything. On top of that, remember the per-portfolio scope:
  • A BSUID is scoped to a business portfolio. A BSUID received in one portfolio does not work in another. If you try to send to a BSUID from an instance tied to a different portfolio, Meta rejects the send. Always reply using the same instance (same portfolio) that received that BSUID.

Best practices

  • Accept and normalize the prefix casing. The country code and the ENT segment are structural and canonically uppercase (US, US.ENT.). Zapster normalizes a BSUID typed as us.ent.<id> to the form Meta emits, so a lowercase value in recipient also works.
  • Never alter the identifier. The part after the prefix is opaque and may be case-sensitive. Preserve it byte for byte: no uppercasing, no trimming of zeros, no transformation of any kind.
  • Store the canonical BSUID for correlation. Save the BSUID in its canonical form (uppercase prefix, intact identifier) to match the value that arrives in webhooks and keep the contact’s history consistent. Keep in mind that when the user changes their number, Meta generates a new BSUID for them, so treat the BSUID as the contact’s identifier within that portfolio, not as something permanent.

Next steps