# Progettazione di API di messaggistica REST: risorse, metodi, status code

> Un'API di messaggistica REST modella ogni invio come una risorsa in una collection di messages. Il client esegue un POST del messaggio e, poiché la consegna è asincrona, il server restituisce 202 Accepted con un identificatore del messaggio e un URL di stato, per poi riportare l'esito finale tramite un webhook. I metodi HTTP e gli status code seguono la semantica di RFC 9110.

- URL canonico: https://www.broadnet.me/it/reference/rest-messaging-api-design
- Lingua: it
- Ultimo aggiornamento: 2026-07-19
- Editore: BroadNet (https://www.broadnet.me)

Come si modella un'API di messaggistica REST basata sugli standard: una collection di messages, i metodi HTTP e la semantica degli status code secondo RFC 9110, invio sincrono vs asincrono (202 Accepted più una callback di stato), content negotiation e versioning su URL vs header — con una tabella di confronto REST vs SMPP.

## Il modello a risorse della collection messages

Un'API di messaggistica REST tratta ogni messaggio come una risorsa all'interno di una collection — per convenzione /messages — indirizzabile tramite un identificatore assegnato dal server. È il verbo, non un campo del payload, a esprimere l'intento: POST /messages crea e accoda un nuovo messaggio in uscita; GET /messages/{id} ne legge lo stato corrente; GET /messages elenca e filtra. Questo è il livello REST che si colloca sopra le stesse operator connection che SMPP raggiunge sul filo, per cui la risorsa che il client invia con POST mappa, a valle, su una submit_sm su una sessione SMPP in bind. Poiché l'identificatore è generato dal server e restituito nella risposta (e di solito ripetuto in un header Location), il client dispone di un handle stabile per fare polling o per correlare le callback di stato successive.

*Creare un messaggio nella collection (pattern REST generico)*

```http
POST /v1/messages HTTP/1.1
Host: api.example
Content-Type: application/json
Authorization: Bearer <token>
Idempotency-Key: 8f14e45f-ea7b-4c0f-9b2a-1d2c3e4f5a6b

{
  "to": "+15551234567",
  "from": "BRANDNAME",
  "text": "Your one-time code is 401 928",
  "callback_url": "https://app.example/webhooks/dlr"
}
```

## I metodi HTTP e le loro garanzie

RFC 9110 definisce due proprietà che governano il modo in cui un client di messaggistica e qualsiasi intermediario possono trattare una richiesta. I metodi safe (GET, HEAD) non hanno side effect e sono liberamente cacheabili e ripetibili. I metodi idempotenti (GET, HEAD, PUT, DELETE) possono essere ripetuti con lo stesso effetto netto. POST non è né safe né idempotente, ed è esattamente il problema della submission di un messaggio: un POST ripetuto potrebbe causare un doppio invio. Il rimedio standard non è abusare di PUT, ma mantenere POST e renderlo idempotente con un header di richiesta Idempotency-Key, così che una submission ripetuta restituisca il risultato originale invece di creare un secondo messaggio.

*Metodi HTTP su una risorsa messages (RFC 9110)*

| Metodo | Su /messages | Sicuro | Idempotente |
|---|---|---|---|
| POST | Crea + metti in coda un nuovo messaggio | No | No (rendilo idempotente tramite Idempotency-Key) |
| GET | Leggi un messaggio o elenca la collezione | Sì | Sì |
| HEAD | Metadati / verifica dell'esistenza | Sì | Sì |
| PUT | Sostituire una risorsa modificabile (ad esempio, la configurazione di un webhook) | No | Sì |
| PATCH | Aggiornamento parziale di una risorsa mutabile | No | No |
| DELETE | Annulla un messaggio ancora in coda | No | Sì |

## Semantica degli status code per l'invio

Lo status code restituito dal server codifica se il messaggio è stato accettato, completato o rifiutato — e l'invio di un messaggio è quasi sempre asincrono. RFC 9110 definisce 202 Accepted proprio per questo caso: la richiesta è stata accettata per l'elaborazione, ma l'elaborazione non è completa, e la risposta dovrebbe indicare dove verificarne lo stato. Un'API di messaggistica restituisce quindi 202 per un invio accodato, riservando 201 Created a una risorsa completamente materializzata e 200 OK a un'operazione realmente sincrona. Gli errori del client (payload malformato, destinazione non valida, mittente sconosciuto) sono 4xx e non devono essere ritentati senza modifiche; i guasti del server e a monte sono 5xx e possono essere ritentati in sicurezza con backoff sotto lo stesso Idempotency-Key.

*Semantica degli status code per la submission di un messaggio (RFC 9110)*

| Codice | Significato | Quando un'API di messaggistica lo utilizza |
|---|---|---|
| 202 Accepted | Accettato, elaborazione incompleta | Invio asincrono in coda; lo stato finale viene fornito tramite callback |
| 201 Created | Risorsa creata | Creazione sincrona quando la risorsa è completa |
| 200 OK | Richiesta completata | Lettura sincrona dello stato o operazione realmente immediata |
| 400 / 422 | Errore del client / non elaborabile | Corpo non valido o campo non valido: non riprovare senza modifiche |
| 401 / 403 | Non autenticato / vietato | Credenziali mancanti o insufficienti |
| 409 Conflict | Conflitto di stato | Idempotency-Key riutilizzata con un payload diverso |
| 429 Too Many Requests | Limite di frequenza superato | Throttling; rispetta Retry-After ed esegui il backoff |
| 5xx | Errore del server/a monte | Transitorio — riprova con backoff con la stessa chiave |

## Consegna sincrona vs asincrona

In un'API di messaggistica esistono due latenze distinte, e confonderle è un errore di progettazione. La latenza dell'API è il tempo che la chiamata HTTP impiega per accettare il messaggio; la latenza di consegna è il tempo che la rete dell'operatore impiega per consegnare il messaggio al terminale e restituire una ricevuta. Poiché la seconda è illimitata e fuori dal controllo del mittente, un'API ben progettata conferma immediatamente (202) con uno stato accepted o queued, per poi consegnare l'esito finale in modo asincrono — una callback di stato di consegna (l'analogo HTTP di una delivery receipt SMPP). I client che necessitano dello stato finale si iscrivono alla callback (push) oppure fanno polling su GET /messages/{id} (pull); la callback è da preferire perché evita il carico del polling e segnala i cambi di stato nel giro di secondi.

