On this page
Data model noteGlossary
BSUID (business-scoped user ID) — WhatsApp/Meta's term for an identifier that stands in for a contact's phone number when that number is hidden from a specific WhatsApp Business Account. Looks like EG.1693676845194969 (two letters, a dot, then digits). It only identifies the contact to this WABA — it is not a phone number and cannot be dialed, texted outside the existing conversation, or used to look up a patient record. Stored on OnlineConversation.bsuid.
Username privacy (WhatsApp) — a WhatsApp setting that hides a user's phone number from a business they haven't recently exchanged a message or call with (per the code's comment: no exchange in the last 30 days, and not in the business's contact book). When active, Meta's webhook sends a BSUID instead of the contact's wa_id (phone number).
wa_id — the field in Meta's webhook contacts[] payload that normally carries a contact's phone number. Omitted when username privacy applies to that contact; user_id (a BSUID) is sent in its place. See Receiving & Replying to Messages.
user_id / from_user_id — the two webhook fields that can carry a BSUID: contacts[0].user_id and messages[0].from_user_id. Dentolize reads either, treating them as the same value.
to vs recipient — the two mutually exclusive fields WhatsApp's Cloud API accepts for addressing an outbound message: to for a phone number, recipient for a BSUID. Sending a BSUID-addressed reply with to fails to deliver.
getConversationHandle — the shared UI helper (separately implemented in clinic-web and clinic-mobile) that picks what to display for a conversation's address: the phone number if there is one, else @username, else the raw BSUID.
conversationKey / waRecipient / isBsuid (server) — small helpers in packages/server/.../official-whats-app.utils.js used by the main GraphQL server to build a Prisma unique-key lookup or a Graph API address from whichever identifier is on hand. isBsuid here is a regex heuristic on the identifier's shape, distinct from the same-named boolean computed in whatsapp-official. See Identifying a Contact.
findConversationByAddress / backfill — the matching function in whatsapp-official that looks up a conversation by phone and/or BSUID and returns whether it's safe to write a newly-learned address onto the matched row (backfill: true) or whether the phone and BSUID lookups disagree and nothing should be written (backfill: false). See Identifying a Contact.
Data model note
OnlineConversation (packages/prisma/schema.prisma:4095) is the row-per-contact conversation record for Dentolize's official WhatsApp integration (distinct from the legacy/unofficial whatsapp package, which this PR does not touch). Relevant fields after this PR:
| Field | Type | Notes |
|---|---|---|
phone | String? | Nullable as of this PR. Unique per companyId. |
bsuid | String? | New in this PR. Unique per companyId. |
username | String? | New in this PR. Not unique — a display convenience only. |
patientId | String? | Links to a Patient, which only ever stores a phone number — never a BSUID. |
leadId | String? | Links to a Lead, auto-created only when the conversation has a phone number. |
A conversation can have phone and bsuid both set (the common steady state once a number is learned), just bsuid (a contact never seen by phone), or — for conversations predating this migration in a conflicting-data scenario — two separate rows that each have one but not the other, not automatically merged by this PR.