UC-004 — Verifica Stato di Consegna
| Campo | Valore |
|---|---|
| ID | UC-004 |
| Obiettivo | Verificare lo stato di consegna dei messaggi con polling e webhook |
| Canale | Multi-canale (SMS, RCS, WhatsApp) |
| Complessità | Base |
| Tempo stimato | 15 minuti |
| API coinvolte | GET /api/partner-gateway/v1/messages/status/{customerMessageId}, GET /api/partner-gateway/v1/messages/status |
Scenari reali
- Dashboard OTP — Verifica invii: BancaSicura monitora in tempo reale se i codici OTP vengono consegnati entro 5 secondi, attivando un canale alternativo in caso di fallimento.
- Report consegna campagna: MarketingPro genera un report di fine campagna SMS con percentuali di consegna, errori e tempi medi.
- Monitoring real-time: TechStore integra lo status check nel proprio CRM per mostrare un badge "Consegnato" o "In attesa" accanto a ogni comunicazione inviata.
Polling vs Webhook
| Caratteristica | Polling | Webhook |
|---|---|---|
| Direzione | Il tuo server chiama l'API | L'API chiama il tuo server |
| Latenza | Dipende dall'intervallo di polling | Tempo reale |
| Carico API | Proporzionale al numero di chiamate | Una chiamata per evento |
| Complessità | Bassa (basta un loop) | Media (serve endpoint pubblico) |
| Ideale per | Verifiche puntuali, debug, piccoli volumi | Produzione, alti volumi, real-time |
Usa il polling per test, debug e verifiche manuali. Usa i webhook in produzione per ricevere notifiche in tempo reale senza sovraccaricare l'API. Vedi la guida Webhook per la configurazione.
Step 1 — Invia un messaggio (prerequisito)
Per verificare lo stato, devi prima aver inviato un messaggio e aver salvato il messageId. Esempio rapido con SMS:
curl -s -X POST https://api.qlara.ai/api/message-server/sms/send \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"destination": "+393471234567",
"sender": "BancaSicura",
"body": "Il tuo codice OTP e: 847293. Valido per 5 minuti.",
"enableNotification": true
}'
Response
{
"messageId": "d1e2f3a4-b5c6-7890-d1e2-f3a4b5c67890",
"simulation": false,
"results": {
"sms": {
"accepted": true,
"unicode": false,
"parts": 1,
"reasons": []
}
}
}
Dietro le quinte — Timeline degli stati
Dopo l'invio, il messaggio attraversa questi stati in sequenza:
- In transito — Il gateway ha accettato il messaggio e lo ha inoltrato, ma non è ancora tornata alcuna ricevuta. Lo stato è
ACCEPTEDsu SMS eUNKNOWNsu RCS e WhatsApp, che non hanno uno stato intermedio proprio. - Stato finale — Arriva la ricevuta dell'operatore o della piattaforma e lo stato non cambia più:
- SMS:
DELIVERED, oppure un fallimento:REJECTED,UNDELIVERABLE,EXPIRED(non consegnato entro la finestra di validità) oDELETED. - RCS:
DELIVERED, oppure un fallimento:ERROR,DISABLED,UNSUPPORTEDoEXPIRED. - WhatsApp: come RCS, più
CONVERSATION_CLOSED.
- SMS:
- Lettura (solo RCS/WhatsApp) — La lettura non è uno stato: il messaggio resta
DELIVERED. Su WhatsApp l'ora di lettura viene valorizzata inreadDate; su RCS e WhatsApp il webhook invia anche un eventoREAD.
La transizione da ACCEPTED/UNKNOWN a DELIVERED avviene tipicamente in 1-5 secondi per SMS, 0.5-2 secondi per RCS/WhatsApp.
Step 2 — Polling singolo
Interroga lo stato di un singolo messaggio usando il messageId come path parameter e il channel come query parameter.
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/messages/status/d1e2f3a4-b5c6-7890-d1e2-f3a4b5c67890?channel=SMS" \
-H "X-Api-Key: YOUR_API_KEY"
Response — DELIVERED
{
"customerMessageId": "d1e2f3a4-b5c6-7890-d1e2-f3a4b5c67890",
"channel": "SMS",
"destination": "+393471234567",
"deliveryStatus": "DELIVERED",
"deliveryStatusDescription": "delivered",
"sendDate": "2026-04-09T15:00:00+02:00",
"deliveryDate": "2026-04-09T15:00:03+02:00",
"readDate": null
}
Response — UNDELIVERABLE
{
"customerMessageId": "d1e2f3a4-b5c6-7890-d1e2-f3a4b5c67890",
"channel": "SMS",
"destination": "+393471234567",
"deliveryStatus": "UNDELIVERABLE",
"deliveryStatusDescription": "undeliverable",
"sendDate": "2026-04-09T15:00:00+02:00",
"deliveryDate": null,
"readDate": null
}
Dietro le quinte — Tabella completa degli status
| Status | Codice webhook | deliveryStatusDescription | Canale | Descrizione |
|---|---|---|---|---|
ACCEPTED | 1 | accepted | SMS | Affidato all'operatore, nessuna ricevuta ancora. Non finale |
REJECTED | 2 | rejected | SMS | L'operatore ha rifiutato il messaggio. Finale |
DELIVERED | 3 | delivered | SMS, RCS, WhatsApp | Messaggio consegnato al dispositivo. Finale |
EXPIRED | 4 | expired | SMS, RCS, WhatsApp | Non consegnato entro la finestra di validità. Finale |
DELETED | 5 | deleted | SMS | Annullato prima della consegna. Finale |
UNDELIVERABLE | 6 | undeliverable | SMS | La destinazione non può riceverlo (numero irraggiungibile o non valido). Finale |
ERROR | 9 | general error | RCS, WhatsApp | Consegna fallita. Finale |
DISABLED | 10 | disabled | RCS, WhatsApp | Il destinatario ha il canale disattivato. Finale |
UNSUPPORTED | 11 | unsupported | RCS, WhatsApp | Il dispositivo o il numero non supporta il canale. Finale |
CONVERSATION_CLOSED | 12 | conversation closed | La finestra di assistenza clienti di 24 ore era chiusa. Finale | |
UNKNOWN | 0 | unknown | SMS, RCS, WhatsApp | Nessuno stato registrato per il messaggio. Su RCS e WhatsApp, lo stato normale mentre è in transito |
Note sui codici webhook: Il webhook di delivery status invia in statusCode gli stessi codici numerici di questa tabella e in description la descrizione in minuscolo. Nell'API di status polling, il campo deliveryStatus è il nome nella prima colonna. Il webhook parte quando arriva la ricevuta dell'operatore o della piattaforma, quindi non invia mai ACCEPTED (1) né UNKNOWN (0).
Step 3 — Polling batch
Per verificare lo stato di più messaggi in una sola chiamata, usa l'endpoint batch. Tutti gli ID devono appartenere allo stesso canale.
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/messages/status?channel=SMS&ids=d1e2f3a4-b5c6-7890-d1e2-f3a4b5c67890,a1b2c3d4-e5f6-7890-abcd-ef1234567890,f47ac10b-58cc-4372-a567-0e02b2c3d479" \
-H "X-Api-Key: YOUR_API_KEY"
Response — Batch status
[
{
"customerMessageId": "d1e2f3a4-b5c6-7890-d1e2-f3a4b5c67890",
"channel": "SMS",
"destination": "+393471234567",
"deliveryStatus": "DELIVERED",
"deliveryStatusDescription": "delivered",
"sendDate": "2026-04-09T15:00:00+02:00",
"deliveryDate": "2026-04-09T15:00:03+02:00",
"readDate": null
},
{
"customerMessageId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"channel": "SMS",
"destination": "+393481234567",
"deliveryStatus": "DELIVERED",
"deliveryStatusDescription": "delivered",
"sendDate": "2026-04-09T15:00:01+02:00",
"deliveryDate": "2026-04-09T15:00:04+02:00",
"readDate": null
},
{
"customerMessageId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"channel": "SMS",
"destination": "+393491234567",
"deliveryStatus": "UNDELIVERABLE",
"deliveryStatusDescription": "undeliverable",
"sendDate": "2026-04-09T15:00:01+02:00",
"deliveryDate": null,
"readDate": null
}
]
Gli ID che non corrispondono a nessun messaggio vengono silenziosamente omessi dalla response. Se invii 3 ID e ricevi solo 2 risultati, il terzo non e stato trovato.
Dietro le quinte — Limiti e best practice del batch
- Limite ID: Puoi inviare fino a diverse centinaia di ID in una singola chiamata. Per volumi superiori, suddividi in più richieste.
- Stesso canale: Tutti gli ID devono appartenere allo stesso canale (SMS, RCS o WHATSAPP). Per canali misti, esegui chiamate separate.
- Ordine risultati: I risultati non sono ordinati. Usa
customerMessageIdper fare il match con i tuoi record. - Polling interval: Per verifiche automatiche, usa un intervallo di almeno 5 secondi tra una chiamata e l'altra. Per volumi elevati, passa ai webhook.
Esempio: polling loop con retry
Uno script bash che verifica lo stato di un SMS ogni 3 secondi, con timeout di 30 secondi. Si ferma su DELIVERED o su un fallimento finale SMS; gli stati di fallimento dipendono dal canale, quindi per RCS usa ERROR|DISABLED|UNSUPPORTED|EXPIRED e per WhatsApp aggiungi CONVERSATION_CLOSED:
#!/bin/bash
MESSAGE_ID="d1e2f3a4-b5c6-7890-d1e2-f3a4b5c67890"
API_KEY="YOUR_API_KEY"
MAX_ATTEMPTS=10
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
ATTEMPT=$((ATTEMPT + 1))
echo "Tentativo $ATTEMPT/$MAX_ATTEMPTS..."
STATUS=$(curl -s -X GET \
"https://api.qlara.ai/api/partner-gateway/v1/messages/status/${MESSAGE_ID}?channel=SMS" \
-H "X-Api-Key: ${API_KEY}" | jq -r '.deliveryStatus')
echo "Status: $STATUS"
case "$STATUS" in
DELIVERED)
echo "Messaggio consegnato!"
exit 0
;;
REJECTED|UNDELIVERABLE|EXPIRED|DELETED) # fallimenti finali SMS
echo "Errore di consegna: $STATUS"
exit 1
;;
esac
sleep 3
done
echo "Timeout: stato finale non raggiunto"
exit 2
Confronto canali
| Campo | SMS | RCS | |
|---|---|---|---|
deliveryStatus | ACCEPTED, REJECTED, DELIVERED, EXPIRED, DELETED, UNDELIVERABLE, UNKNOWN | DELIVERED, EXPIRED, ERROR, DISABLED, UNSUPPORTED, UNKNOWN | DELIVERED, EXPIRED, ERROR, DISABLED, UNSUPPORTED, CONVERSATION_CLOSED, UNKNOWN |
| Stato in transito | ACCEPTED | UNKNOWN | UNKNOWN |
readDate | Sempre null | Sempre null | Presente se letto |
| Latenza tipica DELIVERED | 1-5 secondi | 0.5-2 secondi | 0.5-2 secondi |
| Webhook READ | Non disponibile | Disponibile | Disponibile |
Errori comuni
404 — Messaggio non trovato
{}
Soluzione: Verifica che il customerMessageId sia corretto e che il parametro channel corrisponda al canale usato per l'invio. I messaggi molto vecchi potrebbero non essere più disponibili.
Canale errato nel parametro channel
Se invii un messaggio via SMS ma interroghi lo stato con channel=RCS, riceverai un 404 anche se il messaggio esiste. Assicurati che il canale nella query corrisponda a quello usato nell'invio.
Status ACCEPTED o UNKNOWN persistente
Finché non arriva la ricevuta, un messaggio risulta ACCEPTED su SMS e UNKNOWN su RCS e WhatsApp. Cosa significa un'attesa lunga dipende dal canale:
- RCS e WhatsApp:
UNKNOWNè il normale stato in transito, non un problema di routing. Questi canali non hanno uno stato intermedio, quindi il messaggio restaUNKNOWNfinché non diventaDELIVEREDo fallisce, e può volerci un po' (per esempio se il telefono del destinatario è spento). - SMS: se lo status resta
ACCEPTEDper più di 60 secondi, l'operatore non ha ancora restituito la ricevuta. Verifica:- Il numero del destinatario è valido e raggiungibile
- L'operatore del destinatario è supportato
- Non ci sono problemi di rete in corso
Risultato atteso
| Step | Azione | Risultato |
|---|---|---|
| 1 | POST /sms/send (o RCS/WhatsApp) | messageId salvato |
| 2 | GET /messages/status/{id}?channel=SMS | deliveryStatus: "DELIVERED" |
| 3 | GET /messages/status?channel=SMS&ids=id1,id2,id3 | Array di status per ogni messaggio |
Prossimi passi
- UC-001 — Invio SMS Singolo: Scenario completo di invio e verifica SMS
- UC-002 — Invio RCS Rich Card: Rich card con media e bottoni interattivi
- UC-003 — Invio WhatsApp Template: Template con status tracking
- Guida Webhook: Configura i webhook per notifiche real-time
- Guida Autenticazione: Setup API Key e Basic Auth