Skip to main content

UC-005 — Multi-Channel Send with Automatic Fallback

FieldValue
IDUC-005
GoalSend a message on WhatsApp with automatic fallback to RCS and SMS
ChannelWhatsApp -> RCS -> SMS
ComplexityIntermediate
Estimated time15 minutes
APIs involvedPOST /api/message-server/whatsapp/send, GET /api/partner-gateway/v1/messages/status/{customerMessageId}

Real-world scenarios

  • Banca Adriatica — Transaction notification: The bank notifies the account holder of a suspicious transaction. WhatsApp priority for a rich message with confirm/block buttons, SMS fallback to guarantee receipt even if the customer does not use WhatsApp.
  • TelcoMobile — Billing reminder: Invoice due date reminder with payment link. WhatsApp for the attached document, SMS as a safety net.
  • FarmaExpress — Order ready: The online pharmacy notifies that the order is ready for pickup. WhatsApp with a pickup point map, SMS with a text address as fallback.

Prerequisites

Before you begin, make sure you have:

:::tip Test without costs Add "simulation": true in the request body to validate the flow without actually sending messages and without consuming credit. :::

Fallback flow

The diagram illustrates the fallback chain: the system first tries WhatsApp, then RCS if available, and finally SMS as a last resort.

Step 1 — Compose the message with fallback chain

The request body includes the main message (WhatsApp) and two fallback objects: fallbackRcs for RCS and fallbackSms for SMS.

:::info Important rule If you specify fallbackRcs, you must also include fallbackSms. You can, however, use only fallbackSms without RCS for a direct WhatsApp -> SMS fallback. :::

Body structure

FieldTypeRequiredDescription
destinationstringYesNumber in international format (e.g. +393401234567)
phoneNumberIdintegerYesSender WhatsApp Business number ID
templateobjectYes*Meta-approved template (*alternative to body)
placeholdersobjectNoValues to substitute in the template
fallbackRcs.agentIdintegerYesSender RCS agent ID
fallbackRcs.templateIdintegerYes*RCS template (*alternative to body)
fallbackSms.senderstringYesSMS sender (alphanumeric or numeric)
fallbackSms.textstringYesSMS fallback message text

Step 2 — Send the message

Call the WhatsApp endpoint with the complete fallback chain.

curl -X POST https://lora-api.agiletelecom.com/api/message-server/whatsapp/send \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"destination": "+393401234567",
"phoneNumberId": 5,
"template": {
"id": 42
},
"placeholders": {
"nome": "Giulia",
"importo": "1.250,00",
"data": "09/04/2026"
},
"enableNotification": true,
"messageId": "txn-notifica-20260409-001",
"fallbackRcs": {
"agentId": 1,
"templateId": 10
},
"fallbackSms": {
"sender": "BancaAdri",
"text": "Gentile Giulia, e stata registrata una transazione di EUR 1.250,00 in data 09/04/2026. Se non riconosci questa operazione, chiama il numero verde 800.123.456."
}
}'

Response — WhatsApp accepted

{
"messageId": "txn-notifica-20260409-001",
"simulation": false,
"results": {
"whatsapp": {
"accepted": true
},
"rcs": null,
"sms": null
}
}

When WhatsApp accepts the message, the rcs and sms fields remain null because the fallback was not triggered.

Response — Fallback activated down to SMS

{
"messageId": "txn-notifica-20260409-001",
"simulation": false,
"results": {
"whatsapp": {
"accepted": false
},
"rcs": {
"accepted": false,
"reasons": ["AGENT_NOT_REACHABLE"]
},
"sms": {
"accepted": true,
"unicode": false,
"parts": 2,
"reasons": []
}
}
}
Behind the scenes — How the fallback chain works
  1. WhatsApp attempt: The message is forwarded to Meta via WhatsApp Business API. If the recipient number is registered on WhatsApp and the template is approved, the message is accepted.
  2. RCS fallback: If WhatsApp fails (unregistered number, rejected template, network error), the system automatically tries RCS using the provided agentId and templateId.
  3. SMS fallback: If RCS also fails (incompatible device, unreachable agent), the system sends an SMS with the specified sender and text.

Each level is independent: you can receive separate delivery callbacks for the channel that actually delivered. The messageId stays the same throughout the chain, enabling end-to-end correlation.

Step 3 — Check which channel delivered

After a few seconds, query the delivery status to find out which channel actually delivered the message.

curl -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/messages/status/txn-notifica-20260409-001?channel=SMS" \
-H "X-Api-Key: YOUR_API_KEY"

Response — Delivered via SMS

{
"customerMessageId": "txn-notifica-20260409-001",
"channel": "SMS",
"destination": "+393401234567",
"deliveryStatus": "DELIVERED",
"deliveryStatusDescription": "Message delivered to handset",
"sendDate": "2026-04-09T10:15:00+02:00",
"deliveryDate": "2026-04-09T10:15:04+02:00",
"readDate": null
}

The channel field indicates which channel actually delivered the message.

Variant — Direct WhatsApp -> SMS fallback (without RCS)

If you do not have an RCS agent configured, you can skip the intermediate level by omitting fallbackRcs:

curl -X POST https://lora-api.agiletelecom.com/api/message-server/whatsapp/send \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"destination": "+393489876543",
"phoneNumberId": 5,
"template": {
"id": 55
},
"placeholders": {
"cliente": "Marco Bianchi",
"scadenza": "15/04/2026",
"importo": "89,90"
},
"fallbackSms": {
"sender": "TelcoMob",
"text": "Gentile Marco Bianchi, la sua fattura di EUR 89,90 scade il 15/04/2026. Acceda all area clienti per il pagamento."
}
}'
{
"messageId": "d3f8a1b2-c4e5-6789-abcd-ef0123456789",
"simulation": false,
"results": {
"whatsapp": {
"accepted": true
},
"rcs": null,
"sms": {
"accepted": true,
"unicode": false,
"parts": 1,
"reasons": []
}
}
}

Common errors

All channels fail

If no channel can accept the message, the response indicates accepted: false for every level:

{
"messageId": "txn-notifica-20260409-002",
"simulation": false,
"results": {
"whatsapp": {
"accepted": false
},
"rcs": {
"accepted": false,
"reasons": ["AGENT_NOT_REACHABLE"]
},
"sms": {
"accepted": false,
"reasons": ["INVALID_DESTINATION"]
}
}
}

Corrective actions table

SituationAction
All channels rejectVerify the recipient number and retry
Only SMS failsCheck the sender ID and text (length, special characters)
WhatsApp rejected, RCS/SMS okThe recipient may not have WhatsApp — the fallback is working correctly
422 errorTemplate not approved or invalid phoneNumberId
429 errorRate limit exceeded — wait and retry

Expected result

StepActionResult
1Compose body with fallbackRcs + fallbackSmsFallback chain configured
2POST /whatsapp/sendmessageId returned, at least one channel accepted: true
3GET /messages/status/{id}channel indicates the channel that delivered

Next steps