Claude Code mit OpenAPI 3.1: Swagger-Validierung und TypeScript-Generierung
Erstelle OpenAPI-3.1-Spezifikationen mit Claude Code, validiere sie und generiere TypeScript-Clients.
Claude Code kann sehr schnell eine OpenAPI-Datei schreiben. Riskant wird es, wenn diese Datei ohne Prüfung veröffentlicht wird. Dann entstehen Felder aus UI-Texten, nicht vorhandene enum-Werte oder wechselnde Fehlerformate zwischen Endpunkten.
In diesem Leitfaden nutzen wir Claude Code als Assistenten für API-Verträge. Du erstellst eine OpenAPI-3.1-Spezifikation, validierst sie, generierst einen TypeScript-Client und einen Server-Stub und ergänzt eine kleine Prüfung gegen halluzinierte Schemas. OpenAPI beschreibt REST-Endpunkte, Requests, Responses, Authentifizierung und Fehler maschinenlesbar. Swagger ist das Tool-Ökosystem, mit dem viele Teams solche Dokumente bearbeiten und anzeigen.
Masa hat den Ablauf an einer kleinen Bestell-API getestet. Der freie Prompt erzeugte einen plausiblen, aber falschen Status cancelled. Besser funktionierte ein enger Ablauf: konkrete Dateien lesen lassen, unbewiesene Felder verbieten, Validierung ausführen und offene Fragen außerhalb des öffentlichen Schemas sammeln.
Offizielle Quellen: Am 3. Juni 2026 zeigt OpenAPI Specification latest auf 3.2.0, die Beispiele hier bleiben wegen Generator-Kompatibilität bei openapi: 3.1.0. Nutze OpenAPI Specification 3.1.2, Swagger Editor documentation, OpenAPI Generator usage, typescript-fetch generator und typescript-nestjs-server generator. Für OpenAPI 3.1 solltest du in den aktuellen Swagger-Dokumenten prüfen, ob Swagger Editor Next die benötigten Funktionen abdeckt.
Passende interne Artikel sind der API-Entwicklungsleitfaden, der API-Testleitfaden, Security Best Practices und die CLAUDE.md Best Practices.
flowchart LR
A["Implementierung, DB, Tests"] --> B["Claude Code entwirft OpenAPI"]
B --> C["Swagger- und CLI-Validierung"]
C --> D["TypeScript Client"]
C --> E["Contract Tests"]
C --> F["Security Review"]
D --> G["Frontend oder Partner"]
E --> H["CI-Gate"]
F --> H
Praktische Einsatzfälle
| Einsatz | Claude Code übernimmt | Mensch entscheidet |
|---|---|---|
| Bestehende API dokumentieren | Routen, Modelle, HTTP-Codes, Auth-Grenzen | Öffentliche Felder, Kompatibilität, Namen |
| Contract-first entwickeln | OpenAPI-3.1-Entwurf, Beispiele, Befehle | Geschäftsregeln, Fehlerpolitik, Scope |
| Frontend anbinden | TypeScript-Client, Aufrufbeispiele, Typdiffs | UX, Retry-Verhalten, Texte |
| Contract Tests | operationId, 4xx-Antworten, Enums, Auth | Breaking-Change-Regeln und Ausnahmen |
| Security Review | Öffentliche Schemas, Auth, PII, interne IDs | Rechtliches Risiko, Audit, Partnerzusagen |
| Partner-API veröffentlichen | Swagger-Beschreibungen, Beispiele, Auth-Hinweise | Verträge, Limits, Support |
Die wichtigste Regel: Was Code, Datenbank, Tests oder Produktentscheidung nicht belegen, gehört nicht in das öffentliche Schema.
Kopierbares Setup
Voraussetzung ist Node.js 20+. Für die Codegenerierung benötigt OpenAPI Generator Java.
mkdir openapi-claude-demo
cd openapi-claude-demo
npm init -y
npm install -D @openapitools/openapi-generator-cli js-yaml
mkdir specs generated 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"
}
}
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
Zusätzliche Vertragsprüfung:
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.");
Ergänze einen Contract Test für CI. Er prüft den öffentlichen Vertrag: stabile operationId, Security bei mutierenden Operationen, gemeinsame 4xx-Antworten und das aktuelle Order.status-Enum.
// 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"]);
});
Ausführen:
npm run validate:openapi
npm run lint:contract
npm run test:contract
npm run generate:client
npm run generate:server
Prompt für Claude Code
Erstelle einen OpenAPI-3.1-Vertrag für die Bestell-API.
Lies zuerst src/routes/orders.ts, src/domain/order.ts, prisma/schema.prisma und tests/orders.test.ts.
Erfinde keine Felder, enum-Werte oder Fehlercodes, die nicht durch Code, Schema, Tests oder Produktnotiz belegt sind.
Offene Fragen kommen nach x-claude-review, nicht in öffentliche schemas.
Nutze kein nullable: true. Nutze stabile camelCase operationId-Werte.
Deklariere security bei geschützten Operationen. Interne Felder, PII und mögliche Secrets kommen zuerst in x-claude-review.
Führe npm run validate:openapi, npm run lint:contract und npm run test:contract aus und behebe Fehler.
Gib den Diff, ein TypeScript-Client-Beispiel, Security-Notizen und offene Prüfpunkte zurück.
Contract Tests und Security Review
Bei SaaS- und Partner-APIs ist OpenAPI-Review mehr als Textkorrektur. Trenne Spec Review, generierten Client, Contract Tests und Security Review. Spec Review prüft Pfade, Methoden, Schemas, Statuscodes und Beispiele. Der Client-Review prüft typescript-fetch-Typen und null/optional-Verhalten. Contract Tests stoppen fehlende Auth, driftende Fehlerformen und kaputte Enums. Security Review prüft öffentliche Felder, PII, interne IDs, Server-URLs und mögliche Secrets.
Claude Code kann Diffs inventarisieren, Tests entwerfen und Review-Tabellen vorbereiten. Menschen entscheiden weiterhin, was veröffentlicht werden darf, welche Rate Limits gelten, welche Vertragszusagen entstehen und welche Audit-Spuren nötig sind.
Typische Fehler
Häufig sind erfundene Schemas, inkonsistente Fehlerantworten, OpenAPI-3.0-Gewohnheiten in 3.1, manuelle Änderungen an generiertem Code und reine Sichtprüfung in Swagger. Die Spezifikation bleibt die Quelle der Wahrheit; Client und Server-Stub werden neu generiert.
Training und Beratung
OpenAPI-Aufräumen eignet sich gut für Workshops, weil die Ergebnisse konkret sind: Spezifikation, TypeScript-Client, Server-Stub, Contract Test, Validierung und CI-Checkliste. Einzelne Entwickler können mit ClaudeCodeLab Produkten Prompt- und Review-Vorlagen nutzen. Teams mit echtem Repository, CLAUDE.md, API-Tests und Security Review starten über Claude Code Training und Beratung.
Praxistest
Im Test erzeugte der freie Prompt nicht implementierte Statuswerte und wechselnde Fehlerformen. Mit festen Dateien, Verbot unbewiesener Felder, openapi-generator-cli validate, lokalem Regelcheck und node --test blieben für Menschen vor allem vier Entscheidungen: öffentliche Felder, zukünftige Enum-Erweiterung, Texte für Auth-Fehler und mögliche interne Daten im Schema. OpenAPI funktionierte als gemeinsamer Vertrag zwischen KI und Team.
Kostenloses PDF: Claude-Code-Cheatsheet
E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.
Wir schützen Ihre Daten und senden keinen Spam.
Über den Autor
Masa
Engineer für praktische Claude-Code-Workflows und Team-Einführung.
Ähnliche Artikel
Claude Code Workflow von Obsidian zu CLAUDE.md
Obsidian-Arbeitsnotizen in CLAUDE.md-Betriebsnotizen verwandeln und Kontext nicht ständig neu erklären.
Claude Code Revenue CTA Routing: Artikel zu PDF, Gumroad und Beratung führen
Ein Claude-Code-Ablauf, der Leser nach Absicht zu Gratis-PDF, Gumroad oder Beratung führt.
Claude-Code-Team-Handoff-Regeln: Belege, Berechtigungen, Rollback und Umsatzpfade
Ein praktisches Claude-Code-Handoff für Review-Belege, Berechtigungen, Rollback, Gratis-PDF, Gumroad und Beratung.