Passa al contenuto principale

Webhook e Notifiche di Consegna

Ci sono due modi per tracciare la consegna dei messaggi: polling e webhook. Scegli l'approccio più adatto al tuo caso d'uso.

Polling​

Interroga lo stato di consegna su richiesta:

GET /messages/status/{customerMessageId}?channel=SMS

channel è obbligatorio: SMS, RCS o WHATSAPP. Oppure controlla più messaggi dello stesso canale contemporaneamente:

GET /messages/status?channel=SMS&ids=id1,id2,id3

Entrambe restituiscono il deliveryStatus del messaggio (DELIVERED, UNDELIVERABLE, EXPIRED, ...): la tabella Delivery Statuses elenca tutti i valori.

Quando usare il polling:

  • Volume di messaggi ridotto
  • Controlli di stato occasionali
  • Integrazioni semplici che non necessitano di un endpoint pubblico

Webhook​

Registra un URL di callback HTTPS per ricevere aggiornamenti sullo stato di consegna in tempo reale, non appena il carrier li segnala.

Configura un webhook​

POST /webhooks/delivery-status

Fornisci il tuo URL di callback come {"callbackUrl": "https://..."}. Lo stesso URL riceve gli eventi di SMS, RCS e WhatsApp. L'API invierà richieste HTTP POST a questo URL quando arriva una ricevuta di consegna, quando un destinatario legge un messaggio RCS o WhatsApp e quando un utente finale ti scrive.

Gestisci il tuo webhook​

AzioneEndpointRisposta
Ottieni webhook attualeGET /webhooks/delivery-status200 con companyId e callbackUrl, 404 se assente
Crea webhookPOST /webhooks/delivery-status201 con companyId e callbackUrl, 409 se ne esiste già uno
Aggiorna URL webhookPUT /webhooks/delivery-status200 con companyId e callbackUrl, 404 se assente
Revoca webhookDELETE /webhooks/delivery-status204 senza corpo, 404 se assente
Informazioni

È consentito un solo webhook di stato consegna attivo per account. Se ne esiste già uno, la POST risponde 409 Conflict e lo lascia invariato: cambia l'URL con PUT, oppure elimina prima il webhook con DELETE.

Payload del webhook​

Quando arriva una ricevuta di consegna, l'API invia una richiesta POST al tuo URL di callback. Il corpo è JSON (Content-Type: application/json) e i campi senza valore vengono omessi.

Esempio di notifica di consegna (SMS):

{
"eventType": "DELIVERY",
"channel": "SMS",
"messageId": "order-12345",
"destination": "+393401234567",
"statusCode": 3,
"description": "delivered",
"eventDate": "2026-04-09T11:30:05+02:00",
"price": 0.035,
"totalParts": 1,
"numPart": 1
}

messageId è l'id del messaggio che hai inviato, lo stesso valore che l'API di polling chiama customerMessageId. Un SMS produce un evento per ogni parte (numPart di totalParts). Gli eventi DELIVERY di RCS e WhatsApp hanno gli stessi campi, senza totalParts e numPart.

Esempio di notifica di lettura (solo WhatsApp/RCS):

{
"eventType": "READ",
"channel": "WHATSAPP",
"messageId": "e76614d1-4ac1-4d94-89f0-d07f1b5a190c",
"destination": "+393401234567",
"eventDate": "2026-04-09T11:31:15+02:00"
}

Un evento READ non ha statusCode: un messaggio letto resta DELIVERED.

Esempio di messaggio in arrivo (solo WhatsApp/RCS):

{
"eventType": "INBOUND",
"channel": "WHATSAPP",
"messageId": "b7e2c9a4-3f1d-4c6e-8a5b-0d9f2e7c4a18",
"source": "+393401234567",
"destination": "+393409876543",
"receivedDate": "2026-04-09T11:35:00+02:00",
"messageType": "TEXT",
"text": "Sì, confermo l'appuntamento"
}

