zod-openapi
Generate OpenAPI 3.x documentation directly from your existing Zod schemas.
Repository Health
Technical Analysis
zod-openapi converts Zod schemas into OpenAPI 3.1 (and 3.0-compatible) documentation without requiring a separate schema definition layer. Instead of maintaining Zod validators and OpenAPI specs as two parallel sources of truth, it reads metadata attached via Zod v4’s native .meta() method and renders the equivalent JSON Schema-based OpenAPI output, distinguishing between input contexts (request bodies, parameters) and output contexts (responses, headers) since the two can legitimately differ for the same logical schema.
The library exposes two entry points: createDocument, which builds a full OpenAPIObject from paths, webhooks, and components in one call, and createSchema, which converts a single Zod schema in isolation. Both understand Zod’s component registry, so schemas tagged with an id are automatically hoisted into components.schemas and referenced via $ref rather than inlined repeatedly. An override hook (object or function form) lets callers patch the generated JSON Schema for cases the automatic conversion cannot express, such as custom format values or restructuring anyOf into oneOf.
Because it builds on Zod 4’s built-in metadata and JSON Schema conversion rather than monkey-patching the Zod prototype (the approach used by earlier community solutions), it has no runtime side effects on unrelated Zod usage and stays compatible with Zod’s own release cadence. A companion Fastify plugin and ESLint plugin extend the same schema-to-OpenAPI approach into route registration and editor tooling.
What You Get
createDocument()— builds a complete OpenAPI 3.1 document from paths, webhooks, and components in a single call, given Zod schemas for request params, request bodies, and responsescreateSchema()— converts a single Zod schema into its OpenAPI JSON Schema representation, for callers who only need partial output- Native
.meta()integration — attachid,param,header,override, andoutputIdmetadata directly on Zod schemas with no prototype patching or wrapper functions - Automatic component registration and deduplication — schemas tagged with an
idare hoisted intocomponents.schemasand referenced by$refinstead of being inlined at every use site - Input/output schema differentiation — the same logical schema can render differently for a request body versus a response body (e.g.
additionalProperties: falseonly in outputs), generating separate components automatically when needed - Cycle and schema-reuse handling — configurable via
cycles(ref/throw) andreused(ref/inline) options for self-referential or shared schemas overridehooks — both a shallow object-merge form and a deep function form for patching generated JSON Schema output post-conversion- First-class support for parameters, request bodies, responses, headers, callbacks, links, security schemes, and path items as OpenAPI components
Common Use Cases
- Generating and publishing an OpenAPI/Swagger spec for a TypeScript API that already uses Zod for request/response validation, without maintaining a second spec by hand
- Feeding an auto-generated OpenAPI document into Redoc, Swagger UI, or an SDK/type generator as part of a CI pipeline
- Keeping request and response schemas as reusable, named OpenAPI components (
components.schemas) shared across many route definitions - Building typed API clients or contract tests from a spec that is guaranteed to match the server’s actual runtime validation, because both derive from the same Zod schema
Under The Hood
Architecture
createDocument orchestrates the conversion in three stages: createRegistry (components.ts) builds a ComponentRegistry that tracks separate input and output schema maps keyed by component id, createPaths (paths.ts) walks the supplied paths/webhooks and calls createOperation per HTTP method to resolve parameters, request bodies, and responses against that registry, and createComponents assembles the final components.schemas/parameters/headers/etc. from whatever the registry accumulated. Individual schema conversion is delegated to schema/schema.ts, which walks Zod v4’s $ZodType definitions into JSON Schema. The registry’s dedup-by-id, split-by-input/output-context design is the load-bearing abstraction: content.ts, headers.ts, parameters.ts, links.ts, and callbacks.ts all read from the same registry to decide between inlining a schema and emitting a $ref, so any change to that data structure ripples through every one of those modules.
Tech Stack
A TypeScript pnpm workspace with an internal packages/openapi3-ts package supplying typed OAS 3.0/3.1/3.2 interfaces, built with tsdown into dual ESM/CJS output via the package.json exports map, tested with Vitest, and released through Changesets. The peer dependency is zod ^4.0.0 — the library builds entirely on Zod’s own .meta() metadata and JSON Schema conversion rather than adding a parallel dependency. Tooling (build/lint/test scripts, release provenance) is wrapped by skuba, an internal SEEK build-tooling framework.
Code Quality
45 *.test.ts files sit alongside their implementation files, covering document.ts, paths.ts, components.ts, headers.ts, parameters.ts, callbacks.ts, links.ts, and object.ts with Vitest describe/it suites. ESLint (with a companion eslint-plugin-zod-openapi devDependency) and Prettier enforce style, GitHub Actions runs test and release workflows on every push, and the codebase is strict TypeScript throughout with no untyped escape hatches observed in the core modules read.
What Makes It Unique
Instead of monkey-patching Zod’s prototype — the approach older Zod-to-OpenAPI tools relied on — this library builds directly on Zod v4’s native .meta() and built-in JSON Schema conversion, so it has no side effects on unrelated Zod usage and tracks Zod’s own version support automatically. Its explicit splitting of input versus output component schemas for the same logical Zod type (since a schema can legitimately render differently in a request versus a response) is a design choice most comparable libraries skip, and the override function’s contextual callback (receiving the generated JSON Schema, the source Zod type, and whether it’s an input or output context) gives finer post-processing control than typical override mechanisms.
Used by 11 apps in this directory
Blinko
Knowledge Management · Note Taking
A self-hosted, AI-powered card note-taking tool that lets you capture fleeting thoughts instantly and retrieve them with natural language search.
Documenso
Digital Signiture
Self-hosted, open-source DocuSign alternative with legally binding PDF signatures, multi-party workflows, and a full REST and tRPC API.
Dub
Marketing · Analytics
The open-source link attribution platform for short links, conversion tracking, and affiliate programs — powering 100M+ clicks monthly.
FastGPT
AI Agents · AI Development
Build, debug, and deploy knowledge-based AI agents with a visual workflow editor, RAG retrieval, and support for any OpenAI-compatible LLM.
Formbricks
Forms Surveys · Marketing · Analytics
Open-source experience management platform for in-app, website, email, and link surveys — privacy-first and fully self-hostable.
Helicone
Monitoring · AI Development · Analytics
An open-source AI gateway and LLM observability platform that routes requests to 100+ models while logging cost, latency, and full traces for every call.
LLM Gateway
AI Development · Devops
One API endpoint for 25+ LLM providers — route, track costs, enforce compliance, and switch models without changing your code.
OpenCode
AI Code Assistants
A fully open-source AI coding agent built for the terminal, with a TUI, desktop app, web client, plugin system, and SDK — one of the most-starred AI coding agents on GitHub.
Papermark
Digital Signiture · File Storage
Open-source DocSend alternative with page-by-page analytics, secure data rooms, and custom domains for document sharing.