Une question revient dans presque toutes les revues de code que je fais avec des juniors : « pourquoi mon endpoint renvoie 200 alors qu'il vient de planter ? ». Le type a écrit une API, elle répond, Postman affiche du vert, et pourtant tout est faux. Le problème n'est presque jamais technique. Il est conceptuel : il croit écrire une API REST alors qu'il écrit un tunnel HTTP qui transporte du JSON.
Comprendre les API REST, ce n'est pas apprendre une liste de verbes. C'est accepter une discipline héritée d'une thèse soutenue en 2000 par Roy Fielding, l'un des co-auteurs de la spécification HTTP. Cette discipline s'appelle REST : Representational State Transfer. Et la partie que tout le monde saute, c'est le mot du milieu.
Points clés à retenir
- REST est un style architectural, pas une technologie ni une norme imposée.
- Les six contraintes de Fielding, dont l'absence d'état, sont ce qui distingue une vraie API REST d'un simple service HTTP.
- Les verbes HTTP portent une sémantique précise : GET lit, POST crée, PUT remplace, PATCH modifie, DELETE supprime.
- Les codes de statut font partie du contrat. Un 200 sur une erreur est un bug de conception.
- REST n'est qu'une option : SOAP, GraphQL et gRPC répondent à d'autres besoins.
API REST définition : ce que le mot veut vraiment dire
Un acronyme, d'abord, parce qu'on me le demande souvent. API signifie Application Programming Interface : une interface qui permet à deux logiciels de se parler sans que l'un ait besoin de connaître l'intérieur de l'autre. Quant à REST, il désigne donc un ensemble de règles sur la manière dont ces échanges doivent être structurés.
La nuance qui change tout, c'est celle-ci : une API REST n'est pas une API qui utilise HTTP. C'est une API dont l'architecture respecte les contraintes de REST. On trouve des services qui parlent HTTP, renvoient du JSON, et ne sont pas REST du tout.
Les six contraintes, sans lesquelles rien ne tient
Avouons-le, personne ne les lit. Pourtant elles expliquent 90 % des décisions de design qui suivent.
- Client-serveur : les deux camps évoluent séparément. Le front peut être réécrit en React sans que le back change une ligne.
- Sans état (stateless) : chaque requête contient tout ce qu'il faut pour être comprise. Le serveur ne se souvient de rien entre deux appels. C'est la contrainte la plus violée, et de loin.
- Cacheable : les réponses doivent indiquer si elles peuvent être mises en cache, et pendant combien de temps.
- Interface uniforme : les ressources sont identifiées par des URI, manipulées via des représentations, et les messages portent assez d'information pour agir.
- Système en couches : un client ne sait pas s'il parle directement au serveur ou à un proxy, un load balancer, un CDN.
- Code à la demande : facultative celle-là, et rarement implémentée. On peut la mentionner et passer à autre chose.
Le « sans état » mérite qu'on s'y attarde. J'ai vu une équipe stocker le panier d'un utilisateur dans une variable globale côté serveur. Ça fonctionnait à deux instances. À trois, les clients voyaient leur panier disparaître aléatoirement selon l'instance touchée par le load balancer. Deux jours de debug pour une erreur de conception.
Fonctionnement d'une API REST, étape par étape
Reprenons depuis le début. Un client envoie une requête HTTP à une URL. Cette URL identifie une ressource — pas une action. Le serveur renvoie une représentation de cette ressource, presque toujours en JSON aujourd'hui.
La distinction ressource/action est le point que je vois le plus souvent raté. Une URI correcte ressemble à /utilisateurs/42/commandes. Une URI incorrecte ressemble à /getCommandesUtilisateur?id=42. La première décrit une chose. La seconde décrit un verbe.
Les verbes HTTP et leur sémantique
Chaque méthode porte un contrat implicite. Le respecter, c'est permettre à des intermédiaires — navigateurs, proxys, caches — de faire leur travail sans configuration supplémentaire.
- GET : lire une ressource. Ne doit jamais modifier l'état du serveur.
- POST : créer une ressource ou déclencher un traitement. Non idempotent.
- PUT : remplacer intégralement une ressource. Idempotent.
- PATCH : modifier partiellement. Attention, tout le monde l'implémente n'importe comment.
- DELETE : supprimer. Idempotent — appeler deux fois donne le même résultat final.
Idempotent signifie qu'une même requête répétée produit le même état final côté serveur. Ce n'est pas un détail académique : c'est ce qui autorise un client à réessayer automatiquement après un timeout réseau sans risquer de créer trois commandes.
Les codes de statut, ce contrat qu'on ignore
Le code HTTP n'est pas décoratif. Il dit au client quoi faire ensuite, sans qu'il ait à lire le corps de la réponse.
| Code | Signification | Usage typique |
|---|---|---|
| 200 | OK | GET, PUT, PATCH réussis |
| 201 | Created | POST qui crée une ressource |
| 204 | No Content | DELETE réussi, pas de corps |
| 400 | Bad Request | Données invalides côté client |
| 401 | Unauthorized | Authentification manquante ou invalide |
| 403 | Forbidden | Authentifié mais pas autorisé |
| 404 | Not Found | Ressource inexistante |
| 500 | Server Error | Bug côté serveur, pas côté client |
Mon conseil : n'utilisez jamais 200 avec un corps qui contient une erreur. Ça casse tous les clients génériques, tous les monitoring, tous les retry automatiques. J'ai déjà dû reprendre l'intégralité d'un SDK interne à cause de ça. Le fournisseur renvoyait 200 systématiquement, avec un champ error dans le JSON. Nos alertes ne se déclenchaient jamais.
Différence entre API et API REST : la confusion la plus fréquente
Une API, au sens large, c'est n'importe quelle interface qui expose des fonctionnalités à un autre programme. Une bibliothèque Python a une API. Un système d'exploitation a une API. Une API REST est un cas particulier : une API exposée sur un réseau, qui suit les contraintes REST et dont les échanges passent par HTTP.
Spoiler : toutes les API web ne sont pas REST. Une API qui expose /api/getUser, /api/createUser, /api/deleteUser est une API HTTP, souvent appelée RPC. Elle fonctionne parfaitement. Elle n'est simplement pas REST.
SOAP, GraphQL, gRPC : REST n'est pas la seule voie
SOAP existe depuis bien avant REST, il utilise XML, et il impose un contrat strict via WSDL. C'est verbeux, mais c'est ce que demandent encore certains secteurs réglementés — banque, assurance, santé. Ne partez pas en croisade contre SOAP si vous n'avez jamais eu à intégrer un système d'assurance. Personnellement, je peste à chaque intégration, mais je comprends pourquoi ça tient depuis vingt ans.
GraphQL résout un problème que REST gère mal : le sur-fetching. Si votre application mobile a besoin de cinq ressources liées, REST vous force souvent à cinq appels, ou à une route custom qui devient ingérable. GraphQL laisse le client composer sa requête. Le revers ? Le cache HTTP devient beaucoup plus délicat à mettre en place.
gRPC, enfin, parle Protocol Buffers et binaire. C'est le plus performant des quatre, mais son usage principal reste la communication entre services internes. Dans un navigateur, sans proxy, ça coince encore.
Aucun de ces standards n'est meilleur dans l'absolu. Le choix dépend de qui consomme l'API, de la latence acceptable, et de savoir si vous avez besoin d'un cache HTTP partagé.
Un exemple d'API REST concret : la boutique en ligne
Prenons une boutique qui vend des t-shirts. Voici comment je modéliserais ses ressources.
GET /produits— liste paginée. Renvoie 200.GET /produits/17— un produit précis. 200 ou 404.POST /commandes— crée une commande. Renvoie 201 avec l'URL de la ressource dans l'en-têteLocation.PATCH /commandes/2042— met à jour l'adresse de livraison. Renvoie 200 avec l'objet modifié.DELETE /commandes/2042— annule la commande. Renvoie 204.
Remarquez que les URI sont au pluriel et désignent toujours des collections ou des éléments de collection. C'est une convention, pas une règle. Mais c'est la convention majoritaire, et s'en écarter sans raison coûte cher en lisibilité pour l'équipe suivante.
Les erreurs que j'ai réellement commises
La première : j'ai mis les identifiants de session dans l'URL. Catastrophique — ils se retrouvent dans les logs du serveur, dans les historiques de navigateur, dans les caches intermédiaires. Aujourd'hui, l'authentification passe par un en-tête Authorization, point.
La deuxième : j'ai conçu des endpoints qui acceptaient 14 paramètres optionnels dans la query string. L'équipe front a fini par écrire un fichier de mapping de 300 lignes pour savoir quelle combinaison déclenchait quoi. Refactoriser a pris trois semaines.
La troisième, plus récente : j'ai oublié de versionner. Premier changement cassant en production, 4 h du matin, tous les clients mobiles plantés. Depuis, toutes mes API démarrent avec un /v1/ dans le chemin, même si je pense ne jamais en avoir besoin. Je me suis déjà trompé une fois.
Erreur n°4 : brûler l'étape de conception
Le pattern que je vois le plus souvent chez les développeurs qui découvrent REST : ouvrir l'IDE et commencer à coder des routes. Sans schéma, sans convention de nommage, sans décider qui gère l'authentification ni où placer la pagination.
Deux semaines plus tard, l'API a trente endpoints, dont certains renvoient des tableaux, d'autres des objets enveloppés, d'autres des chaînes brutes. Le client front doit écrire trois parseurs différents.
Prenez une heure. Dessinez les ressources sur une feuille. Choisissez vos conventions : pluriel, casse kebab ou snake, format de pagination, format d'erreur unique. Cette heure vaut trois semaines de refactor.
Quelques conventions que j'applique systématiquement
- URI en minuscules avec des tirets :
/lignes-commandes - JSON en camelCase — c'est le plus lisible depuis du JavaScript côté client
- Erreurs sous une forme unique :
{"code": "...", "message": "...", "details": []} - Pagination par curseur sur les collections qui grossissent, par offset sur les petites
- Un
/healthqui renvoie 200 uniquement quand la base répond
Rien de tout ça n'est dans REST au sens strict. C'est ce qu'on appelle souvent le pragmatisme REST : respecter l'esprit de Fielding tout en adaptant les détails à son équipe. Fielding lui-même a publié des critiques assez dures contre les API qui se disent REST sans en respecter les contraintes.
Et c'est probablement là que se joue la vraie compétence. Pas dans la connaissance des verbes HTTP, qu'on trouve partout. Dans la capacité à décider, pour un projet donné, quelles règles suivre à la lettre et lesquelles assouplir — en sachant précisément ce qu'on sacrifie.
La prochaine fois que vous ouvrez un éditeur pour créer un endpoint, posez-vous une question simple : est-ce que je modélise une ressource ou une action ? Si la réponse est « une action », c'est peut-être du RPC. Et ce n'est pas un gros mot.