source è il numero dell'utente finale e destination il tuo numero WhatsApp (su RCS, l'id del tuo agente). messageId identifica il messaggio in arrivo nella conversazione. I messaggi multimediali includono anche un mediaKey.

Lo statusCode di un evento DELIVERY, con la sua description:

Codice di statoDescrizioneCanaliSignificato
1acceptedSMSConsegnato al carrier, nessuna ricevuta ancora. Mai inviato come evento.
2rejectedSMSIl carrier ha rifiutato il messaggio.
3deliveredSMS, RCS, WhatsAppIl messaggio ha raggiunto il telefono.
4expiredSMS, RCS, WhatsAppNon consegnato entro il periodo di validità.
5deletedSMSAnnullato prima della consegna.
6undeliverableSMSLa destinazione non può riceverlo (numero irraggiungibile o non valido).
9general errorRCS, WhatsAppConsegna fallita.
10disabledRCS, WhatsAppIl destinatario ha il canale disattivato.
11unsupportedRCS, WhatsAppIl dispositivo o il numero non supporta il canale.
12conversation closedWhatsAppLa finestra di assistenza di 24 ore era chiusa.
0unknownSMS, RCS, WhatsAppNessuno stato disponibile per il messaggio. Mai inviato come evento.

Un evento viene inviato solo quando arriva la ricevuta, quindi ogni codice che ricevi è definitivo. Un messaggio ancora in transito risulta ACCEPTED su SMS e UNKNOWN su RCS e WhatsApp quando lo interroghi in polling, e non produce eventi. I codici corrispondono ai valori di deliveryStatus dell'API di polling: vedi Delivery Statuses.

Suggerimento

simulation: true valida una richiesta di invio senza inviare il messaggio, quindi non produce alcuna callback webhook. Per testare il tuo handler dall'inizio alla fine, invia un messaggio reale a un numero di tua proprietà.

Best practice​

  1. Usa HTTPS su un host pubblico -- L'URL di callback viene validato al momento della registrazione. Deve usare https sulla porta 443 (quella predefinita) o 8443, non deve contenere credenziali né frammenti #, e il suo host deve risolvere solo a indirizzi pubblicamente raggiungibili. Indirizzi di loopback, privati, link-local, carrier-grade-NAT e unique-local vengono rifiutati, così come gli host che non risolvono. Un URL che non supera uno di questi controlli viene rifiutato con 400.
  2. Rispondi velocemente -- Rispondi con un qualsiasi 2xx entro 5 secondi (3 secondi per la connessione). Elabora il payload in modo asincrono se necessario.
  3. Gestisci i retry -- Se il tuo endpoint non è raggiungibile o non risponde 2xx, il sistema ritenta: al massimo 5 tentativi in tutto, a distanza di almeno 5 minuti per gli SMS e di almeno 10 minuti per RCS e WhatsApp, e solo per i messaggi inviati negli ultimi 10 giorni. Gli eventi possono arrivare più di una volta e in ordine sparso, quindi rendi la tua elaborazione idempotente, usando come chiave eventType + messageId (+ numPart per gli SMS).
  4. Valida il payload -- Le callback non hanno un header di firma. Tratta il corpo come input non fidato e verifica che il messageId di un evento DELIVERY o READ appartenga a un messaggio che hai inviato.
  5. Monitora i fallimenti -- Se il tuo endpoint webhook fallisce costantemente, controlla i log del server e assicurati che l'URL sia accessibile. Gli eventi che esauriscono i tentativi non vengono più inviati: recupera quegli stati in polling.

Scegliere tra polling e webhook​

AspettoPollingWebhook
LatenzaDipende dalla frequenza di pollingQuasi in tempo reale
ComplessitàSemplici richieste GETRichiede un endpoint HTTPS pubblico
ScalabilitàAumenta le chiamate API a scalaPush-based, nessuna chiamata API extra
Ideale perVolume ridotto, controlli occasionaliVolume elevato, dashboard in tempo reale

Consulta il Riferimento API Webhook e il Riferimento API Stato Consegna Messaggi per la documentazione completa degli endpoint.