Adminsys Dev

Comprendre le fonctionnement des API REST : le guide simple

REST n'est pas qu'une URL qui renvoie du JSON : c'est un ensemble de contraintes architecturales précises. Ignorer la moitié d'entre elles produit des API bancales, impossibles à documenter ou à mettre en cache. Découvrez pourquoi ça compte.

Comprendre le fonctionnement des API REST : le guide simple

La question revient à chaque audit technique : « une API REST, c'est juste une URL qui renvoie du JSON, non ? » Techniquement, on peut faire ça. Et c'est précisément ce qui produit la majorité des interfaces bancales que je croise en mission.

Une API REST, ce n'est pas un format de réponse. C'est un ensemble de contraintes architecturales posées par Roy Fielding dans sa thèse de 2000 — et si vous en ignorez la moitié, votre service fonctionnera peut-être, mais il ne sera pas REST. Détail qui n'en est pas un quand votre équipe mobile, votre partenaire logistique et votre back-office doivent tous taper sur le même système sans se marcher dessus.

Points clés à retenir

  • REST est un style d'architecture, pas une technologie ni un protocole. Fielding l'a formalisé comme un ensemble de six contraintes.
  • Sans état (stateless) est la contrainte qu'on casse le plus souvent, et celle qui coûte le plus cher en production.
  • Les verbes HTTP portent une sémantique précise : GET, POST, PUT, PATCH et DELETE ne sont pas interchangeables.
  • Les codes de statut sont un langage : un 200 mal placé vaut un bug caché.
  • REST n'est ni le plus rapide ni le plus expressif — il est le plus lisible par une machine générique, ce qui explique sa longévité.
  • La différence entre API et API REST tient entièrement à ces contraintes.

Comprendre le fonctionnement d'une API REST : ce que tout le monde saute

Un collègue m'a montré une fois son « API REST ». Elle n'avait qu'un seul endpoint : /api. Toutes les opérations passaient par POST, avec un champ action dans le corps JSON pour dire quoi faire. Ça marchait. C'était aussi impossible à documenter, à mettre en cache, et à débugger sans lire 400 lignes de code applicatif.

Ce qu'il lui manquait n'était pas technique. C'était architectural.

Les six contraintes que Fielding a réellement posées

REST ne dit pas « utilisez HTTP ». REST dit : si vous respectez ces six propriétés, vous obtenez certains bénéfices — scalabilité, évolutivité, indépendance des composants. Sinon, vous n'êtes pas REST.

  1. Client-serveur : séparation nette entre l'interface et le stockage. Le client ne sait rien de la base de données.
  2. Sans état : chaque requête contient tout ce qu'il faut pour être comprise. Le serveur ne garde aucune mémoire de la précédente.
  3. Cacheable : une réponse doit pouvoir déclarer si elle est réutilisable, et pendant combien de temps.
  4. Interface uniforme : c'est la contrainte la plus abstraite et la plus mal comprise. Elle impose d'identifier les ressources par des URI, de manipuler ces ressources via une représentation (JSON, XML…), et de rendre les messages auto-descriptifs.
  5. Système en couches : un client ne doit pas savoir s'il parle directement au serveur ou à un proxy, un load balancer, un cache intermédiaire.
  6. Code à la demande (facultatif) : le serveur peut envoyer du code exécutable au client. En pratique, presque personne ne l'implémente.

C'est la contrainte numéro deux qui fait le plus de dégâts. J'ai repris une base de code où l'authentification reposait sur une variable globale côté serveur, modifiée à chaque login. En local, tout allait bien. En production, avec trois instances derrière un répartiteur de charge, les utilisateurs se retrouvaient aléatoirement connectés au compte d'un autre. Deux semaines à chercher avant de comprendre que le problème n'était pas le code, mais l'architecture.

Quelle est la différence entre API et API REST ?

Une API est n'importe quelle interface qui permet à deux programmes de se parler : une bibliothèque logicielle, un système de fichiers, une fonction exposée par un système d'exploitation. La notion est très large. Une API REST est un sous-ensemble précis : une API qui respecte les six contraintes ci-dessus et qui, dans la pratique, s'appuie sur HTTP.

Autrement dit : toute API REST est une API. L'inverse est faux. Une API peut être une bibliothèque Python, un appel RPC, un service SOAP — rien de tout cela n'est REST.

Ce qui se passe vraiment quand vous appelez une API REST

Prenons une requête réelle, sans simplification. Un client veut créer un utilisateur.

Ce qui se passe vraiment quand vous appelez une API REST
  • Méthode : POST
  • URI : https://api.exemple.fr/v1/utilisateurs
  • En-têtes : Content-Type: application/json, Authorization: Bearer <jeton>
  • Corps : {"nom": "Dupont", "email": "[email protected]"}

Le serveur répond avec un code 201 Created, un en-tête Location pointant vers la nouvelle ressource, et un corps contenant l'objet créé, identifiant inclus.

Pourquoi 201 et pas 200 ? Parce qu'un client générique doit pouvoir distinguer « j'ai créé quelque chose » de « voici ce que tu as demandé ». Cette distinction n'a l'air de rien jusqu'au jour où vous branchez un cache ou un orchestrateur qui se base sur ces codes pour décider quoi faire. C'est là que la rigueur paie.

Les verbes HTTP et leur sémantique

Un endpoint mal verbeux est une dette technique qui se paie en support client. Voici la table que j'affiche systématiquement dans les projets que j'accompagne :

Verbe Intention Idempotent ? Exemple d'URI
GET Lire une ressource ou une collection Oui /utilisateurs/42
POST Créer une ressource Non /utilisateurs
PUT Remplacer intégralement une ressource Oui /utilisateurs/42
PATCH Modifier partiellement une ressource Non (en théorie) /utilisateurs/42
DELETE Supprimer une ressource Oui /utilisateurs/42

Un mot sur idempotent, terme qui effraie alors qu'il est simple : une opération est idempotente si la rejouer donne le même résultat que la jouer une fois. Un GET rejoué dix fois ne change rien. Un POST rejoué dix fois crée dix utilisateurs. C'est précisément pourquoi les paiements en ligne utilisent des clés d'idempotence plutôt que des POST nus.

Les codes de statut : un langage, pas un ornement

Le pire que j'aie vu : une API qui renvoyait systématiquement 200, avec {"success": false} dans le corps. Sur le papier, ça fonctionne. En pratique, chaque client devait parser le JSON pour savoir si l'appel avait réussi, ce qui annulait tout l'intérêt du protocole HTTP.

Les codes sont répartis en familles :

  • 2xx : succès. 200 pour un GET classique, 201 pour une création, 204 quand il n'y a rien à renvoyer.
  • 3xx : redirection. Rarement géré manuellement, mais utile en cas de déplacement de ressource.
  • 4xx : erreur du client. 400 pour une requête malformée, 401 pour une authentification manquante, 403 pour un accès refusé, 404 pour une ressource inexistante.
  • 5xx : erreur du serveur. 500 pour un plantage, 503 pour un service indisponible.

La confusion 401/403 est un classique. Un 401 dit « je ne sais pas qui vous êtes ». Un 403 dit « je sais qui vous êtes, et vous n'avez pas le droit ». Confondre les deux fait perdre des heures aux développeurs qui consomment l'interface.

API REST ou SOAP : pourquoi l'un a gagné

SOAP existait avant REST et faisait tout ce que REST fait, en plus verbeux. Enveloppes XML, WSDL, contrats stricts, gestion des transactions intégrée. Sur le papier, c'était rigoureux. En pratique, écrire un client SOAP en JavaScript relevait du parcours du combattant.

API REST ou SOAP : pourquoi l'un a gagné

REST a gagné pour une raison peu romantique : les navigateurs et les outils HTTP existaient déjà. Pas besoin de générer un client, pas besoin de schéma. Une URL, une méthode, des en-têtes. J'ai migré un service interne de SOAP à REST en 2019, principalement pour cette raison : trois jours de travail, et l'équipe front pouvait enfin se débrouiller sans demander au back de générer des stubs.

Cela dit, SOAP garde des avantages : contrats formels, sécurité WS-Security, transactionnalité native. Dans certains secteurs bancaires ou assurantiels, il reste incontournable. REST a gagné sur le web grand public, pas partout.

Et depuis quelques années, GraphQL occupe un créneau différent : un seul endpoint, le client décide de la forme de la réponse. Pratique quand vous avez un front mobile qui n'a besoin que de trois champs sur quarante. Moins pratique quand vous devez mettre en cache côté réseau, parce que le cache HTTP standard ne sait pas traiter une requête POST unique.

Les erreurs que je vois le plus souvent

