Changelog
Latest changes on the WhatsApp and RCS channels. Backwards compatibility is total in every case: integrations that do not use the new fields keep working unchanged.
1. WhatsApp — Send by BSUID
Besides the E.164 number, POST /v1/whatsapp/messages now accepts a BSUID
(Business Solution User ID) in the to field. A BSUID is the anonymous
identifier Meta assigns to a contact when the conversation comes from a
“Click to WhatsApp” flow or another channel where Meta does not expose the
user’s real number — it lets you reply without knowing their phone. Inbound
webhooks carry it in message.from_user_id.
If to matches neither format, the API rejects with 400. The format applies
equally to template sends (type: TEMPLATE) and every other message type.
2. WhatsApp — Automatic SMS fallback
POST /v1/whatsapp/messages now admits an optional fallback to SMS: if the
WhatsApp send fails definitively (synchronously or through a status webhook),
the API automatically retries the same recipient over SMS — without the
integrator having to detect the failure and resend.
Each send decides whether it wants the fallback and with which content, in the
new fallback field:
fallback.sms uses exactly the same shape as the body of
POST /v1/sms/messages (mask, text, has_accents, complement)
except to — the recipient is inherited from the original WhatsApp
message. The mask is validated at the moment of the original send (an
invalid or disabled mask rejects the whole request with 400 before
attempting WhatsApp). The fallback fires only once per message (atomic
lock) and it is a single hop: WhatsApp → SMS, no further cascade.
The feature must be enabled for the account by whoever manages it:
Synchronous response when the fallback activates. If the send fails
synchronously and the request included fallback.sms, the 201 response
includes fallback_id — the identifier to correlate the backup SMS in the
webhooks:
Webhooks. The status events of the backup SMS arrive as SMS webhooks
carrying origin_identifier — the message_id of the WhatsApp send that
originated the fallback. If the backup SMS also fails (or could not be
generated, e.g. the to was a BSUID with no real phone behind it), a final
Fallback exhausted event is emitted:
See the Fallback exhausted webhook in the WhatsApp API reference for the
message_id / origin_identifier semantics of each case.
3. RCS — Automatic SMS fallback
Same mechanism as section 2, applied to POST /v1/rcs/messages: if the RCS
message is not delivered, the API automatically retries over SMS.
What fires it:
- The RCS delivery status webhook reports
FAILEDorEXPIREDfor the message. - A late
FAILED/EXPIREDthat the RCS status priority logic already discards (a suppressed downgrade, an out-of-order event) does not fire the fallback — only a failure that actually advances the message status does. - Unlike WhatsApp, RCS has no synchronous failure point (the send always
responds
202 Accepted) — the RCS fallback fires only through webhooks.
Webhooks work as in section 2: the backup SMS statuses arrive as SMS webhooks
with origin_identifier, and the chain ends with a Fallback exhausted
event. The mask of the fallback is validated when sending the original RCS
message (fast 400), not when the fallback fires hours later.
4. RCS — Free-form sends (no template)
POST /v1/rcs/messages now accepts the message content directly in the
body, without a pre-created and approved template. The mode is selected
with the new discriminator field type:
If type is omitted, TEMPLATE is assumed: existing integrations do not
change.
Rules to keep in mind:
template_idis forbidden (400) with any free-formtype, and required withTEMPLATE.variablesalso applies to free-form content: the{{placeholders}}written intext,contentInfo, orrichCardare substituted with the same type rules (URL infileUrl/thumbnailUrl/iconUrl/url, free text elsewhere) and the same HEAD media validation.variables.UUID_MESSAGEis a reserved name, now rejected explicitly with400in the five types (before, in the template path, it was silently overwritten — the only behavior change in theTEMPLATEflow).- One content per request → 1 credit per free-form send.
- The billing channel derives from the agent, not the content: a
CONVERSATIONALagent bills asRCS_CONVERSATIONALwhether it sends text or a rich card; same for the conversation window. - Root-level
suggestions(message-level chips, max 11) are independent from the ones embedded inside a card, and can be combined. Never sendpostbackData— the backend generates it. - Agent ↔ content compatibility (replaces
RCS_TYPE_MISMATCH, which stays exclusive toTEMPLATEmode):
New errors:
Unchanged: the 202 Accepted response, the webhooks (same envelope, same
correlation by message_id, clicks on free-form suggestions arrive
classified with action/element_type/element_value exactly like template
ones), and the agents/templates endpoints. In the App-Key CSV report,
free-form sends show template_name = Envío libre, with the full
content (including type) in the data column.
5. WhatsApp — Inbound contacts messages (vCard)
The Inbound message webhook supports a new content type: contacts. It
fires when a user shares one or more contacts (vCard) in the conversation.
message.type can now be "contacts" (previously: text, image,
video, document, audio, button, location).
New message.contacts field (array): the shared contacts. Every field is
optional — Meta omits the ones the user did not share from their address book.
Note: in real traffic we have also observed the fields vcard (the full
vCard in Base64) and origin (e.g. "other"), which are not part of Meta’s
officially documented schema but do arrive in production. Those fields — and
any other not listed above — are propagated as-is: do not assume a closed
shape.
Example:

