Skip to content

WhatsApp Business-Scoped User IDs (BSUID) support needed before June 2026 #13837

Description

@m-ret

Summary

Meta is launching WhatsApp Usernames — users will be able to set an @username and hide their phone number from businesses. To support this, Meta is adding a Business-Scoped User ID (BSUID) to all webhook payloads via a new user_id field.

Starting June 2026, the wa_id / from fields that currently always contain a phone number may contain a BSUID instead (format: CC.alphanumeric, e.g. BR.1A2B3C4D5E6F7G8H9I0J...). This will break Chatwoot's contact resolution for username-adopting users.

Timeline

Date What happens
Early April 2026 Contact Book feature — Meta auto-stores phone+BSUID pairs from prior interactions
May 2026 BSUIDs start appearing in all webhook payloads (testing phase)
June 2026 Usernames launch in test countries — wa_id may be BSUID, not phone
August 2026+ Global rollout

What breaks in Chatwoot

Chatwoot currently uses the phone number (wa_id) as the primary identifier for WhatsApp contacts:

  1. Whatsapp::IncomingMessageBaseService resolves contacts via wa_id assuming it's always a phone number
  2. ContactInbox uses source_id (phone number in E.164) with a unique index on (inbox_id, source_id)
  3. find_or_create_contact maps phone number → Contact record

When a username-adopting user messages a business and their phone number is not in the Contact Book:

  • wa_id / from will be a BSUID, not a phone number
  • Chatwoot will create a duplicate contact (new source_id with the BSUID) instead of matching the existing contact
  • Sending replies may fail if the code assumes wa_id is always E.164

Webhook payload changes

New field user_id — always present in all message webhooks (regardless of username adoption):

{
  "contacts": [{"profile": {"name": "Jessica"}, "wa_id": "BR.1A2B3C4D5E6F7G8H9I0J..."}],
  "messages": [{
    "from": "BR.1A2B3C4D5E6F7G8H9I0J...",
    "user_id": "BR.1A2B3C4D5E6F7G8H9I0J...",
    "id": "wamid.xxx",
    "type": "text",
    "text": {"body": "Hello"}
  }]
}

For users without usernames, wa_id remains a phone number, but user_id (BSUID) is still present.

Suggested approach

  1. Store user_id (BSUID) — add a bsuid / whatsapp_user_id column to ContactInbox or Contact
  2. Dual-key contact resolution — match by BSUID first, fall back to phone number, write BSUID back when matched by phone
  3. Detect BSUID vs phone — BSUIDs have the format CC.alphanum (2-letter country code + dot + up to 128 chars), phone numbers are E.164
  4. Handle sending to BSUIDs — when no phone number is known, use the BSUID as the recipient identifier in the Cloud API

References

Environment

  • Self-hosted Chatwoot CE (latest)
  • WhatsApp Cloud API with coexistence mode
  • Affects all WhatsApp Cloud API integrations

I'm happy to contribute a PR if the team can provide guidance on the preferred approach for contact resolution changes.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions