Delivery Report
Un delivery report (DLR) è la conferma asincrona e per-messaggio che ti dice l'esito finale di un SMS — se è stato consegnato al telefono, rifiutato dall'operatore, scaduto o fallito. Senza DLR, tutto ciò che sai è che la piattaforma ha accettato il messaggio per l'invio.
Come ricevere i DLR
I DLR vengono pushati su un webhook HTTPS che gestisci tu non appena l'operatore comunica lo stato finale. Abilitali impostando enableDelivery: true sulla request di invio e configurando l'URL del webhook nel portale wholesale sotto Settings → Webhooks.
La latenza end-to-end tipica dalla submission a una callback DELIVERED è di pochi secondi.
Payload del Webhook
I DLR vengono inviati via HTTP POST all'URL che configuri. Il payload identifica il messaggio e ne fornisce il nuovo stato.
{
"id": "msg_abc123",
"globalId": "req_1234567890",
"destination": "+393351234567",
"status": "DELIVERED",
"statusCode": 0,
"submitDate": "2026-05-14T10:23:11.000+0200",
"doneDate": "2026-05-14T10:23:14.221+0200",
"operator": "TIM",
"parts": 1
}
Reference dei campi
| Campo | Significato |
|---|---|
id | Identificativo per messaggio restituito dalla send response |
globalId | ID di correlazione della submission originale |
destination | Numero del destinatario |
status | Stato finale (vedi tabella sotto) |
statusCode | Codice numerico corrispondente allo stato |
submitDate | Quando la piattaforma ha accettato il messaggio |
doneDate | Quando è stato raggiunto lo stato finale |
operator | Operatore mobile destinatario (best effort) |
parts | Numero di parti SMS fatturate |
Codici di Stato DLR
| Stato | Codice | Significato | Fatturabile? |
|---|---|---|---|
DELIVERED | 0 | Il telefono ha confermato la ricezione | Sì |
BUFFERED | 1 | In coda sull'operatore, non ancora consegnato | Sì |
EXPIRED | 2 | Periodo di validità scaduto prima della consegna | Sì |
REJECTED | 3 | L'operatore ha rifiutato il messaggio | No |
UNDELIVERABLE | 4 | Numero errato, blacklisted, opt-out | No |
UNKNOWN | 5 | Nessuno stato finale ricevuto nella finestra di validità | Dipende |
FAILED | 6 | Errore interno prima della submission all'operatore | No |
Le regole di fatturazione possono variare per operatore; il portale wholesale è la fonte di verità per il tuo account.
Requisiti del Webhook
- Solo HTTPS — HTTP in chiaro non è accettato.
- Rispondi con
200 OKentro 10 secondi — Altrimenti il DLR viene rilanciato. - Idempotenza — Lo stesso DLR può essere rilanciato in caso di errori transienti. Usa
idcome chiave di deduplica. - Ordine non garantito — Un evento
BUFFEREDpuò arrivare dopoDELIVERED. UsadoneDateper riconciliare. - Retry policy — Le consegne fallite sono ritentate con back-off esponenziale fino a 24 ore, poi scartate.
Esempio di handler webhook
- Python (Flask)
- Node.js (Express)
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.post("/webhook/dlr")
def dlr():
payload = request.get_json(force=True)
msg_id = payload["id"]
status = payload["status"]
# Persisti; il processing downstream deve essere asincrono.
save_dlr(msg_id, status, payload)
return jsonify({"ok": True}), 200
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook/dlr', (req, res) => {
const { id, status } = req.body;
saveDlr(id, status, req.body); // coda / DB
res.status(200).json({ ok: true });
});
app.listen(8080);
Prossimi passi
- Invio SMS — Assicurati di avere
enableDelivery: truesulle send. - SMS in ingresso — Ricevi risposte sui numeri noleggiati.
- Gestione errori — Mappa codici di stato ad azioni user-facing.