OpenAPI + Zod mit Claude Code: API-First Development 2026
API-First bedeutet: Schema zuerst, Code danach. Mit OpenAPI und Zod generiert Claude Code typsichere API-Clients, Validierungsschemas und vollständige Dokumentation — direkt aus einer einzigen Source of Truth.
OpenAPI Schema mit Claude Code designen
SchemaOpenAPI 3.1 YAML/JSON
# Prompt: "Erstelle OpenAPI 3.1 Schema fuer eine Project-Management-API"
# openapi.yaml — Claude Code generiert vollstaendiges Schema:
openapi: "3.1.0"
info:
title: Project Management API
version: "1.0.0"
components:
schemas:
Project:
type: object
required: [id, name, orgId, createdAt]
properties:
id:
type: string
format: cuid
name:
type: string
minLength: 1
maxLength: 200
orgId:
type: string
status:
type: string
enum: [active, archived, deleted]
default: active
tags:
type: array
items:
type: string
createdAt:
type: string
format: date-time
CreateProjectDto:
type: object
required: [name, orgId]
properties:
name:
type: string
minLength: 1
orgId:
type: string
securitySchemes:
bearerAuth:
type: http
scheme: bearer
paths:
/projects:
get:
summary: List projects
security: [{bearerAuth: []}]
parameters:
- name: orgId
in: query
required: true
schema: {type: string}
- name: page
in: query
schema: {type: integer, default: 1}
responses:
"200":
content:
application/json:
schema:
type: object
properties:
data:
type: array
items: {$ref: "#/components/schemas/Project"}
total: {type: integer}
"401":
description: Unauthorized
Code-Generierung mit openapi-typescript
CodegenTypeScript-Typen aus OpenAPI
# Typen generieren (einmalig oder im CI)
npx openapi-typescript openapi.yaml -o src/types/api.ts
# Generierte Typen nutzen mit openapi-fetch:
import createClient from "openapi-fetch";
import type { paths } from "./types/api";
const client = createClient<paths>({ baseUrl: "/api" });
// Vollstaendig typsicher — keine manuellen Typen!
const { data, error } = await client.GET("/projects", {
params: {
query: { orgId: "org-123", page: 1 },
},
});
// data ist typed als { data: Project[], total: number }
// error ist typed als 401-Response-Schema
const { data: newProject } = await client.POST("/projects", {
body: { name: "Neues Projekt", orgId: "org-123" },
// body ist typed als CreateProjectDto
});
# package.json Script fuer automatische Regenerierung:
# "generate:api": "openapi-typescript openapi.yaml -o src/types/api.ts"
# In CI: npm run generate:api && git diff --exit-code
Codegen-Tipp: "Generiere TypeScript-Typen aus meinem OpenAPI-Schema und zeige mir wie ich openapi-fetch typsicher nutze." Claude Code schreibt das gesamte Client-Setup mit korrekten Generic-Typen.
Zod aus OpenAPI generieren
ValidationServer-seitige Validation mit Zod
# openapi-zod-client: Zod-Schemas aus OpenAPI
npx openapi-zod-client openapi.yaml -o src/schemas/api.ts
# Oder: manuell mit zod-to-openapi (umgekehrter Weg)
import { extendZodWithOpenApi, OpenApiGeneratorV31 } from "@asteasolutions/zod-to-openapi";
import { z } from "zod";
extendZodWithOpenApi(z);
// Zod-Schema mit OpenAPI-Metadaten
const ProjectSchema = z.object({
id: z.string().cuid().openapi({ example: "clxxxxxxx" }),
name: z.string().min(1).max(200).openapi({ example: "Mein Projekt" }),
orgId: z.string(),
status: z.enum(["active", "archived"]).default("active"),
}).openapi("Project");
// OpenAPI-Dokument aus Zod generieren:
const generator = new OpenApiGeneratorV31([registry]);
const document = generator.generateDocument({
openapi: "3.1.0",
info: { title: "API", version: "1.0.0" },
});
// Vorteil: Zod = Source of Truth → OpenAPI wird generiert, nicht umgekehrt
API-Client mit React Query
ClientTypsichere Queries aus OpenAPI
# Prompt: "Erstelle React Query Hooks aus meinem OpenAPI-Client"
// hooks/useProjects.ts — generierter + manueller Layer
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { client } from "../lib/api-client";
export function useProjects(orgId: string) {
return useQuery({
queryKey: ["projects", orgId],
queryFn: async () => {
const { data, error } = await client.GET("/projects", {
params: { query: { orgId } },
});
if (error) throw new Error("Failed to fetch projects");
return data;
},
});
}
export function useCreateProject() {
const qc = useQueryClient();
return useMutation({
mutationFn: async (body: CreateProjectDto) => {
const { data, error } = await client.POST("/projects", { body });
if (error) throw new Error("Failed to create project");
return data;
},
onSuccess: (_, { orgId }) => {
qc.invalidateQueries({ queryKey: ["projects", orgId] });
},
});
}
API-Design im Kurs
Im Claude Code Mastery Kurs: vollstaendiges API-First-Modul mit OpenAPI Schema-Design, Code-Generierung, Zod-Validation und React Query Integration — inkl. CI-Pipeline fuer automatische Schema-Synchronisation.
14 Tage kostenlos testen →