Mettre des verbes dans les URL

/utilisateurs/42/getCommandes n'est pas REST. L'URI identifie une ressource, pas une action. Si la ressource est une collection de commandes liées à un utilisateur, l'URI correcte est /utilisateurs/42/commandes, et la méthode HTTP dit ce qu'on veut en faire.

Les erreurs que je vois le plus souvent

Je sais, ça paraît pédant. Mais cette convention a un effet concret : elle rend les URI prévisibles. Un développeur qui découvre votre API peut deviner l'URI d'une ressource sans lire la documentation.

Le versioning bâclé

J'ai fait cette erreur il y a longtemps : modifier le format de réponse d'un endpoint existant parce que « personne ne l'utilise ». Trois mois plus tard, une intégration partenaire cassait en production. Depuis, je mets systématiquement un préfixe de version dans l'URI (/v1/, /v2/). Ce n'est pas élégant, mais ça coûte moins cher qu'un incident un samedi matin.

Oublier la pagination

Une collection qui renvoie 50 000 lignes en une seule réponse, ce n'est pas REST — c'est un déni de service auto-infligé. La pagination par curseur (cursor-based) est plus robuste que la pagination par offset, parce qu'elle ne se décale pas quand des éléments sont ajoutés pendant la lecture. Je l'ai apprise à mes dépens sur un flux de logs où des enregistrements disparaissaient entre deux pages.

L'authentification dans une API REST

La contrainte sans état impose une règle simple : pas de session côté serveur. Chaque requête porte son propre justificatif d'identité.

Dans la pratique, deux approches dominent :

  • Clé d'API : un jeton fixe passé dans un en-tête. Simple, adapté aux intégrations serveur-à-serveur. Faible granularité, révocation manuelle.
  • Jeton porteur (Bearer) : typiquement un JWT signé, avec une durée de vie courte et un mécanisme de rafraîchissement. Plus souple, mais impose de gérer correctement l'expiration côté client.

Un piège que je vois régulièrement : stocker un jeton longue durée dans le localStorage d'une application web. Une seule faille XSS et le jeton est exfiltrable. Pour du navigateur, le cookie HttpOnly reste plus sûr, à condition d'ajouter une protection CSRF.

Sur l'authentification comme ailleurs, la règle est la même : le serveur ne doit rien retenir entre deux requêtes. Tout ce qui doit persister doit être signé et renvoyé au client.

Un exemple concret, de bout en bout

Imaginons un service de gestion de tâches. Trois opérations :

  1. Lister les tâches : GET /v1/taches → réponse 200 avec un tableau d'objets.
  2. Créer une tâche : POST /v1/taches avec {"titre": "Relire la doc"} → réponse 201 avec l'objet créé et son identifiant.
  3. Marquer comme terminée : PATCH /v1/taches/17 avec {"terminee": true} → réponse 200 avec la ressource à jour.

Rien de spectaculaire. Mais chaque élément porte du sens : le verbe dit l'intention, l'URI identifie la ressource, le code dit ce qui s'est passé. Un client qui ne connaît rien à votre système peut interagir avec lui s'il comprend HTTP.

C'est exactement le point. REST n'est pas une mode. C'est une contrainte de lisibilité — pour les machines, et pour les humains qui reprendront votre code dans deux ans.

Faut-il vraiment respecter les six contraintes à la lettre ?

Non, et peu d'API le font réellement. Le code à la demande n'est presque jamais implémenté, et beaucoup d'interfaces dites REST gardent un état côté serveur (sessions, verrous). Ce qui compte, c'est de savoir quelles contraintes vous relâchez et pourquoi. Une API « presque REST » documentée vaut mieux qu'une API prétendument REST dont personne ne comprend le comportement.

La prochaine fois qu'on vous présentera une « API REST », posez une seule question : que se passe-t-il si je rejoue exactement la même requête deux fois de suite ? Si la réponse est floue, vous avez votre diagnostic.

Marion Rossignol

Marion Rossignol

Marion Rossignol est une développeuse et architecte reconnue pour son expertise en JavaScript moderne, en architecture web et en pratiques DevOps et CI/CD. Elle accompagne des équipes techniques dans la conception de solutions robustes et évolutives, en mettant l'accent sur l'automatisation et la qualité logicielle. Passionnée par la transmission, elle partage régulièrement ses connaissances à travers des articles et des conférences.

Voir tous les articles →

Articles similaires