Due payload di webhook trasportano gli eventi di messaggistica. Un evento di stato di consegna (DLR) riporta l'esito di un messaggio — message_id, un enum di stato (accepted, delivered, undelivered, expired, rejected), una causa di errore e i timestamp. Un evento in ingresso (MO) riporta un messaggio che un abbonato ti ha inviato. Entrambi sono gli equivalenti HTTP delle ricevute SMPP deliver_sm e dei messaggi mobile-originated.
- La tua applicazioneInviato tramite REST API o SMPP
- Piattaforma BroadNetValida, instrada e fattura ogni messaggio
- SMSC dell’operatoreConnessione diretta con l'operatore
- Dispositivo dell'abbonatoIl messaggio viene consegnato
Due famiglie di eventi: di stato e in ingresso
Una piattaforma di messaggistica emette due callback fondamentalmente diverse. Un evento di stato di consegna (DLR, delivery receipt) è il seguito asincrono di un messaggio che hai inviato: ti dice cosa gli è alla fine successo nella rete dell'operatore. Un evento in ingresso (MO, mobile-originated) è non sollecitato — un messaggio che un abbonato ha inviato a uno dei tuoi numeri o una risposta a una campagna. Condividono il transport dei webhook e la firma, ma i loro schemi e il loro significato differiscono, quindi un consumer robusto si dirama su un discriminatore di tipo di evento prima di fare il parsing del resto. Entrambi sono l'espressione a livello HTTP di ciò che SMPP consegna come PDU deliver_sm: un flag di receipt distingue un DLR da un MO sul filo, e la stessa distinzione è un campo event esplicito su HTTP.
Payload di stato di consegna (DLR)
Un payload di stato di consegna si correla all'invio originale tramite il message_id assegnato dal server e riporta uno stato tratto da una piccola enumerazione, più la causa e i timestamp che consentono di misurare la latenza e riconciliare la fatturazione. L'enum di stato è il cuore di tutto: distingue uno stato intermedio accepted/enroute dagli stati terminali, e separa un delivered positivo dai diversi modi in cui un messaggio può fallire. Gli stati negativi terminali portano un codice di errore e una causa leggibile dall'uomo così che un consumer possa decidere se la destinazione è permanentemente inutilizzabile (sopprimerla) o se il fallimento è stato transitorio (sicuro da reinviare). I timestamp includono tipicamente quando la piattaforma ha accettato il messaggio e quando si è verificato lo stato terminale.
{
"event": "message.delivered",
"message_id": "01HZY8Q3M6",
"to": "+15551234567",
"status": "delivered",
"error": null,
"reason": null,
"submitted_at": "2026-07-19T09:15:22Z",
"done_at": "2026-07-19T09:15:25Z",
"sequence": 3
}L'enumerazione dello stato di consegna
Standardizzare i valori di stato è ciò che consente a un solo consumer di gestire ogni operatore, perché le risposte grezze di rete variano enormemente. Un enum canonico le mappa su una manciata di stati con semantica chiara: se lo stato è terminale e se è un successo. Gli stati intermedi (accepted, enroute) possono essere superati da un evento successivo per lo stesso id di messaggio, ed è esattamente per questo che i payload portano una sequence o un timestamp e per cui i consumer applicano la regola di auto-ordinamento dell'affidabilità dei webhook — un accepted tardivo non deve mai sovrascrivere un delivered precedente.
| status | Terminale | Significato |
|---|---|---|
| accepted | No | La piattaforma ha accettato il messaggio per la consegna |
| enroute | No | Consegnato all'operatore, in attesa di conferma di consegna |
| delivered | Sì | Consegna al terminale confermata |
| undelivered | Sì | L'operatore non è riuscito a consegnare (vedi errore/motivo) |
| expired | Sì | Il periodo di validità è scaduto prima della consegna |
| rejected | Sì | Rifiutato (numero non valido, mittente bloccato, filtro antispam) |
| unknown | Sì | L'operatore non ha restituito uno stato finale definitivo |
Payload di messaggio in ingresso (MO)
Un evento in ingresso trasporta il contenuto del messaggio più il routing necessario per rispondere e per correlare una conversazione. I campi critici sono from (l'MSISDN dell'abbonato in E.164), to (il numero o lo short/long code a cui ha scritto) e il text; accanto a essi un id di messaggio per il messaggio in ingresso stesso, un timestamp di ricezione e — poiché l'SMS in ingresso è soggetto alle stesse regole di encoding e segmentazione di quello in uscita — l'encoding e, per un messaggio multipart, il reference di concatenazione e gli indici delle parti così che il consumer possa riassemblare il testo completo. Gli eventi in ingresso sono il modo in cui vengono guidati le campagne a keyword, le conversazioni bidirezionali e i flussi di compliance STOP/HELP.
{
"event": "message.inbound",
"message_id": "01HZY8R7T0",
"from": "+15551234567",
"to": "44160",
"text": "STOP",
"encoding": "GSM7",
"received_at": "2026-07-19T09:20:11Z",
"concat": { "ref": null, "part": 1, "total": 1 }
}Tassonomia dei tipi di evento
Oltre a DLR e MO, una piattaforma emette eventi di ciclo di vita e di account, e uno schema di denominazione coerente — una stringa puntata resource.action — consente a un consumer di iscriversi a essi e instradarli in modo pulito. Gli eventi di stato di consegna sono variazioni su message.<status>; l'evento in ingresso è message.inbound. Il raggruppamento per prefisso di risorsa significa che un consumer può matchare message.* per tutto ciò che riguarda un messaggio e riservare altri prefissi agli eventi di account o di numero. Ogni evento dovrebbe anche portare un event id stabile (usato come nonce di firma e chiave di dedup) e la stringa di tipo, così che il discriminatore e la chiave di idempotenza siano sempre presenti.
| Tipo di evento | Famiglia | Attivato quando |
|---|---|---|
| message.accepted | Stato (DLR) | Messaggio accettato per la consegna |
| message.delivered | Stato (DLR) | Consegna al terminale confermata |
| message.undelivered | Stato (DLR) | L'operatore non è riuscito a consegnare |
| message.expired | Stato (DLR) | Periodo di validità scaduto |
| message.rejected | Stato (DLR) | Messaggio rifiutato a monte |
| message.inbound | Inbound (MO) | Un abbonato ti ha inviato un messaggio |
Mappare un DLR HTTP su SMPP deliver_sm
La callback di stato di consegna HTTP e la delivery receipt SMPP sono la stessa informazione in due codifiche, e una piattaforma che fa da ponte tra REST e SMPP traduce tra loro. Su SMPP una ricevuta arriva come PDU deliver_sm il cui esm_class la marca come ricevuta; il suo campo short-message trasporta una ricevuta testuale con i campi id, stat ed err, e la TLV message_state trasporta lo stato numerico. Il DLR HTTP li solleva in JSON: il token stat SMPP mappa sull'enum di stato canonico, il valore err mappa sul campo error e i tempi submit/done della ricevuta mappano su submitted_at/done_at. Comprendere questa mappatura è ciò che consente a un unico percorso di codice di gestione delle consegne di servire entrambi i transport; il formato della ricevuta SMPP e la PDU deliver_sm sono documentati in dettaglio nel riferimento SMPP.
| Campo della ricevuta SMPP | Campo HTTP DLR | Nota |
|---|---|---|
| id (ricevuta) | message_id | Corrisponde all'originale submit_sm / POST |
| stat (DELIVRD/UNDELIV/EXPIRED/REJECTD) | status | Il token corrisponde all'enum canonico |
| err | error | Codice di errore operatore/rete |
| message_state TLV | status (valore numerico sottostante) | Stato numerico SMPP dietro il token |
| data di invio / data di completamento | submitted_at / done_at | Timestamp di latenza e riconciliazione |
Domande frequenti
Che cosa c'è in un payload di webhook di stato di consegna (DLR)?
Il message_id assegnato dal server che lo correla al tuo invio, uno stato tratto da un enum canonico (accepted, enroute, delivered, undelivered, expired, rejected, unknown), un codice di errore e una causa leggibile dall'uomo per i fallimenti, e i timestamp di quando il messaggio è stato inviato e di quando si è verificato lo stato terminale.
In cosa differisce un evento in ingresso (MO) da un DLR?
Un DLR è l'esito asincrono di un messaggio che hai inviato. Un evento in ingresso (MO) è non sollecitato — un messaggio che un abbonato ha inviato al tuo numero o una risposta a una campagna — e trasporta from, to, il text, l'encoding e, per i messaggi multipart, i campi di concatenazione. Condividono transport e firma ma hanno schemi diversi, quindi i consumer si diramano prima sul tipo di evento.
Perché standardizzare l'enum di stato di consegna?
Perché le risposte grezze degli operatori variano enormemente. Mapparle su un piccolo enum canonico con semantica terminale-e-successo chiara consente a un solo consumer di gestire ogni operatore in modo uniforme, e ti consente di decidere dal solo stato se sopprimere una destinazione inutilizzabile, reinviare un fallimento transitorio o registrare una consegna confermata.
Come impedisco che un 'accepted' tardivo sovrascriva un 'delivered' precedente?
Usa i campi di auto-ordinamento. I payload DLR portano un timestamp e spesso una sequence; il consumer li confronta con l'ultimo stato registrato per quell'id di messaggio e scarta ogni evento più vecchio di quanto già possiede, così che uno stato intermedio fuori ordine non calpesti mai uno terminale.
Come mappa un DLR HTTP su una ricevuta SMPP deliver_sm?
Portano la stessa informazione. Su SMPP la ricevuta è una PDU deliver_sm marcata in esm_class, con i campi id, stat ed err e una TLV message_state. Il DLR HTTP mappa stat sull'enum di stato, err sul campo error e i timestamp della ricevuta su submitted_at/done_at — così un unico percorso di gestione delle consegne può servire entrambi i transport.
Quali campi mi permettono di riassemblare un SMS in ingresso multipart?
I campi di concatenazione: un reference che lega le parti, l'indice della parte e il conteggio totale. Poiché l'SMS in ingresso obbedisce alle stesse regole di encoding e segmentazione di quello in uscita, un messaggio lungo in ingresso arriva come diversi eventi MO che il consumer ricuce in ordine usando quei campi.
Specifiche della fonte
Gli standard pubblicati su cui si basa questa pagina. Si apre in una nuova scheda.