Apprenez à générer OpenAPI à partir du comportement avec Claude Code, puis comparez‑le à votre implémentation API et créez des exemples simples de validation client et serveur.

Un contrat OpenAPI est une description partagée de votre API : quels endpoints existent, ce que vous envoyez, ce que vous recevez en retour, et à quoi ressemblent les erreurs. C’est l’accord entre le serveur et tout ce qui l’appelle (une application web, une appli mobile ou un autre service).
Le problème, c’est la dérive. L’API en cours d’exécution change, mais le spec ne suit pas. Ou le spec est « nettoyé » pour paraître plus propre que la réalité, tandis que l’implémentation continue à renvoyer des champs étranges, des codes de statut manquants ou des formes d’erreur incohérentes. Avec le temps, les gens cessent de faire confiance au fichier OpenAPI, et il devient juste un autre document ignoré par tous.
La dérive vient généralement de pressions normales : un correctif rapide est déployé sans mettre à jour le spec, un nouveau champ optionnel est ajouté « temporairement », la pagination évolue, ou des équipes mettent à jour différentes « sources de vérité » (code backend, collection Postman et fichier OpenAPI).
Garder le spec honnête signifie qu’il reflète le comportement réel. Si l’API renvoie parfois 409 pour un conflit, cela doit figurer dans le contrat. Si un champ est nullable, indiquez‑le. Si l’auth est requise, ne laissez pas ça vague.
Un bon workflow vous donne :
Ce dernier point est important, car un contrat n’aide que lorsqu’il est appliqué. Un spec honnête plus des vérifications répétables transforme la « documentation API » en quelque chose sur lequel les équipes peuvent compter.
Si vous commencez par lire le code ou copier les routes, votre OpenAPI décrira ce qui existe aujourd’hui, incluant des particularités que vous ne voulez peut‑être pas promettre. Au lieu de ça, décrivez ce que l’API doit faire pour un appelant, puis utilisez le spec pour vérifier que l’implémentation correspond.
Avant d’écrire du YAML ou du JSON, collectez un petit ensemble de faits par endpoint :
Puis rédigez le comportement sous forme d’exemples. Les exemples vous forcent à être précis et facilitent la rédaction d’un contrat cohérent.
Pour une API de tâches, un chemin heureux pourrait être : « Créer une tâche avec title et recevoir id, title, status et createdAt. » Ajoutez des échecs courants : « title manquant renvoie 400 avec {\"error\":\"title is required\"} » et « Pas d’auth renvoie 401. » Si vous connaissez déjà des cas limites, incluez‑les : les titres dupliqués sont‑ils autorisés, et que se passe‑t‑il quand un ID de tâche n’existe pas.
Capturez les règles en phrases simples qui ne dépendent pas des détails du code :
title est requis et fait 1 à 120 caractères. »limit est défini (max 200). »dueDate est un date‑time ISO 8601. »Enfin, décidez du périmètre de votre v1. Si vous n’êtes pas sûr, gardez la v1 petite et claire (créer, lire, lister, mettre à jour le statut). Laissez la recherche, les mises à jour en masse et les filtres complexes pour plus tard afin que le contrat reste crédible.
Avant de demander à Claude Code d’écrire un spec, rédigez des notes de comportement dans un format petit et répétable. Le but est de rendre difficile le fait de « combler les vides » par des suppositions.
Un bon modèle est assez court pour que vous l’utilisiez vraiment, mais suffisamment cohérent pour que deux personnes décrivent le même endpoint de façon similaire. Gardez l’attention sur ce que fait l’API, pas sur la façon dont elle est implémentée.
Use one block per endpoint:
METHOD + PATH:
Purpose (1 sentence):
Auth:
Request:
- Query:
- Headers:
- Body example (JSON):
Responses:
- 200 OK example (JSON):
- 4xx example (status + JSON):
Edge cases:
Data types (human terms):
Écrivez au moins une requête concrète et deux réponses. Incluez les codes de statut et des corps JSON réalistes avec des noms de champs réels. Si un champ est optionnel, montrez un exemple où il est absent.
Signalez explicitement les cas limites. Ce sont des endroits où les specs deviennent discrètement fausses plus tard parce que chacun suppose quelque chose de différent : résultats vides, IDs invalides (400 vs 404), doublons (409 vs comportement idempotent), échecs de validation et limites de pagination.
Notez aussi les types de données en termes simples avant de penser aux schémas : chaînes vs nombres, formats date‑time, booléens et enums (liste des valeurs autorisées). Cela évite un schéma « joli » qui ne correspond pas aux payloads réels.
Claude Code fonctionne mieux si vous le traitez comme un scribe méticuleux. Donnez‑lui vos notes de comportement et des règles strictes sur la forme du OpenAPI. Si vous dites seulement « écris un spec OpenAPI », vous obtiendrez souvent des suppositions, des noms incohérents et des cas d’erreur manquants.
Collez d’abord vos notes de comportement, puis ajoutez un bloc d’instructions serré. Un prompt pratique ressemble à ceci :
You are generating an OpenAPI 3.1 YAML spec.
Source of truth: the behavior notes below. Do not invent endpoints or fields.
If anything is unclear, list it under ASSUMPTIONS and leave TODO markers in the spec.
Requirements:
- Include: info, servers (placeholder), tags, paths, components/schemas, components/securitySchemes.
- For each operation: operationId, tags, summary, description, parameters, requestBody (when needed), responses.
- Model errors consistently with a reusable Error schema and reference it in 4xx/5xx responses.
- Keep naming consistent: PascalCase schema names, lowerCamelCase fields, stable operationId pattern.
Behavior notes:
[PASTE YOUR NOTES HERE]
Output only the OpenAPI YAML, then a short ASSUMPTIONS list.
Après avoir obtenu le brouillon, lisez d’abord les ASSUMPTIONS. C’est là que l’honnêteté est gagnée ou perdue. Approuvez ce qui est correct, corrigez ce qui est faux, et relancez avec des notes mises à jour.
Pour garder la nomenclature cohérente, énoncez les conventions dès le départ et tenez‑vous‑y. Par exemple : un pattern stable pour operationId, noms de tags uniquement des noms de ressources, noms de schémas au singulier, un Error partagé, et un seul nom de schéma d’auth utilisé partout.
Si vous travaillez dans un espace vibe‑coding comme Koder.ai, il est utile d’enregistrer le YAML comme un vrai fichier tôt et d’itérer par petits diffs. Vous pouvez voir quelles modifications viennent de décisions de comportement approuvées versus des détails que le modèle a devinés.
Avant de comparer quoi que ce soit à la production, assurez‑vous que le fichier OpenAPI est internement cohérent. C’est le moyen le plus rapide de trouver les souhaits ou le langage vague.
Lisez chaque endpoint comme si vous étiez le développeur client. Concentrez‑vous sur ce qu’un appelant doit envoyer et sur ce qu’il peut compter recevoir.
Un passage de revue pratique :
Les réponses d’erreur méritent une attention particulière. Choisissez une forme partagée et réutilisez‑la partout. Certaines équipes gardent cela très simple ({ error: string }), d’autres utilisent un objet ({ error: { code, message, details } }). Les deux peuvent fonctionner, mais ne les mélangez pas entre endpoints et exemples. Sinon, le code client accumulera des cas spéciaux.
Un petit scénario de sanity check aide. Si POST /tasks exige title, le schéma doit le marquer comme requis, la réponse d’échec doit montrer quel corps d’erreur vous renvoyez réellement, et l’opération doit indiquer clairement si l’auth est requise.
Une fois que le spec ressemble à votre comportement attendu, traitez l’API en cours d’exécution comme la vérité de ce que vivent les clients aujourd’hui. Le but n’est pas de « gagner » entre spec et code, mais de faire remonter tôt les différences et de prendre une décision claire sur chacune.
Pour une première passe, des échantillons réels requête/réponse sont souvent la solution la plus simple. Les logs et tests automatisés fonctionnent aussi s’ils sont fiables.
Surveillez les écarts courants : endpoints présents d’un côté mais pas de l’autre, différences de noms ou de formes de champs, différences de codes de statut (200 vs 201, 400 vs 422), comportements non documentés (pagination, tri, filtrage), et différences d’auth (le spec dit public, le code exige un token).
Exemple : votre OpenAPI indique que POST /tasks renvoie 201 avec {id,title}. Vous appelez l’API en cours et recevez 200 plus {id,title,createdAt}. Ce n’est pas « assez proche » si vous générez des SDKs depuis le spec.
Avant d’éditer quoi que ce soit, décidez comment résoudre les conflits :
Gardez chaque changement petit et révisable : un endpoint, une réponse, un ajustement de schéma. C’est plus facile à relire et à retester.
Une fois que vous avez un spec de confiance, transformez‑le en petits exemples de validation. C’est ce qui empêche la dérive de revenir.
Sur le serveur, la validation signifie échouer rapidement quand une requête ne correspond pas au contrat, et renvoyer une erreur claire. Cela protège vos données et rend les bugs plus faciles à repérer.
Une manière simple d’exprimer des exemples de validation serveur est de les écrire comme des cas avec trois parties : input, output attendu et erreur attendue (un code d’erreur ou un pattern de message, pas du texte exact).
Exemple (le contrat dit que title est requis et doit faire 1 à 120 caractères) :
{
"name": "Create task without title returns 400",
"request": {"method": "POST", "path": "/tasks", "body": {"title": ""}},
"expect": {"status": 400, "body": {"error": {"code": "VALIDATION_ERROR"}}}
}
Côté client, la validation sert à détecter la dérive avant les utilisateurs. Si le serveur commence à renvoyer une forme différente, ou si un champ requis disparaît, vos tests doivent le signaler.
Conservez les vérifications client focalisées sur ce dont vous dépendez réellement, comme « une tâche a id, title, status ». Évitez d’asserter chaque champ optionnel ou l’ordre exact. Vous voulez des échecs sur des changements cassants, pas sur des ajouts anodins.
Quelques lignes directrices pour garder les tests lisibles :
Si vous construisez avec Koder.ai, vous pouvez générer et conserver ces cas d’exemple à côté de votre fichier OpenAPI, puis les mettre à jour dans la même revue quand le comportement change.
Imaginez une petite API avec trois endpoints : POST /tasks crée une tâche, GET /tasks liste les tâches, et GET /tasks/{id} renvoie une tâche.
Commencez par écrire quelques exemples concrets pour un endpoint, comme si vous l’expliquiez à un testeur.
Pour POST /tasks, le comportement attendu pourrait être :
{ "title": "Buy milk" } et obtenir 201 avec un objet tâche, incluant un id, le title et done:false.{} et obtenir 400 avec une erreur comme { "error": "title is required" }.{ "title": "x" } (trop court) et obtenir 422 avec { "error": "title must be at least 3 characters" }.Quand Claude Code rédige le OpenAPI, le snippet pour cet endpoint doit capturer le schéma, les codes de statut et des exemples réalistes :
paths:
/tasks:
post:
summary: Create a task
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTaskRequest'
examples:
ok:
value: { "title": "Buy milk" }
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/Task'
examples:
created:
value: { "id": "t_123", "title": "Buy milk", "done": false }
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
missingTitle:
value: { "error": "title is required" }
'422':
description: Unprocessable Entity
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
tooShort:
value: { "error": "title must be at least 3 characters" }
Un désaccord courant est subtil : l’API en cours renvoie 200 au lieu de 201, ou elle renvoie { "taskId": 123 } au lieu de { "id": "t_123" }. C’est le genre de différence « presque la même » qui casse les clients générés.
Corrigez‑le en choisissant une vérité. Si le comportement voulu est correct, changez l’implémentation pour renvoyer 201 et la forme Task convenue. Si le comportement en production est déjà utilisé, mettez à jour le spec (et les notes de comportement) pour refléter la réalité, puis ajoutez les validations et réponses d’erreur manquantes pour que les clients ne soient pas surpris.
Un contrat devient malhonnête quand il cesse de décrire des règles et commence à décrire tout ce que votre API a renvoyé un bon jour. Un test simple : une nouvelle implémentation pourrait‑elle satisfaire ce spec sans reproduire les bizarreries d’aujourd’hui ?
Un piège est le sur‑apprentissage. Vous capturez une réponse et en faites la loi. Exemple : votre API renvoie actuellement dueDate: null pour chaque tâche, donc le spec dit que le champ est toujours nullable. Mais la vraie règle pourrait être « requis quand le status est scheduled ». Le contrat doit exprimer la règle, pas seulement le dataset actuel.
Les erreurs sont souvent l’endroit où l’honnêteté se casse. Il est tentant de spécifier seulement les réponses de succès parce qu’elles paraissent propres. Mais les clients ont besoin du minimum : 401 quand le token manque, 403 pour accès refusé, 404 pour IDs inconnus, et une erreur de validation cohérente (400 ou 422).
D’autres motifs qui causent des problèmes :
taskId dans une route mais id ailleurs, ou priority en string d’un côté et en nombre de l’autre).string, tout devient optionnel).Un bon contrat est testable. Si vous ne pouvez pas écrire un test qui échoue à partir du spec, ce n’est pas encore honnête.
Avant de remettre un fichier OpenAPI à une autre équipe (ou de le coller dans des docs), faites une passe rapide pour « est‑ce que quelqu’un peut l’utiliser sans lire dans vos pensées ? »
Commencez par les exemples. Un spec peut être valide et pourtant inutile si chaque requête et réponse est abstraite. Pour chaque opération, incluez au moins un exemple réaliste de requête et un exemple de réponse de succès. Pour les erreurs, un exemple par échec courant (auth, validation) suffit généralement.
Ensuite vérifiez la cohérence. Si un endpoint renvoie { "error": "..." } et un autre { "message": "..." }, les clients auront une logique en branchement partout. Choisissez une forme d’erreur unique et réutilisez‑la, avec des codes de statut prévisibles.
Une petite checklist :
Une astuce pratique : choisissez un endpoint, faites comme si vous n’aviez jamais vu l’API, et répondez « Que j’envoie‑je, que reçois‑je en retour, et qu’est‑ce qui casse ? » Si l’OpenAPI ne peut pas répondre clairement, il n’est pas prêt.
Ce workflow paye quand il tourne régulièrement, pas seulement lors d’une panique de release. Choisissez une règle simple et tenez‑vous‑y : exécutez‑la à chaque changement d’endpoint, et relancez‑la avant de publier un spec mis à jour.
Simplifiez la propriété. La personne qui change un endpoint met à jour les notes de comportement et le brouillon du spec. Une seconde personne relit le diff « spec vs implementation » comme une review de code. Les collègues QA ou support font souvent de bons reviewers parce qu’ils repèrent vite les réponses et cas limites flous.
Traitez les modifications de contrat comme du code. Si vous utilisez un constructeur piloté par chat comme Koder.ai, prendre un snapshot avant des modifications risquées et revenir en arrière si besoin garde l’itération sûre. Koder.ai permet aussi d’exporter le code source, ce qui aide à garder le spec et l’implémentation côte à côte dans votre repo.
Une routine qui marche sans ralentir les équipes :
Action suivante : choisissez un endpoint existant. Écrivez 5–10 lignes de notes de comportement (entrées, sorties, cas d’erreur), générez un brouillon OpenAPI à partir de ces notes, validez‑le, puis comparez‑le à l’implémentation en cours. Corrigez un écart, retestez, et recommencez. Après un endpoint, l’habitude a tendance à s’installer.
La dérive OpenAPI, c'est lorsque l'API que vous exécutez réellement ne correspond plus au fichier OpenAPI que vous partagez. Le spec peut manquer des champs récents, des codes de statut ou des règles d'authentification, ou bien décrire un comportement « idéal » que le serveur ne suit pas.
C'est important parce que les clients (applications, autres services, SDKs générés, tests) prennent des décisions à partir du contrat, pas à partir de ce que votre serveur « fait habituellement ».
Les pannes côté client deviennent aléatoires et difficiles à déboguer : une appli mobile attend 201 mais reçoit 200, un SDK ne peut pas désérialiser une réponse parce qu'un champ a été renommé, ou la gestion des erreurs échoue parce que les formats diffèrent.
Même quand rien ne plante, les équipes perdent confiance et cessent d'utiliser le spec, ce qui supprime votre système d'alerte précoce.
Parce que le code reflète le comportement actuel, y compris des bizarreries accidentelles que vous n'avez peut‑être pas envie de promettre à long terme.
Un meilleur point de départ est : écrivez d'abord le comportement voulu (entrées, sorties, erreurs), puis vérifiez que l'implémentation correspond. Cela vous donne un contrat que vous pouvez faire respecter, plutôt qu'une photo instantanée des routes d'aujourd'hui.
Pour chaque endpoint, capturez :
Choisissez une forme d'erreur et réutilisez‑la partout.
Un choix simple est soit :
{ "error": "message" }, soit{ "error": { "code": "...", "message": "...", "details": ... } }Puis rendez-le cohérent entre endpoints et exemples. La cohérence compte plus que la sophistication, car les clients vont coder en dur cette forme.
Donnez à Claude Code vos notes de comportement et des règles strictes, et dites‑lui de ne pas inventer de champs. Un jeu d'instructions pratique :
TODO dans le spec et listez‑le sous ASSUMPTIONS. »Error) et les référencer. »Après génération, lisez d'abord la section . C'est là que l'honnêteté commence à se perdre si vous acceptez des suppositions.
Validez d'abord le spec lui‑même :
201)Cela permet d'attraper les fichiers OpenAPI « souhaitistes » avant même de regarder la prod.
Considérez l'API en cours comme ce que les utilisateurs voient aujourd'hui, et décidez au cas par cas :
Gardez les changements petits (un endpoint ou une réponse à la fois) pour pouvoir retester rapidement.
La validation côté serveur doit rejeter rapidement les requêtes qui violent le contrat et renvoyer une erreur claire et cohérente (statut + code/forme d'erreur).
La validation côté client doit détecter tôt les changements cassants de réponse en ne vérifiant que ce dont vous dépendez réellement :
Évitez d'asserter chaque champ optionnel pour que les tests échouent sur de vraies régressions, pas sur des ajouts innocents.
Une routine pratique :
Si vous travaillez avec Koder.ai, vous pouvez garder le fichier OpenAPI à côté du code, faire des snapshots avant les modifications risquées et revenir en arrière si un changement rend le diff confus.
Si vous pouvez écrire une requête concrète et deux réponses, vous avez généralement assez pour rédiger un spec fidèle.