Passa al contenuto principale

UC-027 — Re-engagement Workflow (Retry su Canale Diverso)

CampoValore
IDUC-027
ObiettivoReinviare un messaggio su un canale alternativo se il primo tentativo fallisce
CanaleWhatsApp → SMS (fallback manuale)
Complessità⭐⭐⭐ Avanzato
Tempo stimato20 minuti
API coinvoltePOST /api/message-server/whatsapp/send, GET /api/partner-gateway/v1/messages/status/{customerMessageId}, POST /api/message-server/sms/send

Scenari reali

  • FashionOutlet — Promo non consegnata: Il messaggio promozionale WhatsApp per i saldi invernali non viene consegnato (utente senza WhatsApp). Il sistema rileva il fallimento e invia automaticamente un SMS con lo stesso contenuto.
  • ClinicaSalute — Reminder appuntamento: Il promemoria inviato via WhatsApp resta in stato SENT per oltre 2 ore. L'applicazione decide di inviare un SMS di backup per assicurare che il paziente riceva l'avviso.
  • BancaSicura — Notifica scadenza pagamento: L'avviso di scadenza rata inviato su WhatsApp fallisce. Il sistema scala su SMS entro 30 minuti per garantire la ricezione nei tempi utili.

:::info Differenza da UC-005 (Multi-Channel Fallback) Nel UC-005 il fallback e automatico: il gateway gestisce la catena WhatsApp → RCS → SMS in modo trasparente. In questo UC-027, il fallback e manuale e controllato dalla tua applicazione: sei tu a decidere quando, come e su quale canale ritentare. Questo approccio e utile quando vuoi applicare logica personalizzata (attese diverse, contenuti adattati per canale, limiti di budget). :::

Flusso del re-engagement

Il diagramma illustra il flusso decisionale: la tua applicazione invia su WhatsApp, attende il risultato, e in caso di fallimento adatta il contenuto e ritenta su SMS.

Step 1 — Invia il messaggio primario su WhatsApp

Invia il messaggio promozionale su WhatsApp:

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": "+393471234567",
"sender": "+393801234567",
"content": {
"templateName": "promo_saldi_inverno",
"language": "it",
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Marco" },
{ "type": "text", "text": "30%" },
{ "type": "text", "text": "15 aprile" }
]
}
]
},
"enableNotification": true
}'

Response — Messaggio accettato

{
"messageId": "b8f3a21c-7d44-4e19-9a1b-3c5d7e9f0a12",
"simulation": false,
"results": {
"whatsapp": {
"accepted": true,
"reasons": []
}
}
}

:::tip Salva il messageId e il timestamp Salva messageId e l'ora di invio nel tuo database. Ti serviranno per il polling e per calcolare il timeout di attesa prima del retry. :::

Step 2 — Attendi e verifica lo stato di consegna

Dopo un intervallo ragionevole (es. 2 ore per messaggi promozionali, 30 minuti per notifiche urgenti), verifica lo stato:

curl -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/messages/status/b8f3a21c-7d44-4e19-9a1b-3c5d7e9f0a12?channel=WHATSAPP" \
-H "X-Api-Key: YOUR_API_KEY"

Response — Messaggio non consegnato

{
"customerMessageId": "b8f3a21c-7d44-4e19-9a1b-3c5d7e9f0a12",
"channel": "WHATSAPP",
"destination": "+393471234567",
"deliveryStatus": "SENT",
"deliveryStatusDescription": "Message sent but not delivered to device",
"sendDate": "2026-04-09T10:00:00+02:00",
"deliveryDate": null
}
Dietro le quinte — Quando attivare il fallback

La decisione di quando attivare il retry dipende dal tipo di messaggio:

Tipo messaggioTimeout suggeritoMotivazione
Promozionale2-4 oreL'utente potrebbe leggere più tardi, non urgente
Reminder appuntamento30-60 minutiDeve arrivare in tempo utile
Notifica sicurezza10-15 minutiCritico, necessita consegna immediata
Billing/scadenza1-2 oreImportante ma non critico nell'immediato

Gli stati che indicano fallimento sono:

  • ERROR (statusCode 6): errore definitivo, retry immediato
  • EXPIRED (statusCode 8): TTL superato, retry immediato
  • SENT dopo il timeout: messaggio inviato ma non consegnato, probabile assenza di WhatsApp

Step 3 — Invia il fallback su SMS

Se lo stato non e DELIVERED o READ dopo il timeout, adatta il contenuto e invia via SMS:

