API Documentation
Rules
- OpenAPI 3.1 spec as the single source of truth — generate from code, not manually written
- Zod schemas to OpenAPI: use
zod-openapi or @asteasolutions/zod-to-openapi — define once, validate and document
- Interactive docs: Scalar (modern, fast) or Swagger UI — serve at
/docs or /api-docs
- Every endpoint must have: summary, description, request body schema, all response codes with examples
- Example request/response for every endpoint — use realistic data, not
"string" placeholders
- Versioning strategy: URL path (
/api/v1/, /api/v2/) for breaking changes — simpler than header versioning
- Error responses: document all error shapes consistently —
{ error: string, code: string, details?: object }
- Authentication: document auth scheme (Bearer token, API key) in security schemes section
- Group endpoints by resource:
/users, /products, /orders — use tags for grouping in docs UI
Patterns
import { z } from "zod";
import { extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi";
extendZodWithOpenApi(z);
const UserSchema = z.object({
id: z.string().uuid().openapi({ example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }),
name: z.string().openapi({ example: "Jane Smith" }),
email: z.string().email().openapi({ example: "[email protected]" }),
}).openapi("User");
const CreateUserSchema = UserSchema.omit({ id: true }).openapi("CreateUser");
registry.registerPath({
method: "post",
path: "/api/v1/users",
summary: "Create a user",
request: { body: { content: { "application/json": { schema: CreateUserSchema } } } },
responses: {
201: { description: "User created", content: { "application/json": { schema: UserSchema } } },
400: { description: "Validation error" },
},
});
Avoid
- Writing OpenAPI YAML by hand — generate from Zod schemas or route definitions
- Missing error response documentation — document 400, 401, 403, 404, 500
- Generic examples like
"string" or 0 — use realistic values that show the shape of real data
- Docs that drift from implementation — generate spec from the same schemas used for validation