# Payload dei webhook di stato (DLR) e in ingresso (MO)

> 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.

- URL canonico: https://www.broadnet.me/it/reference/message-status-and-inbound-webhooks
- Lingua: it
- Ultimo aggiornamento: 2026-07-19
- Editore: BroadNet (https://www.broadnet.me)

Gli schemi dei payload per le due callback di messaggistica fondamentali: l'evento di stato di consegna (DLR) con il suo id di messaggio, l'enum di stato, la causa di errore e i timestamp, e l'evento di messaggio in ingresso (MO) — più una tassonomia dei tipi di evento e come un DLR HTTP mappa su una ricevuta SMPP deliver_sm.

## 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.

*Body del webhook di stato di consegna (DLR)*

```json
{
  "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.

*Valori canonici di stato di consegna*

| 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.

*Body del webhook in ingresso (MO)*

```json
{
  "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.

*Tipi comuni di evento di messaggistica*

| 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.

*Mappatura dei campi dalla delivery receipt SMPP al DLR HTTP*

| 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.

## Fonti

- [IETF RFC 9110 — HTTP Semantics](https://datatracker.ietf.org/doc/html/rfc9110)
- [IETF RFC 8288 — Web Linking (Link header)](https://datatracker.ietf.org/doc/html/rfc8288)

## Correlati

- [Consegna e affidabilità dei webhook](https://www.broadnet.me/it/reference/webhook-delivery-and-reliability)
- [Verifica della firma dei webhook](https://www.broadnet.me/it/reference/webhook-signature-verification)
- [Delivery receipt SMPP (DLR)](https://www.broadnet.me/it/reference/smpp-delivery-receipts-dlr)
- [SMPP deliver_sm](https://www.broadnet.me/it/reference/smpp-deliver-sm)
- [Guida ai webhook di BroadNet](https://www.broadnet.me/it/developers/webhooks)
