Use Cases (Mis à jour: 03/06/2026)

Claude Code et OpenAPI 3.1 : validation Swagger et génération TypeScript

Créez des specs OpenAPI 3.1 avec Claude Code, validez-les et générez un client TypeScript fiable.

Claude Code et OpenAPI 3.1 : validation Swagger et génération TypeScript

Claude Code peut produire une spécification OpenAPI très vite. Ce n’est pas suffisant pour la publier. Sans garde-fous, il peut ajouter un champ vu dans une maquette, inventer une valeur d’enum ou modifier la forme des erreurs d’une route à l’autre.

Ce guide montre comment l’utiliser comme assistant de maintenance de contrat API. Nous allons créer une spécification OpenAPI 3.1, la valider, générer un client TypeScript et un stub serveur, puis ajouter un petit contrôle local contre les schémas hallucinés. OpenAPI décrit les endpoints REST, les requêtes, les réponses, l’authentification et les erreurs. Swagger désigne l’écosystème d’outils utilisé pour éditer, afficher et vérifier ces documents.

Masa a testé ce flux sur une petite API de commandes. Le prompt libre a généré un statut cancelled inexistant dans le modèle métier. Le flux fiable consistait à imposer les fichiers à lire, interdire les champs non prouvés, valider la spec et sortir les questions ouvertes du schéma public.

Références officielles : au 3 juin 2026, OpenAPI Specification latest pointe vers 3.2.0, mais les exemples de cet article restent en openapi: 3.1.0 pour la compatibilité des générateurs. Utilisez OpenAPI Specification 3.1.2, Swagger Editor documentation, OpenAPI Generator usage, typescript-fetch generator et typescript-nestjs-server generator. Pour OpenAPI 3.1, vérifiez le support de Swagger Editor Next dans la documentation actuelle.

À lire aussi : développement API avec Claude Code, tests API, sécurité Claude Code et bonnes pratiques CLAUDE.md.

flowchart LR
  A["Code, base, tests"] --> B["Claude Code rédige OpenAPI"]
  B --> C["Validation Swagger et CLI"]
  C --> D["Client TypeScript"]
  C --> E["Tests de contrat"]
  C --> F["Revue sécurité"]
  D --> G["Frontend ou partenaires"]
  E --> H["Gate CI"]
  F --> H

Trois usages concrets

UsageTravail de Claude CodeDécision humaine
Documenter une API existanteRoutes, modèles, codes HTTP, authChamps publics, compatibilité, nommage
Démarrer en contract-firstBrouillon OpenAPI 3.1, exemples, commandesRègles métier, erreurs, périmètre
Brancher le frontendClient TypeScript, exemples d’appelUX, retry, messages utilisateurs
Tester le contratoperationId, 4xx, enums, authPolitique de breaking change et exceptions
Revue sécuritéSchemas publics, auth, PII, IDs internesRisque légal, audit, promesses aux partenaires
Publier à des partenairesDescriptions Swagger, exemples, authContrats, quotas, support

Si un détail de schéma n’est pas confirmé par le code, la base, les tests ou une décision produit, il doit rester en question ouverte.

Mise en place copiable

Node.js 20+ est recommandé. OpenAPI Generator utilise Java pour la génération.

mkdir openapi-claude-demo
cd openapi-claude-demo
npm init -y
npm install -D @openapitools/openapi-generator-cli js-yaml
mkdir specs generated scripts

Ajoutez ces scripts à package.json :

{
  "type": "module",
  "scripts": {
    "validate:openapi": "openapi-generator-cli validate -i specs/openapi.yaml",
    "lint:contract": "node scripts/check-openapi-rules.mjs",
    "test:contract": "node --test scripts/contract.test.mjs",
    "generate:client": "openapi-generator-cli generate -i specs/openapi.yaml -g typescript-fetch -o generated/client --additional-properties=supportsES6=true,npmName=@example/orders-client,npmVersion=0.1.0",
    "generate:server": "openapi-generator-cli generate -i specs/openapi.yaml -g typescript-nestjs-server -o generated/server",
    "contract": "npm run validate:openapi && npm run lint:contract && npm run test:contract && npm run generate:client"
  },
  "devDependencies": {
    "@openapitools/openapi-generator-cli": "latest",
    "js-yaml": "latest"
  }
}

Créez specs/openapi.yaml :

openapi: 3.1.0
info:
  title: Orders API
  version: 0.1.0
  description: Contract-first sample API for order intake.
servers:
  - url: https://api.example.com/v1
paths:
  /orders:
    post:
      operationId: createOrder
      summary: Create an order
      tags: [orders]
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateOrderRequest"
      responses:
        "201":
          description: Order created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Order"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  responses:
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    Unauthorized:
      description: Missing or invalid token
  schemas:
    CreateOrderRequest:
      type: object
      additionalProperties: false
      required: [customerEmail, items]
      properties:
        customerEmail:
          type: string
          format: email
        note:
          type: [string, "null"]
        items:
          type: array
          minItems: 1
          items:
            $ref: "#/components/schemas/OrderItemInput"
    OrderItemInput:
      type: object
      additionalProperties: false
      required: [sku, quantity]
      properties:
        sku:
          type: string
        quantity:
          type: integer
          minimum: 1
    Order:
      type: object
      additionalProperties: false
      required: [id, customerEmail, status, items, createdAt]
      properties:
        id:
          type: string
          format: uuid
        customerEmail:
          type: string
          format: email
        status:
          type: string
          enum: [pending, paid]
        items:
          type: array
          items:
            $ref: "#/components/schemas/OrderItemInput"
        createdAt:
          type: string
          format: date-time
    ErrorResponse:
      type: object
      additionalProperties: false
      required: [code, message]
      properties:
        code:
          type: string
          enum: [invalid_request, unauthorized]
        message:
          type: string