*Risposta 202 Accepted con un handle di stato*

```http
HTTP/1.1 202 Accepted
Location: /v1/messages/01HZY8Q3M6
Content-Type: application/json

{
  "id": "01HZY8Q3M6",
  "status": "accepted",
  "created_at": "2026-07-19T09:15:22Z",
  "status_url": "/v1/messages/01HZY8Q3M6"
}
```

## Content negotiation e versioning

Client e server concordano la rappresentazione tramite gli header di content negotiation di RFC 9110: la richiesta trasporta Content-Type per il body che invia e Accept per ciò che desidera ricevere, e il server ripete il media type scelto nel Content-Type della risposta. La maggior parte delle API di messaggistica si standardizza su application/json e usa application/problem+json per gli errori. Il versioning delle API ha due pattern principali. Il versioning su URL (/v1/messages) è esplicito, cache-friendly e banale da instradare, al costo di un incremento grossolano dell'intera superficie. Il versioning su header o media type (Accept: application/vnd.example.v2+json) mantiene gli URL stabili e consente a una risorsa di evolvere in modo indipendente, al costo di essere invisibile in un browser e più difficile da testare a mano. Qualunque sia la scelta, le modifiche additive (nuovi campi opzionali) non dovrebbero mai richiedere un incremento di versione; solo le breaking change lo richiedono.

*Approcci al versioning delle API*

| Approccio | Esempio | Compromesso |
|---|---|---|
| Percorso URL | /v1/messages | Esplicito, memorizzabile in cache, facile da instradare; incrementi di versione grossolani |
| Intestazione personalizzata | Api-Version: 2026-07-19 | URL puliti, con data fissa; invisibili a cache e browser |
| Tipo di media accettato | Accept: application/vnd.example.v2+json | Evoluzione per risorsa; più difficile da testare manualmente |
| Parametro di query | /messages?version=2 | Semplice; complica il caching e l'identità della risorsa |

## REST vs SMPP: scegliere il transport

Il livello HTTP/REST e SMPP sono due transport verso la stessa rete di messaggistica, e i mittenti maturi li usano entrambi. REST è la scelta giusta per l'integrazione applicativa: è stateless, firewall-friendly su normale HTTPS, facile da proteggere con bearer token e semplice da strumentare. SMPP è la scelta giusta per un throughput sostenuto molto elevato e per il minimo overhead per messaggio, perché una sessione binaria a lunga durata evita il costo di connessione per messaggio e offre un controllo fine della window. La tabella mette a confronto i due, così che un integratore possa abbinare il transport al workload; per gli endpoint REST concreti di BroadNet vedi il riferimento API per sviluppatori, mentre per il protocollo sul filo vedi la panoramica SMPP.

