WhatsApp usernames & user IDs
Meta now identifies WhatsApp users with a Business Scoped User ID (BSUID).
This ID is scoped to the business portfolio that owns your WhatsApp number and
is the identity Wabery exposes as user_id. A phone number is an optional
address, not the contact key. Current BSUIDs use the complete
CC.<alphanumeric> form (or CC.ENT.<alphanumeric> for an enabled parent
BSUID) and must not be truncated or reformatted.
Wabery uses the Meta business-portfolio owner ID as the namespace when embedded signup captured it. Older channels without that metadata use an explicit WABA namespace as a fail-closed fallback; Wabery never broadens a BSUID to an entire Wabery organization.
Compatibility and required client changes
Section titled “Compatibility and required client changes”No new Wabery API version is required: no existing endpoint or webhook field is
removed or renamed. Existing phone-number conversations keep the same
contact_id, conversation_id, and E.164 from behavior. Wabery’s existing
public to input remains an E.164 phone-number input. For sends addressed by
conversation_id, Wabery resolves the stored contact: it maps a known phone to
Meta’s to field and a phone-hidden BSUID to Meta’s dedicated recipient
field. Wabery continues to prefer the phone value whenever one is known.
However, this is still a required compatibility update for webhook consumers. A username user may not expose a phone number, and Meta can rotate their BSUID. Before rollout, make sure your integration:
- accepts
from: nullandrecipient_id: nullinstead of requiring E.164; - joins records on
contact_id, notfromor a raw BSUID; - accepts additive webhook properties and safely acknowledges unknown event and message types;
- handles
contact.identity.updated, or at minimum does not reject it; and - requests contact info before a phone-only workflow such as an authentication template.
The existing fields remain in place:
fromis the E.164 phone number when Meta discloses it, otherwisenull.user_idis the WhatsApp BSUID when Meta supplies one and is safe inside the channel’s business portfolio.parent_user_idandusernameare nullable metadata from Meta.contact_idremains Wabery’s stable application-facing contact identifier.message.statuscan includerecipient_user_ideven when no phone is known.
Wabery consumes Meta’s required user_id_update webhook and emits
contact.identity.updated after reconciling a changed BSUID. Store the new
user_id if you mirror platform identities, but keep joining on contact_id.
These nullable identity properties already exist in Wabery’s webhook shape;
the rollout populates them when Meta supplies the corresponding values.
{ "event": "contact.identity.updated", "payload": { "object": "contact_identity", "channel_id": "channel_...", "contact_id": "contact_...", "previous_user_id": "US.111", "user_id": "US.222", "parent_user_id": null, "phone": null, "updated_at": "2026-08-05T12:00:00.000Z" }}Ask a user to share their phone number
Section titled “Ask a user to share their phone number”Send an interactive contact-info request inside the customer-service window:
await wabery.messages.send({ channelId: "channel_...", conversationId: "conversation_...", interactive: { type: "request_contact_info", body: { text: "Share your number so we can complete your booking." }, },});The response arrives as messages[n].type: "contacts" and the complete contact
cards are in messages[n].contacts. Wabery only backfills the sender phone when
Meta marks the card with origin: "contact_request"; ordinary shared contacts
never change the sender’s identity. Meta’s one-tap, zero-tap, and copy-code
authentication templates still require a phone-number recipient.
Templates can include Meta’s fixed contact button:
{ "type": "BUTTONS", "buttons": [{ "type": "REQUEST_CONTACT_INFO", "text": "Share Contact Info" }]}Manage your business username
Section titled “Manage your business username”Business usernames make a business discoverable; they do not hide the business phone number.
Meta allows 3–35 characters: English letters, digits, periods, and underscores,
with at least one letter. A username cannot start or end with a period, contain
two consecutive periods, start with www, or end with a domain suffix. Matching
is case-insensitive; periods and underscores remain distinct.
const suggestions = await wabery.channels.listWhatsAppUsernameSuggestions("channel_...");
const username = await wabery.channels.setWhatsAppUsername("channel_...", { username: "AcmeSupport", // Only use this when moving the username from another number in this portfolio: transferAction: "none",});curl https://api.wabery.com/v1/channels/channel_id/whatsapp-username/suggestions \ -H "Authorization: Bearer $WABERY_API_KEY"
curl -X POST https://api.wabery.com/v1/channels/channel_id/whatsapp-username \ -H "Authorization: Bearer $WABERY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"username":"AcmeSupport","transfer_action":"none"}'Use GET, POST, or DELETE /v1/channels/{id}/whatsapp-username. The current
status is approved (visible) or reserved (claimed but not visible yet).
transfer_action defaults to none; use force_transfer only to move a
username already assigned to another phone number in the same portfolio.
Meta removed pending-request cancellation from the current contract. Wabery
emits channel.username.updated when Meta sends business_username_updates.
The event status is approved, reserved, or deleted.
{ "event": "channel.username.updated", "payload": { "object": "whatsapp_username", "channel_id": "channel_...", "username": "AcmeSupport", "status": "approved", "updated_at": "2026-08-05T12:00:00.000Z" }}Meta is authoritative for availability, eligibility, linked Facebook/Instagram requirements, and status. See Meta’s official Business Scoped User IDs documentation.