Public cible
Débutants, étudiants et professionnels qui souhaitent acquérir une pratique structurée dans ce domaine.
Construire une API qui tient dans la durée : un contrat écrit avant le code, une spécification exécutée comme test, le contrôle d'accès par objet, les limites de débit, l'idempotence, et les règles de versionnement qui évitent de casser les clients.
Débutants, étudiants et professionnels qui souhaitent acquérir une pratique structurée dans ce domaine.
Comprendre les notions essentielles et les appliquer dans un projet vérifiable.
Aucune connaissance préalable n’est strictement obligatoire ; les prérequis détaillés sont précisés dans les ateliers.
Tous niveaux
La validation repose sur les évaluations actives et les livrables pratiques du cours.
Un ordinateur, un navigateur et les outils indiqués dans le premier atelier sont suffisants pour commencer.
Écrire la spécification OpenAPI puis un test de contrat qui l'exécute.
Obligatoire ConsulterAuditer une API pour le contrôle d'accès, les limites et l'idempotence.
Obligatoire ConsulterÉcrire la spécification OpenAPI puis un test de contrat qui l'exécute.
Obligatoire ConsulterAuditer une API pour le contrôle d'accès, les limites et l'idempotence.
Obligatoire ConsulterUne API est un contrat commercial autant que technique. Toute forme de compatibilité promise devient une dette que l'on portera.
Un contrat qui omet ces cinq points produit des surprises, et chaque surprise se négocie au pire moment : à la mise en production d'un client.
Le format d'erreur est la partie la plus souvent improvisée, et la plus coûteuse. Il faut un format unique, valable pour toutes les routes, avec au minimum : un code stable que le client peut tester, un message destiné à être lu par un humain, et des champs de détail par valeur invalide. Le code d'erreur ne doit jamais être une phrase traduite : les clients testent sur le code, et un message d'erreur destiné aux utilisateurs finira par changer de formulation, ce qui cassera le client.
Une spécification en OpenAPI décrit les routes, les paramètres, les types et les réponses dans un document structuré. Trois bénéfices concrets, dans cet ordre : un test qui vérifie que l'implémentation respecte la spécification, une documentation générée donc jamais périmée, et la possibilité d'un client généré automatiquement. Le dernier est le moins intéressant en soi — un client généré reste un client qu'on écrit.
La manière dont on nomme et découpe les ressources détermine l'evolution future de l'API. Une mauvaise structure de ressources ne se corrige pas sans casser les clients.
Une API qui expose POST /creerClient,
POST /modifierClient,
POST /supprimerClient n'expose pas des
ressources : elle expose un RPC sur HTTP. Elle
fonctionnera, et elle empêchera toute évolution, parce
que chaque nouvelle opération imposera une nouvelle
route ad hoc.
La forme correcte expose des ressources — ici des clients — et laisse la méthode HTTP exprimer l'action. Ce changement n'est pas cosmétique : il est la différence entre une API qui évolue et une API qui s'épuise.
Ce sont des principes de conception, pas une checklist à cocher ligne par ligne. Une API peut tranquillement en violer trois et rester parfaitement exploitable ; l'erreur est de les violer par accident, sans savoir pourquoi.
Les codes de statut sont la partie du contrat la plus sous-estimée. C'est pourtant le seul canal qui dise au client ce qu'il doit faire, sans qu'il ait à deviner.
| Code | Situation | Ce que fait un bon client |
|---|---|---|
| 400 | demande invalide | corriger, ne pas réessayer à l'identique |
| 401 | non authentifié | obtenir un jeton, réessayer une fois |
| 403 | authentifié mais interdit | ne pas réessayer, avertir l'utilisateur |
| 404 | ressource absente | ne pas réessayer |
| 409 | conflit d'état | relire l'état, résoudre, réessayer |
| 429 | débit dépassé | attendre et réessayer, en respectant l'en-tête de délai |
| 500 | erreur serveur | réessayer avec temporisation croissante |
401 et 403 se confondent très souvent, et le client ne peut pas les traiter de la même façon. Un 401 doit déclencher une procédure de renouvellement de jeton ; un 403 ne le doit pas, et réessayer indéfiniment sur un 403 est exactement le comportement d'un client mal écrit. Le même raisonnement vaut pour 404 et 409.
Répondre 200 avec un corps
{"erreur": "non autorisé"} est
l'erreur la plus répandue des API internes. Elle rend
l'API inexploitable pour tout client qui s'appuie sur
le code — c'est-à-dire tous les clients générés, les
bibliothèques de monitoring, les passerelles, et
pour finir les humains.
L'API a une surface d'attaque que le site n'a pas : elle est interrogeable par quiconque connaît son URL. Les contrôles du navigateur ne la protègent pas.
Le défaut le plus répandu des API n'est pas
l'absence d'authentification, c'est
l'absence de vérification de propriété. Un
utilisateur authentifié demande
/factures/1042 : le serveur vérifie qu'il
est connecté, et lui renvoie la facture. Elle appartient
à quelqu'un d'autre.
Ce défaut figure en tête du Top 10 de la sécurité des API de l'OWASP, et il n'est détectable ni par un test de charge ni par une revue superficielle : il faut le chercher explicitement, en tentant d'accéder aux objets d'un autre utilisateur. La parade est une règle unique : toute requête qui porte un identifiant d'objet vérifie que l'appelant a le droit sur cet objet. Une vérification faite sur l'identifiant de la requête ne suffit pas.
Le troisième défaut est la validation des entrées : une API reçoit des données d'une source externe, et les valide côté serveur. La validation du côté client n'est pas une validation, c'est un confort d'affichage.
Une API publique sans limite est une API qui tombera, et son indisponibilité sera attribuée à la conception du service, pas à l'appelant.
Sur une liste qui reçoit des écritures pendant que l'utilisateur parcourt les pages, la pagination par numéro produit un défaut silencieux : un élément inséré entre deux lectures décale toutes les pages suivantes, et l'utilisateur voit un enregistrement deux fois, ou n'en voit aucun. Le curseur n'a pas ce problème, parce qu'il décrit une position stable dans le flux et non un décalage.
Chaque limite doit être choisie, pas laissée par défaut. Le critère n'est pas « quelle valeur semble raisonnable » mais « quelle valeur l'infrastructure supporte-t-elle, et que se passe-t-il quand on la dépasse ? ». Une limite trop basse rend l'API inutilisable ; une limite trop haute la rend indisponible pour tous. Un seuil doit être un compromis assumé et documenté, pas une valeur posée au hasard pour faire taire une alerte.
Réseaux non fiables signifie qu'une requête peut arriver au serveur et que la réponse peut se perdre. L'API doit alors pouvoir être rejouée sans créer d'effet de bord.
La méthode GET doit être idempotente : la répéter ne doit pas changer l'état du serveur. C'est aussi ce qui autorise le cache et la pré-chargement. En revanche, PUT et DELETE sont eux aussi idempotents par convention : répéter une suppression, c'est supprimer quelque chose qui n'existe déjà pas, ce qui doit réussir sans effet supplémentaire. POST n'est pas idempotent : c'est la seule méthode où répéter pose problème.
La parade pour POST est un identifiant fourni par l'appelant, que le serveur mémorise. Si la même clé arrive deux fois, la seconde requête renvoie le résultat de la première au lieu d'en créer un second. C'est ce qui rend une reprise après coup de perte de connexion possible sans créer de doublon — le défaut le plus signalé sur les systèmes de paiement et de commande.
Un appel qui expire chez l'appelant a peut-être été exécuté côté serveur. Toute opération non idempotente crée donc une incertitude réelle. La conception doit la traiter explicitement : soit l'opération est idempotente par construction, soit elle est réversible, soit elle fournit un moyen de savoir si elle a abouti. Une conception qui ignore ce cas produit des doublons, pas des erreurs visibles.
Une API se teste plus facilement qu'une interface, parce que son comportement est entièrement décrit par ses entrées et ses sorties. Cela ne dispense pas de tester les cas que personne n'écrit.
Une API publiée est un contrat qui vit : il faut la surveiller, la faire évoluer et savoir ce qu'elle fait réellement.
Trois règles, dans cet ordre :
Une documentation d'API publiée est un service : elle évolue, elle a des versions, et elle a des lecteurs pressés. Les trois erreurs habituelles sont de la documenter une fois à la livraison, d'en écrire trois pages là où une suffit, et d'omettre la section la plus utile de toutes — les exemples complets et exécutables, un par cas d'usage courant. Un exemple qui marche remplace un paragraphe entier.
Concevoir et implémenter l'API d'un service métier de son choix : spécification OpenAPI rédigée avant l'implémentation, authentification par jeton, contrôle d'accès par objet, pagination, limites de débit, idempotence sur la création, et suite de tests dont un test de contrat exécuté contre la spécification.
Le jury retient ceci : l'API reste-t-elle utilisable par quelqu'un qui n'a jamais vu son code ? Test final à faire passer : donner la spécification à un collègue et lui demander de créer une ressource sans poser de question. Les questions qu'il pose sont exactement les zones d'ombre de l'API — et une API qui exige de poser des questions n'est pas terminée.
Ecrire la specification avant le code, puis la faire executer comme un test.
Publié le 29/09/2026