Ajoutez scripts/check-openapi-rules.mjs :

import { readFileSync } from "node:fs";

const spec = readFileSync("specs/openapi.yaml", "utf8");
const forbidden = [
  { pattern: /\bTBD\b|\bTODO\b|placeholder/i, reason: "unfinished placeholder" },
  { pattern: /nullable:\s*true/, reason: "OpenAPI 3.1 should use JSON Schema null types" },
  { pattern: /password|secret|clientSecret|apiKey/i, reason: "review sensitive fields before publishing" }
];

const errors = forbidden.filter((rule) => rule.pattern.test(spec)).map((rule) => `- ${rule.reason}`);
if (!spec.includes("additionalProperties: false")) errors.push("- schemas should explicitly decide additionalProperties");
if (errors.length > 0) {
  console.error("Contract review failed:\n" + errors.join("\n"));
  process.exit(1);
}
console.log("Contract review passed.");

Ajoutez aussi un test de contrat exécutable en CI. Il vérifie le contrat public : operationId, sécurité sur les opérations mutantes, réponses 4xx partagées et enum Order.status.

// scripts/contract.test.mjs
import { readFileSync } from "node:fs";
import assert from "node:assert/strict";
import test from "node:test";
import { load } from "js-yaml";

const doc = load(readFileSync("specs/openapi.yaml", "utf8"));
const httpMethods = new Set(["get", "put", "post", "delete", "patch", "options", "head", "trace"]);

function operations() {
  return Object.entries(doc.paths ?? {}).flatMap(([path, pathItem]) =>
    Object.entries(pathItem)
      .filter(([method]) => httpMethods.has(method))
      .map(([method, operation]) => ({ path, method, operation }))
  );
}

test("operationId is unique and camelCase", () => {
  const ids = operations().map(({ operation }) => operation.operationId);
  assert.equal(new Set(ids).size, ids.length);
  for (const id of ids) assert.match(id, /^[a-z][A-Za-z0-9]*$/);
});

test("mutating operations require security", () => {
  for (const { path, method, operation } of operations()) {
    if (["get", "head", "options"].includes(method)) continue;
    assert.ok(operation.security?.length, `${method.toUpperCase()} ${path} must declare security`);
  }
});

test("client-visible 4xx responses reuse shared components", () => {
  for (const { path, method, operation } of operations()) {
    for (const [status, response] of Object.entries(operation.responses ?? {})) {
      if (!status.startsWith("4")) continue;
      assert.ok(response.$ref?.startsWith("#/components/responses/"), `${method.toUpperCase()} ${path} ${status}`);
    }
  }
});

test("Order status enum matches the current implementation decision", () => {
  const status = doc.components.schemas.Order.properties.status;
  assert.deepEqual(status.enum, ["pending", "paid"]);
});

Puis lancez :

npm run validate:openapi
npm run lint:contract
npm run test:contract
npm run generate:client
npm run generate:server

Prompt à donner à Claude Code

Crée un contrat OpenAPI 3.1 pour l'API de commandes.
Lis src/routes/orders.ts, src/domain/order.ts, prisma/schema.prisma et tests/orders.test.ts.
N'invente aucun champ, enum ou code d'erreur non prouvé.
Place les questions dans x-claude-review, pas dans les schemas publics.
N'utilise pas nullable: true. Utilise des operationId camelCase stables.
Déclare security sur les opérations protégées. Sépare les champs internes, PII et secrets possibles dans x-claude-review.
Exécute npm run validate:openapi, npm run lint:contract et npm run test:contract, puis corrige les erreurs.
Retourne le diff, un exemple de client TypeScript, les notes sécurité et les points à valider humainement.

Tests de contrat et sécurité

Pour une API SaaS ou partenaire, la revue OpenAPI doit être découpée. La revue de spec regarde routes, méthodes, schemas, statuts et exemples. La revue du client généré vérifie les types typescript-fetch et le traitement de null. Les tests de contrat bloquent les auth manquantes, les erreurs incohérentes et les enums cassés. La revue sécurité vérifie les champs publics, PII, IDs internes, URLs serveur et secrets possibles.

Claude Code peut préparer les diffs, les tests et le tableau de revue. L’équipe garde la décision sur les champs publiables, les limites de débit, les engagements contractuels et les preuves d’audit.

Pièges fréquents

Les problèmes récurrents sont les schémas inventés, les formats d’erreur incohérents, les habitudes OpenAPI 3.0 dans un fichier 3.1, la modification manuelle du code généré et la revue uniquement visuelle dans Swagger. Le fichier specs/openapi.yaml reste la source de vérité ; les clients et stubs se régénèrent.

Formation et conseil

Cette démarche se vend bien en formation parce que les livrables sont visibles : spec OpenAPI, client TypeScript, stub serveur, test de contrat, validation et checklist CI. Pour travailler seul, consultez les produits ClaudeCodeLab. Pour une équipe avec dépôt réel, CLAUDE.md, tests API et revue sécurité, utilisez la page formation et conseil Claude Code.

Vérification terrain

Lors du test de Masa, le prompt libre a ajouté des statuts inexistants et modifié les erreurs. Avec les fichiers imposés, l’interdiction d’inventer, openapi-generator-cli validate, le script local et node --test, la revue humaine s’est limitée aux champs publics, à l’évolution des enums, au texte des erreurs d’authentification et au risque de fuite d’informations internes. OpenAPI a été le socle commun entre l’IA et l’équipe, pas un document abandonné à l’IA.

#Claude Code #OpenAPI #Swagger #API design #REST
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.