curl -X POST https://lora-api.agiletelecom.com/api/message-server/sms/send \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"destination": "+393471234567",
"sender": "FashionOut",
"body": "Ciao Marco! Saldi invernali FashionOutlet: -30% su tutto fino al 15 aprile. Scopri le offerte: https://fashionoutlet.it/saldi Rispondi STOP per non ricevere più messaggi.",
"campaignId": "saldi-inverno-2026-retry",
"enableNotification": true
}'

Response — SMS accettato

{ "messageId": "c9a4b32d-8e55-4f20-ab2c-4d6e8f0a1b23", "simulation": false, "results": { "sms": { "accepted": true, "parts": 1 } } }

:::note Adatta il contenuto per il canale Il testo SMS ha limiti diversi da WhatsApp. Rimuovi formattazioni ricche, accorcia i link e includi sempre l'opzione di opt-out. :::

Step 4 — Verifica la consegna finale

Controlla lo stato dell'SMS di fallback:

curl -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/messages/status/c9a4b32d-8e55-4f20-ab2c-4d6e8f0a1b23?channel=SMS" \
-H "X-Api-Key: YOUR_API_KEY"

Response — Consegnato

{ "customerMessageId": "c9a4b32d-8e55-4f20-ab2c-4d6e8f0a1b23", "channel": "SMS", "deliveryStatus": "DELIVERED", "deliveryDate": "2026-04-09T12:05:02+02:00" }

Risultato atteso

StepAzioneRisultato
1POST /whatsapp/sendmessageId restituito, accepted: true
2GET /messages/status/{id}deliveryStatus: "SENT" (non consegnato dopo timeout)
3POST /sms/sendNuovo messageId, accepted: true
4GET /messages/status/{id}deliveryStatus: "DELIVERED" su SMS

Esempio completo end-to-end

#!/bin/bash
# Re-engagement workflow: WhatsApp → SMS fallback
API_KEY="YOUR_API_KEY"
BASE_URL="https://lora-api.agiletelecom.com"
TIMEOUT_SECONDS=7200 # 2 ore per messaggi promozionali

# 1. Invio WhatsApp
WA_ID=$(curl -s -X POST "${BASE_URL}/api/message-server/whatsapp/send" \
-H "Content-Type: application/json" -H "X-Api-Key: ${API_KEY}" \
-d '{"destination":"+393471234567","sender":"+393801234567","content":{"templateName":"promo_saldi_inverno","language":"it","components":[{"type":"body","parameters":[{"type":"text","text":"Marco"},{"type":"text","text":"30%"},{"type":"text","text":"15 aprile"}]}]},"enableNotification":true}' | jq -r '.messageId')

# 2. Attendi e verifica
sleep ${TIMEOUT_SECONDS}
STATUS=$(curl -s -X GET "${BASE_URL}/api/partner-gateway/v1/messages/status/${WA_ID}?channel=WHATSAPP" \
-H "X-Api-Key: ${API_KEY}" | jq -r '.deliveryStatus')

# 3. Se non consegnato, retry su SMS
if [[ "$STATUS" != "DELIVERED" && "$STATUS" != "READ" ]]; then
SMS_ID=$(curl -s -X POST "${BASE_URL}/api/message-server/sms/send" \
-H "Content-Type: application/json" -H "X-Api-Key: ${API_KEY}" \
-d '{"destination":"+393471234567","sender":"FashionOut","body":"Ciao Marco! Saldi invernali: -30% fino al 15 aprile. https://fashionoutlet.it/saldi","campaignId":"saldi-inverno-2026-retry"}' | jq -r '.messageId')
echo "Retry SMS inviato: ${SMS_ID}"
fi

Varianti

Retry con escalation a tre canali

Aggiungi RCS come livello intermedio: WhatsApp → RCS → SMS. Dopo il fallimento WhatsApp, prova POST /rcs/send prima di ricadere su SMS.

Retry con contenuto differenziato per urgenza

Per notifiche critiche (es. sicurezza bancaria), riduci il timeout a 10 minuti e usa un testo SMS con tono urgente.

Errori comuni

WhatsApp — Template non approvato

{ "results": { "whatsapp": { "accepted": false, "reasons": ["Template not approved or not found"] } } }

Soluzione: Verifica che il template sia stato approvato da Meta (vedi UC-013).

Doppia consegna

Se il messaggio WhatsApp viene consegnato dopo il retry SMS, l'utente ricevera il messaggio su entrambi i canali. Usa timeout adeguati al tipo di messaggio (vedi tabella nello Step 2).

Prossimi passi

Riferimenti