Un mail, à 18h47, un vendredi. Le genre de mail qu'on ouvre en soupirant.
Une consœur me demande de l'aide : sa nouvelle application mobile n'arrive pas à récupérer les commandes de son site e-commerce. Le prestataire lui a livré une "API REST" qui renvoie du HTML. Du HTML, encodé en JSON, lui-même imbriqué dans un champ nommé data à l'intérieur d'un autre champ data. Je vous passe les détails. Le problème n'était pas technique. Il était conceptuel. Personne n'avait pris le temps de comprendre ce qui fait qu'une API REST est REST.
Et c'est le piège dans lequel tout le monde tombe. On croit qu'ajouter /api devant une URL suffit. Spoiler : non.
Points clés à retenir
- REST n'est pas un protocole, c'est un style architectural décrit par Roy Fielding en 2000 dans sa thèse de doctorat.
- Une URL désigne une ressource, pas une action. Les verbes HTTP font le travail.
- Un corps d'erreur structuré vaut mieux qu'un code 500 muet.
- Le versioning et la pagination se décident avant la mise en production, jamais après.
- Une API sans authentification solide est une porte ouverte, même si elle fonctionne parfaitement.
API REST : ce que ça signifie vraiment (et ce que la plupart des docus n'osent pas dire)
Commençons par le mot que je vois mal traduit partout : API REST. L'acronyme signifie Representational State Transfer. Derrière ce nom un peu jargonnant se cache une idée simple, exprimée par Roy Fielding dans sa thèse : tout ce que votre service expose est une ressource, chaque ressource a un identifiant stable (une URL), et les interactions suivent une poignée de règles uniformes.
Ce qui déroute les développeurs qui débarquent du SOAP ou des RPC, c'est justement qu'on arrête de penser en actions pour penser en objets.
Comment fonctionne une API REST, concrètement ?
Un client envoie une requête HTTP à une URL qui représente une ressource. Le serveur renvoie une représentation de cette ressource, le plus souvent en JSON. Le client ne connaît pas l'état interne du serveur, et réciproquement. C'est ce qu'on appelle l'absence d'état : chaque requête porte tout ce qu'il faut pour être interprétée.
Prenons un exemple. Vous voulez les commandes d'un client.
GET /customers/42/orders?page=1&limit=20
Le serveur répond avec une liste de commandes, et un en-tête de pagination qui indique la suite. Aucun verbe "getOrders" dans l'URL. Aucune session à maintenir côté serveur. L'URL décrit quoi, le verbe HTTP décrit comment.
Un exemple qui m'a servi de leçon
Sur un projet interne, on avait construit une API avec des routes du genre /getProductById, /createOrder, /updateStock. Tout fonctionnait. Puis on a voulu brancher un cache HTTP. Impossible : aucune route ne pouvait être mise en cache, parce qu'elles ressemblaient à des fonctions, pas à des ressources. Trois semaines de refonte. Je ne referai pas l'erreur.
Conventions de nommage : la partie que tout le monde sous-estime
La convention de nommage d'une API REST n'est pas un détail cosmétique. C'est ce qui rend votre API prévisible. Un développeur qui découvre votre documentation doit pouvoir deviner le nom d'une route sans la lire.
- Ressources au pluriel, en minuscules, séparées par des tirets :
/order-items - Pas de verbe dans l'URL. Jamais
/getUser. On utiliseGET /users/12. - Relations imbriquées uniquement quand la ressource n'a pas de sens seule :
/orders/12/lines, mais/products/8reste à la racine. - Filtres, tri et pagination en query string :
?status=shipped&sort=-created_at - Versionnage explicite dans l'URL ou via l'en-tête
Accept. Je préfère l'URL, parce qu'elle est visible dans les logs.
Là où beaucoup se trompent, c'est sur le choix du verbe HTTP. Un POST qui modifie une ressource existante, c'est une faute. Un GET qui a des effets de bord, c'est un désastre qui finira par frapper votre cache ou votre crawler.
| Verbe | Usage | Idempotent ? |
|---|---|---|
| GET | Lire une ressource | Oui |
| POST | Créer une ressource | Non |
| PUT | Remplacer intégralement | Oui |
| PATCH | Modifier partiellement | Non (en général) |
| DELETE | Supprimer | Oui |
Ce tableau semble élémentaire. Pourtant j'ai vu des équipes expérimentées l'ignorer, souvent par habitude d'un framework qui pousse à tout faire en POST.
Erreurs, sécurité, performance : les trois angles morts
Voici ce que je ne trouve presque jamais dans les cours d'API REST. Trois sujets qu'on traite comme des détails alors qu'ils conditionnent la survie d'une API en production.
Structurer les erreurs, pas seulement les coder
Renvoyer un 400 avec un corps vide n'aide personne. Un bon corps d'erreur contient :
- un code lisible par une machine et stable dans le temps ;
- un message destiné au développeur, pas à l'utilisateur final ;
- un identifiant de corrélation (
request-id) qui permet de retrouver la trace dans les logs ; - éventuellement, la liste des champs invalides quand il s'agit d'une erreur de validation.
La RFC 7807 propose un format standardisé pour ça, appelé Problem Details. Je l'utilise systématiquement depuis quelques années. Le gain n'est pas visible au premier jour. Il devient énorme le jour où un partenaire vous appelle en disant "on a une erreur 422" et que vous pouvez retrouver la requête en dix secondes grâce au request-id.
Sécuriser : authentification, autorisation, chiffrement
Une API REST exposée sur internet sans authentification est une anomalie. Selon vos cas d'usage, vous opterez pour :
- des clés d'API pour un usage interne simple,
- des jetons JWT signés pour des clients tiers,
- OAuth 2.0 dès qu'il faut une délégation d'autorisation entre plusieurs acteurs.
Ces mécanismes ne remplacent pas HTTPS, qui reste non négociable. J'ai vu un projet interne fonctionner en HTTP sur un réseau "de confiance". Six mois plus tard, un nouvel outil de monitoring captait les jetons en clair dans les logs. Ce n'est pas un scénario théorique.
Attention aussi à ne jamais mettre de secret dans l'URL. Les URLs finissent dans les historiques de navigateur, les proxys, les journaux d'accès. Un token dans une query string est un token déjà fuité.
Ce qui se passe quand l'API grossit
Trois mécanismes sauvent une API qui commence à être sollicitée sérieusement :
- Le cache HTTP via
ETagetCache-Control, qui évite de reconstruire une réponse identique des centaines de fois. - Le rate limiting, qui empêche un client mal écrit (ou mal intentionné) de saturer votre service. On renvoie
429avec un en-têteRetry-After, pas une erreur floue. - La pagination systématique des collections. Une route
/ordersqui renvoie toutes les commandes finira par faire tomber votre serveur le jour où un client dépasse les 50 000 enregistrements.
Et un détail que j'ai appris à la dure : sur la gestion des timeouts et des retries, la règle d'or est qu'un GET, PUT ou DELETE peut être rejoué sans risque (ils sont idempotents). Un POST, non. Sans identifiant de requête côté client, un retry sur un POST peut créer deux commandes identiques. Ça arrive plus souvent qu'on ne le pense.
Documentation, versionnage, cycle de vie
Une API sans documentation à jour est une API morte à moyen terme. Et "à jour" est le mot clé. Le fichier PDF exporté il y a huit mois ne vaut rien.
La bonne pratique, si vous me demandez mon avis tranché : une spécification OpenAPI (anciennement Swagger) qui génère automatiquement la documentation, les exemples de requête et parfois même des SDK clients. Elle vit dans le dépôt de code, elle évolue avec les routes, et elle devient la source de vérité.
Sur le versionnage, deux écoles s'affrontent. Je vais trancher : version dans l'URL. C'est visible, c'est log dans les journaux, c'est testable à la main dans un navigateur. Le versionnage par en-tête Accept est plus élégant sur le papier, moins lisible au quotidien.
Et surtout : annoncez vos dépréciations. Un en-tête Deprecation et un Sunset qui indique la date de fin de support. Rien n'est plus pénible, pour un partenaire, que d'apprendre la suppression d'une route le jour où elle disparaît.
API REST ou SOAP : est-ce encore un vrai débat ?
On me pose souvent la question. Franchement, pour tout nouveau projet en 2026, REST gagne la majorité des cas. JSON est plus léger, les outils sont partout, les navigateurs parlent HTTP nativement.
Mais SOAP garde des niches légitimes : les systèmes bancaires historiques, certains échanges inter-entreprises avec contrats stricts, ou les environnements qui dépendent de WS-Security. Migrer un système SOAP vieillissant vers REST n'a de sens que si vous avez une vraie raison. "C'est moderne" n'en est pas une.
Et REST n'est pas toujours le bon choix non plus. Si vos clients ont des besoins de données très variés, GraphQL peut être plus adapté. Si vous voulez une communication binaire performante entre microservices, gRPC est souvent meilleur. REST est un défaut raisonnable, pas une religion.
Ce qui distingue une API REST qu'on aime d'une API REST qu'on subit
Revenons à cette consœur et son prestataire. Ce qui manquait, ce n'était ni la technologie, ni l'outillage. C'était une poignée de décisions prises au bon moment : nommer les choses correctement, documenter avant de coder, structurer les erreurs, prévoir la montée en charge, sécuriser dès la première route exposée.
Une API REST réussie, ce n'est pas une API qui répond. C'est une API qu'un développeur que vous n'avez jamais rencontré peut appeler sans vous poser de question. Si vous devez expliquer votre propre API à voix haute pour qu'on la comprenne, il y a un problème.
La prochaine fois que vous ouvrez votre éditeur pour ajouter une route, posez-vous une seule question : est-ce que je décris une ressource, ou est-ce que je cache un verbe ? La réponse oriente tout le reste.