*REST (HTTP) vs SMPP come transport di messaggistica*

| Proprietà | REST / HTTP | SMPP |
|---|---|---|
| Modello | Richiesta/risposta senza stato tramite HTTPS | Sessione binaria di lunga durata con stato (bind) |
| Framing | JSON su HTTP/1.1 o HTTP/2 | PDU binari (submit_sm, deliver_sm) |
| Ricevuta di consegna | Webhook di stato / polling GET | ricevuta deliver_sm sulla stessa sessione |
| Throughput | Buono; overhead per richiesta | Massimo throughput sostenuto; a finestra, basso overhead |
| Auth | Bearer token / chiave API / OAuth 2.0 | system_id + password al bind |
| Controllo di flusso | 429 + Retry-After, intestazioni RateLimit | Dimensione della finestra + throttling enquire_link |
| Ideale per | Integrazione app, webhook, volume moderato | Flussi massivi A2P ad alto volume di livello carrier |

## Domande frequenti

### Perché un'API di messaggistica REST restituisce 202 invece di 200 o 201?

Perché la consegna del messaggio è asincrona. RFC 9110 definisce 202 Accepted come 'accettato per l'elaborazione, elaborazione non completa', che descrive esattamente un invio accodato. L'API conferma immediatamente con un id del messaggio e un handle di stato, per poi riportare l'esito finale di consegna più tardi tramite una callback. 201 e 200 implicano che l'operazione sia già completa.

### Come si dovrebbe modellare una risorsa messages?

Come una collection: POST /messages crea e accoda un messaggio, GET /messages/{id} ne legge lo stato e GET /messages elenca e filtra. Il server genera l'identificatore e lo restituisce (spesso in un header Location) così che il client disponga di un handle stabile per il polling o per la correlazione con le callback di stato.

### POST non è idempotente — come si evitano i doppi invii?

Si mantiene POST (esprime correttamente 'crea un nuovo messaggio') e lo si rende idempotente con un header di richiesta Idempotency-Key. Una submission ripetuta che trasporta la stessa chiave restituisce il risultato originale invece di creare un secondo messaggio. Abusare di PUT per forzare l'idempotenza infrange il modello a risorse REST.

### Qual è la differenza tra latenza dell'API e latenza di consegna?

La latenza dell'API è il tempo che la chiamata HTTP impiega per accettare il messaggio; la latenza di consegna è il tempo che la rete dell'operatore impiega per raggiungere il terminale e restituire una ricevuta. La seconda è illimitata e fuori dal controllo del mittente, ed è per questo che l'API conferma rapidamente (202) e riporta la consegna finale in modo asincrono.

### Dovrei versionare un'API di messaggistica nell'URL o in un header?

Il versioning su URL (/v1/messages) è esplicito, cache-friendly e facile da instradare, ma incrementa l'intera superficie in una volta sola. Il versioning su header o media type mantiene gli URL stabili e consente alle risorse di evolvere in modo indipendente, ma è invisibile alle cache e più difficile da testare a mano. In entrambi i casi, le modifiche additive non dovrebbero mai forzare un incremento di versione.

### Quando dovrei usare REST rispetto a SMPP?

Usa REST per l'integrazione applicativa: HTTPS stateless e firewall-friendly, autenticazione con bearer token e facile strumentazione. Usa SMPP per il throughput sostenuto più elevato e il minimo overhead per messaggio, dove una sessione binaria a lunga durata con window ripaga. Entrambi raggiungono la stessa rete di messaggistica; molti mittenti usano REST per il traffico di controllo e SMPP per i firehose ad alto volume.

## Fonti

- [IETF RFC 9110 — HTTP Semantics](https://datatracker.ietf.org/doc/html/rfc9110)
- [IETF RFC 9111 — HTTP Caching](https://datatracker.ietf.org/doc/html/rfc9111)

## Correlati

- [Panoramica del protocollo SMPP](https://www.broadnet.me/it/reference/smpp-protocol-overview)
- [Consegna e affidabilità dei webhook](https://www.broadnet.me/it/reference/webhook-delivery-and-reliability)
- [Idempotenza e rate limiting](https://www.broadnet.me/it/reference/idempotency-and-rate-limiting)
- [Errori API e paginazione](https://www.broadnet.me/it/reference/api-errors-and-pagination)
- [Riferimento API BroadNet](https://www.broadnet.me/it/developers/api-reference)
