> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://cla-demo.postmansolutions.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://cla-demo.postmansolutions.com/_mcp/server.

# Zod To OpenAPI

### User Story:

[User Story 712102 Spike: Evaluate use of Zod-to-OpenAPI for schema generation](https://dev.azure.com/CLADevOps/Development/_workitems/edit/712102)

### Library:

[https://github.com/asteasolutions/zod-to-openapi](https://github.com/asteasolutions/zod-to-openapi)

### Branch:

[CLADevOps/fluxx-registration at jv\_ZodToOpenAPI\_2\_712102](https://github.com/CLADevOps/fluxx-registration/tree/jv_ZodToOpenAPI_2_712102)

### 1. Can Zod-to-OpenAPI generate accurate and usable Swagger docs?

Yes, but only partly.\
Zod-to-OpenAPI can generate proper OpenAPI 3.x docs from Zod schemas, including schema components, types, required fields, and example values.

It works well for JSON request/response bodies, but the registered paths (`registerPath`) don’t automatically show up in Fastify Swagger. You will need to manually add them or use a generator.
So, it is good for documentation, but not a plug-and-play setup for Fastify validation.

### 2. Does it support multipart/form-data and file uploads?

Limited support in this version.\
You can document uploads by marking fields as `type: string`, `format: binary` in `.openapi()` metadata, but it won’t automatically generate full multipart schemas or validate uploads properly.

### 3. How hard is it to integrate with Fastify Swagger?

hard.\
`.openapi()` is meant for docs, not runtime validation. Using these directly in Fastify routes can trigger validation errors like `data/required must be array`.\
To make paths appear in Swagger, inject paths manually into the Fastify Swagger config.
Setup isn’t smooth.

### 4. Does it reduce duplication?

Yes, for schemas.\
You only define fields, examples, and required properties once in Zod, which can be used for both validation and docs.
However, path definitions still need manual work, so it does not remove duplication there.

### 5. Tradeoffs

| Area            | What’s good                                               | What’s not                                                                                        |
| --------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| Flexibility     | Can describe complex Zod schemas with examples and types. | Multipart/form-data and file uploads still limited.                                               |
| Maintainability | One source of truth for schema definitions.               | Paths are duplicated, you declare them in Fastify and again in registry. Easy to get out of sync. |
| Dev Experience  | `.openapi()` annotations are clean and readable.          | Manual registry setup adds extra work per route; error-prone for large services.                  |

#### This is where paths are duplicated

|               | Before (Fastify only) | After (with Zod-to-OpenAPI)              |
| ------------- | --------------------- | ---------------------------------------- |
| Where defined | `fastify.route()`     | `fastify.route()` **+** `registerPath()` |
| Impact        | Single source         | Duplicate paths to maintain              |
| Risk          | None                  | Fastify vs Swagger mismatch              |

#### Before (Fastify only)

fastify.route(\{
method: 'POST',
url: '/users',
schema: userSchema,
handler: createUser,
});

#### After (with Zod-to-OpenAPI)

fastify.route(\{
method: 'POST',
url: '/users',
schema: userSchema,
handler: createUser,
});

registry.registerPath(\{
method: 'POST',
path: '/users',
request: \{ body: userSchema },
responses: \{ 200: userResponse },
});

---

## Things to consider

* Use **Zod-to-OpenAPI** only for generating documentation but it is not tailored for Fastify JSON Schema.
* There is another library which is [https://www.npmjs.com/package/@anatine/zod-openapi](https://www.npmjs.com/package/@anatine/zod-openapi) that might work for Fastify integration

# Recommendation

* Keep plain **Zod** for Fastify runtime validation.