# Conception d'API de messagerie REST : ressources, méthodes, codes de statut

> Une API de messagerie REST modélise chaque envoi comme une ressource au sein d'une collection de messages. Le client fait un POST du message et, la livraison étant asynchrone, le serveur renvoie 202 Accepted avec un identifiant de message et une URL de statut, puis rapporte le résultat final via un webhook. Les méthodes HTTP et les codes de statut suivent la sémantique de RFC 9110.

- URL canonique: https://www.broadnet.me/fr/reference/rest-messaging-api-design
- Langue: fr
- Dernière mise à jour: 2026-07-19
- Éditeur: BroadNet (https://www.broadnet.me)

Comment se modélise une API de messagerie REST fondée sur les standards : une collection de messages, la sémantique des méthodes HTTP et des codes de statut selon RFC 9110, l'envoi synchrone vs asynchrone (202 Accepted plus un callback de statut), la négociation de contenu et le versionnage par URL ou par en-tête — avec un tableau de compromis REST vs SMPP.

## Le modèle de ressource « messages »

Une API de messagerie REST traite chaque message comme une ressource au sein d'une collection — conventionnellement /messages — adressable par un identifiant attribué par le serveur. C'est le verbe, et non un champ de la charge utile, qui exprime l'intention : POST /messages crée et met en file d'attente un nouveau message sortant ; GET /messages/{id} lit son état courant ; GET /messages liste et filtre. C'est la couche REST qui se superpose aux mêmes connexions opérateurs que SMPP atteint sur le fil, si bien que la ressource que le client fait POST se traduit, en aval, par un submit_sm sur une session SMPP liée. Comme l'identifiant est forgé par le serveur et renvoyé dans la réponse (et généralement repris dans un en-tête Location), le client dispose d'une référence stable pour interroger l'état ou corréler ultérieurement les callbacks de statut.

*Créer un message dans la collection (motif REST générique)*

```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"
}
```

## Les méthodes HTTP et leurs garanties

RFC 9110 définit deux propriétés qui régissent la manière dont un client de messagerie et tout intermédiaire peuvent traiter une requête. Les méthodes sûres (GET, HEAD) sont sans effet de bord, librement mises en cache et rejouables. Les méthodes idempotentes (GET, HEAD, PUT, DELETE) peuvent être répétées avec le même effet net. POST n'est ni sûr ni idempotent, ce qui est précisément le problème pour la soumission de messages : un POST rejoué pourrait provoquer un double envoi. Le remède standard n'est pas de détourner PUT, mais de conserver POST et de le rendre idempotent au moyen d'un en-tête de requête Idempotency-Key, de sorte qu'une soumission rejouée renvoie le résultat d'origine au lieu de créer un second message.

*Méthodes HTTP sur une ressource messages (RFC 9110)*

| Méthode | Sur /messages | Sûr | Idempotent |
|---|---|---|---|
| POST | Créer et mettre en file d'attente un nouveau message | No | Non (le rendre idempotent via Idempotency-Key) |
| GET | Lire un message ou consulter la collection | Oui | Oui |
| HEAD | Vérification des métadonnées / de l'existence | Oui | Oui |
| PUT | Remplacer une ressource modifiable (par exemple, une configuration de webhook) | No | Oui |
| PATCH | Mise à jour partielle d'une ressource mutable | No | No |
| DELETE | Annuler un message en attente | No | Oui |

## Sémantique des codes de statut à l'envoi

Le code de statut que renvoie le serveur encode si le message a été accepté, achevé ou rejeté — et l'envoi de messages est presque toujours asynchrone. RFC 9110 définit 202 Accepted précisément pour ce cas : la requête a été acceptée pour traitement, mais le traitement n'est pas terminé, et la réponse doit indiquer où en suivre l'avancement. Une API de messagerie renvoie donc 202 pour un envoi mis en file d'attente, réservant 201 Created à une ressource entièrement matérialisée et 200 OK à une opération réellement synchrone. Les erreurs client (charge utile mal formée, destination invalide, émetteur inconnu) sont des 4xx et ne doivent pas être rejouées telles quelles ; les échecs serveur et amont sont des 5xx et peuvent être rejoués sans risque avec backoff sous la même Idempotency-Key.

*Sémantique des codes de statut pour la soumission de messages (RFC 9110)*

| Code | Signification | Lorsqu'une API de messagerie l'utilise |
|---|---|---|
| 202 Accepted | Accepté, traitement incomplet | Envoi asynchrone en file d'attente ; l'état final est transmis via un rappel |
| 201 Created | Ressource créée | Création synchrone lorsque la ressource est complète |
| 200 OK | Requête terminée | Lecture d'état synchrone ou opération véritablement immédiate |
| 400 / 422 | Erreur client / non traitable | Corps malformé ou champ invalide — ne pas réessayer à l'identique |
| 401 / 403 | Non authentifié / interdit | Identifiants manquants ou insuffisants |
| 409 Conflict | Conflit d'état | Idempotency-Key réutilisée avec une charge utile différente |
| 429 Too Many Requests | Limite de débit atteinte | Limiter le débit ; respecter Retry-After et appliquer un backoff |
| 5xx | Défaillance du serveur/de la chaîne en amont | Transitoire — réessayer avec backoff sous la même clé |

## Livraison synchrone vs asynchrone

Il existe deux latences distinctes dans une API de messagerie, et les confondre est une erreur de conception. La latence d'API correspond au temps que met l'appel HTTP à accepter le message ; la latence de livraison correspond au temps que met le réseau opérateur à remettre le message au combiné et à retourner un accusé. Comme la seconde est non bornée et échappe au contrôle de l'émetteur, une API bien conçue accuse réception immédiatement (202) avec un état accepté ou en file d'attente, puis livre le résultat terminal de façon asynchrone — un callback de statut de livraison (l'équivalent HTTP d'un accusé de livraison SMPP). Les clients qui ont besoin de l'état final s'abonnent au callback (push) ou interrogent GET /messages/{id} (pull) ; le callback est préférable car il évite la charge d'interrogation et rapporte les changements d'état en quelques secondes.

*Réponse 202 Accepted avec une référence de statut*

```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"
}
```

## Négociation de contenu et versionnage

Client et serveur s'accordent sur la représentation au moyen des en-têtes de négociation de contenu de RFC 9110 : la requête porte Content-Type pour le corps qu'elle envoie et Accept pour ce qu'elle veut en retour, et le serveur répercute le type de média choisi dans le Content-Type de la réponse. La plupart des API de messagerie standardisent sur application/json et utilisent application/problem+json pour les erreurs. Le versionnage d'API suit deux grands motifs. Le versionnage par URL (/v1/messages) est explicite, favorable au cache et trivial à router, au prix d'un incrément grossier de toute la surface. Le versionnage par en-tête ou type de média (Accept: application/vnd.example.v2+json) garde les URL stables et laisse une ressource évoluer indépendamment, au prix d'être invisible dans un navigateur et plus difficile à tester à la main. Quel que soit le choix, les changements additifs (nouveaux champs optionnels) ne devraient jamais imposer un incrément de version ; seuls les changements cassants le devraient.

*Approches de versionnage d'API*

| Approche | Exemple | Compromis |
|---|---|---|
| Chemin d'URL | /v1/messages | Explicite, mis en cache, facile à router ; incréments de version grossiers |
| En-tête personnalisé | Api-Version: 2026-07-19 | URL propres, version épinglée par date ; invisible pour les caches et les navigateurs |
| Type de média accepté | Accept: application/vnd.example.v2+json | Évolution par ressource ; plus difficile à tester manuellement |
| Paramètre de requête | /messages?version=2 | Simple ; brouille la mise en cache et l'identité de la ressource |

## REST vs SMPP : choisir le transport

La couche HTTP/REST et SMPP sont deux transports vers le même réseau de messagerie, et les émetteurs matures utilisent les deux. REST est le bon choix pour l'intégration applicative : il est sans état, compatible avec les pare-feux via du HTTPS ordinaire, facile à sécuriser avec des bearer tokens et simple à instrumenter. SMPP est le bon choix pour un débit soutenu très élevé et le plus faible surcoût par message, car une session binaire de longue durée évite le coût de connexion par message et offre un contrôle fin de la fenêtre. Le tableau oppose les deux pour qu'un intégrateur adapte le transport à la charge de travail ; pour les endpoints REST concrets de BroadNet, voir la référence de l'API pour développeurs, et pour le protocole de fil, voir la vue d'ensemble SMPP.

*REST (HTTP) vs SMPP comme transport de messagerie*

| Propriété | REST / HTTP | SMPP |
|---|---|---|
| Modèle | Requête/réponse sans état via HTTPS | Session binaire persistante avec état (bind) |
| Cadrage | JSON sur HTTP/1.1 ou HTTP/2 | PDU binaires (submit_sm, deliver_sm) |
| Accusé de réception de livraison | Webhook de statut / interrogation GET | reçu deliver_sm sur la même session |
| Débit | Bon ; surcoût par requête | Le plus élevé en continu ; fenêtré, faible surcoût |
| Auth | Jeton Bearer / clé API / OAuth 2.0 | system_id + mot de passe lors de la liaison |
| Contrôle de flux | 429 + en-têtes Retry-After, RateLimit | Taille de la fenêtre + limitation de débit enquire_link |
| Idéal pour | Intégration d'applications, webhooks, volume modéré | Flux A2P massifs à fort volume, de qualité opérateur |

## Questions fréquentes

### Pourquoi une API de messagerie REST renvoie-t-elle 202 plutôt que 200 ou 201 ?

Parce que la livraison des messages est asynchrone. RFC 9110 définit 202 Accepted comme « accepté pour traitement, traitement non terminé », ce qui décrit exactement un envoi en file d'attente. L'API accuse réception immédiatement avec un id de message et une référence de statut, puis rapporte plus tard le résultat de livraison terminal via un callback. 201 et 200 impliquent que l'opération est déjà achevée.

### Comment modéliser une ressource messages ?

Comme une collection : POST /messages crée et met en file d'attente un message, GET /messages/{id} lit son état, et GET /messages liste et filtre. Le serveur forge l'identifiant et le renvoie (souvent dans un en-tête Location) pour que le client dispose d'une référence stable à interroger ou à corréler avec les callbacks de statut.

### POST n'est pas idempotent — comment éviter les doubles envois ?

On conserve POST (il exprime correctement « créer un nouveau message ») et on le rend idempotent au moyen d'un en-tête de requête Idempotency-Key. Une soumission rejouée portant la même clé renvoie le résultat d'origine au lieu de créer un second message. Détourner PUT pour forcer l'idempotence casse le modèle de ressource REST.

### Quelle est la différence entre latence d'API et latence de livraison ?

La latence d'API est le temps que met l'appel HTTP à accepter le message ; la latence de livraison est le temps que met le réseau opérateur à atteindre le combiné et à retourner un accusé. La seconde est non bornée et échappe au contrôle de l'émetteur, d'où l'accusé rapide (202) et le rapport de livraison finale de façon asynchrone.

### Faut-il versionner une API de messagerie dans l'URL ou dans un en-tête ?

Le versionnage par URL (/v1/messages) est explicite, favorable au cache et facile à router, mais fait évoluer toute la surface d'un coup. Le versionnage par en-tête ou type de média garde les URL stables et laisse les ressources évoluer indépendamment, mais reste invisible aux caches et plus difficile à tester à la main. Dans les deux cas, les changements additifs ne devraient jamais forcer un incrément de version.

### Quand utiliser REST plutôt que SMPP ?

Utilisez REST pour l'intégration applicative : HTTPS sans état et compatible pare-feu, authentification par bearer token et instrumentation aisée. Utilisez SMPP pour le débit soutenu le plus élevé et le plus faible surcoût par message, là où une session binaire à fenêtre de longue durée est rentable. Les deux atteignent le même réseau de messagerie ; beaucoup d'émetteurs exploitent REST pour le trafic de contrôle et SMPP pour les flux à haut volume.

## Sources

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

## Voir aussi

- [Vue d'ensemble du protocole SMPP](https://www.broadnet.me/fr/reference/smpp-protocol-overview)
- [Livraison et fiabilité des webhooks](https://www.broadnet.me/fr/reference/webhook-delivery-and-reliability)
- [Idempotence et limitation de débit](https://www.broadnet.me/fr/reference/idempotency-and-rate-limiting)
- [Erreurs d'API et pagination](https://www.broadnet.me/fr/reference/api-errors-and-pagination)
- [Référence de l'API BroadNet](https://www.broadnet.me/fr/developers/api-reference)
