{"id":14156650,"url":"https://github.com/samchungy/zod-openapi","last_synced_at":"2026-01-05T07:22:05.215Z","repository":{"id":153100778,"uuid":"628179878","full_name":"samchungy/zod-openapi","owner":"samchungy","description":"Use Zod Schemas to create OpenAPI v3.x documentation","archived":false,"fork":false,"pushed_at":"2025-05-05T01:07:04.000Z","size":2853,"stargazers_count":413,"open_issues_count":15,"forks_count":19,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-11T04:16:42.806Z","etag":null,"topics":["json-schema","openapi","openapi3","swagger","typescript","zod","zod-openapi"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/samchungy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["samchungy"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2023-04-15T06:28:51.000Z","updated_at":"2025-05-08T17:37:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"fef2b795-db9f-41b7-ac69-8f730377ed17","html_url":"https://github.com/samchungy/zod-openapi","commit_stats":{"total_commits":438,"total_committers":13,"mean_commits":33.69230769230769,"dds":0.4200913242009132,"last_synced_commit":"c9ec8813a48e33b43ad1b0abdafcdc1d5fcb64ab"},"previous_names":[],"tags_count":82,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samchungy%2Fzod-openapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samchungy%2Fzod-openapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samchungy%2Fzod-openapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samchungy%2Fzod-openapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/samchungy","download_url":"https://codeload.github.com/samchungy/zod-openapi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254169583,"owners_count":22026213,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json-schema","openapi","openapi3","swagger","typescript","zod","zod-openapi"],"created_at":"2024-08-17T08:07:32.139Z","updated_at":"2026-01-05T07:22:05.209Z","avatar_url":"https://github.com/samchungy.png","language":"TypeScript","funding_links":["https://github.com/sponsors/samchungy"],"categories":["TypeScript","typescript"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"zod-openapi.png\" width=\"200px\" align=\"center\" alt=\"zod-openapi logo\" /\u003e\n  \u003ch1 align=\"center\"\u003ezod-openapi\u003c/h1\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\nA TypeScript library which uses \u003ca href=\"https://github.com/colinhacks/zod\"\u003eZod\u003c/a\u003e schemas to generate OpenAPI v3.x documentation.\n\u003c/p\u003e\n\u003cdiv align=\"center\"\u003e\n\u003ca href=\"https://www.npmjs.com/package/zod-openapi\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/zod-openapi\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://www.npmjs.com/package/zod-openapi\"\u003e\u003cimg src=\"https://img.shields.io/npm/dm/zod-openapi\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://nodejs.org/en/\"\u003e\u003cimg src=\"https://img.shields.io/node/v/zod-openapi\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/samchungy/zod-openapi/actions/workflows/test.yml\"\u003e\u003cimg src=\"https://github.com/samchungy/zod-openapi/actions/workflows/test.yml/badge.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/samchungy/zod-openapi/actions/workflows/release.yml\"\u003e\u003cimg src=\"https://github.com/samchungy/zod-openapi/actions/workflows/release.yml/badge.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/seek-oss/skuba\"\u003e\u003cimg src=\"https://img.shields.io/badge/🤿%20skuba-powered-009DC4\"/\u003e\u003c/a\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n## Installation\n\nInstall via `npm`, `yarn`, or `pnpm`:\n\n```bash\nnpm install zod zod-openapi\n# or\nyarn add zod zod-openapi\n# or\npnpm install zod zod-openapi\n```\n\n## Usage\n\n### `.meta()`\n\nUse Zod's native `.meta()` method to add OpenAPI metadata to your schemas. This library leverages Zod's built-in metadata functionality - no monkey patching or additional setup is required. Simply call `.meta()` on any Zod schema and it accepts an object with the following options:\n\n\u003e **Note:** To get full TypeScript support for the OpenAPI-specific properties in `.meta()`, you need to import `zod-openapi` somewhere in your project. This import provides TypeScript type definitions that extend Zod's `.meta()` interface at compile-time (no runtime changes), enabling your IDE and TypeScript compiler to recognize the additional properties (like `id`, `param`, `header`, etc.). In most cases this will be done where you call `createDocument` or other zod-openapi functions.\n\n| Option     | Description                                                                                                      |\n| ---------- | ---------------------------------------------------------------------------------------------------------------- |\n| `id`       | Registers a schema as a reusable OpenAPI component.                                                              |\n| `header`   | Adds metadata for [response headers](#response-headers).                                                         |\n| `param`    | Adds metadata for [request parameters](#parameters).                                                             |\n| `override` | Allows you to override the rendered OpenAPI schema. This takes either an object or a function.                   |\n| `outputId` | Allows you to set a different ID for the output schema. This is useful when the input and output schemas differ. |\n| `unusedIO` | Allows you to set the `io` for an unused schema added to the components section. Defaults to `output`.           |\n\nYou can also set standard OpenAPI properties directly in Zod's native `.meta()` method, such as:\n\n```typescript\nz.string().meta({\n  description: 'A text field',\n  example: 'Example value',\n});\n```\n\nYou can set additional metadata to the rendered schema in a few different ways. Zod's native `.meta()` method allows you to directly set OpenAPI properties to the schema. However, if you wanted to override any field that Zod generates, this may not work as expected. In this case, you can use the `override` option to customize the rendered OpenAPI schema.\n\neg.\n\n```typescript\nz.string().datetime().meta({\n  description: 'A date field',\n  format: 'MY-FORMAT',\n  'x-custom-field': 'custom value',\n});\n```\n\nWould render the following OpenAPI schema. Note that format is not overridden with our custom format value.\n\n```json\n{\n  \"type\": \"string\",\n  \"format\": \"date-time\",\n  \"description\": \"A date field\",\n  \"x-custom-field\": \"custom value\"\n}\n```\n\nIn order to override fields which are generated by Zod or this library, you can use the `override` option in Zod's `.meta()` method. This allows you to customize the rendered OpenAPI schema after we have both processed it.\n\n##### override object\n\nThis does a naive merge of the override object with the rendered OpenAPI schema. This is useful for simple overrides where you want to add or modify properties without complex logic.\n\n```typescript\nz.string.datetime().meta({\n  description: 'A date field',\n  override: {\n    format: 'MY-FORMAT',\n  },\n});\n```\n\n##### override function\n\nThe `override` function allows you to deeply customize the rendered OpenAPI schema. Eg. if you wanted to render a Zod union as a `oneOf` instead of `anyOf` for a single schema, you can do so by using the `override` function. View the documentation for `override` in the [CreateDocumentOptions](#createdocumentoptions) section for more information.\n\n```typescript\nz.union([z.string(), z.number()]).meta({\n  description: 'A union of string and number',\n  override: ({ jsonSchema }) =\u003e {\n    jsonSchema.anyOf = jsonSchema.oneOf;\n    delete jsonSchema.oneOf;\n  },\n});\n```\n\n### `createDocument`\n\nGenerates an OpenAPI documentation object.\n\n```typescript\nimport * as z from 'zod/v4';\n// or import * as z from 'zod'; if using Zod 4.0.0+\n\nimport { createDocument } from 'zod-openapi';\n\nconst jobId = z.string().meta({\n  description: 'A unique identifier for a job',\n  example: '12345',\n  id: 'jobId',\n});\n\nconst title = z.string().meta({\n  description: 'Job title',\n  example: 'My job',\n});\n\nconst document = createDocument({\n  openapi: '3.1.0',\n  info: {\n    title: 'My API',\n    version: '1.0.0',\n  },\n  paths: {\n    '/jobs/{jobId}': {\n      put: {\n        requestParams: { path: z.object({ jobId }) },\n        requestBody: {\n          content: {\n            'application/json': { schema: z.object({ title }) },\n          },\n        },\n        responses: {\n          '200': {\n            description: '200 OK',\n            content: {\n              'application/json': { schema: z.object({ jobId, title }) },\n            },\n          },\n        },\n      },\n    },\n  },\n});\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eCreates the following object:\u003c/summary\u003e\n  \n  ```json\n  {\n    \"openapi\": \"3.1.0\",\n    \"info\": {\n      \"title\": \"My API\",\n      \"version\": \"1.0.0\"\n    },\n    \"paths\": {\n      \"/jobs/{jobId}\": {\n        \"put\": {\n          \"parameters\": [\n            {\n              \"in\": \"path\",\n              \"name\": \"jobId\",\n              \"description\": \"A unique identifier for a job\",\n              \"schema\": {\n                \"$ref\": \"#/components/schemas/jobId\"\n              }\n            }\n          ],\n          \"requestBody\": {\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"type\": \"object\",\n                  \"properties\": {\n                    \"title\": {\n                      \"type\": \"string\",\n                      \"description\": \"Job title\",\n                      \"example\": \"My job\"\n                    }\n                  },\n                  \"required\": [\"title\"]\n                }\n              }\n            }\n          },\n          \"responses\": {\n            \"200\": {\n              \"description\": \"200 OK\",\n              \"content\": {\n                \"application/json\": {\n                  \"schema\": {\n                    \"type\": \"object\",\n                    \"properties\": {\n                      \"jobId\": {\n                        \"$ref\": \"#/components/schemas/jobId\"\n                      },\n                      \"title\": {\n                        \"type\": \"string\",\n                        \"description\": \"Job title\",\n                        \"example\": \"My job\"\n                      }\n                    },\n                    \"required\": [\"jobId\", \"title\"]\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n    },\n    \"components\": {\n      \"schemas\": {\n        \"jobId\": {\n          \"type\": \"string\",\n          \"description\": \"A unique identifier for a job\",\n          \"example\": \"12345\"\n        }\n      }\n    }\n  }\n  ```\n\u003c/details\u003e\n\n`createDocument` takes an optional options argument which can be used to modify how the document is created\n\n```typescript\ncreateDocument(doc, {\n  override: ({ jsonSchema, zodSchema, io }) =\u003e {\n    const def = zodSchema._zod.def;\n    if (def.type === 'date' \u0026\u0026 io === 'output') {\n      jsonSchema.type = 'string';\n      jsonSchema.format = 'date-time';\n    }\n  },\n  allowEmptySchema: {\n    custom: true,\n  },\n});\n```\n\n#### CreateDocumentOptions\n\n| Option             | Type                | Description                                                                                                                               |\n| ------------------ | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |\n| `override`         | `Function`          | Override rendered schema with a function``                                                                                                |\n| `outputIdSuffix`   | `string`            | Suffix for output schema IDs when the schema is used in both a request and response. Defaults to ``'Output'`                              |\n| `allowEmptySchema` | `Object`            | Control whether empty schemas are allowed for specific Zod schema types                                                                   |\n| `cycles`           | `'ref' \\| 'throw'`  | How to handle cycles in schemas.\u003cbr\u003e- `'ref'` — Break cycles using $defs\u003cbr\u003e- `'throw'` — Error on cycles. Defaults to `'ref'`            |\n| `reused`           | `'ref' \\| 'inline'` | How to handle reused schemas.\u003cbr\u003e- `'ref'` — Reused schemas as references\u003cbr\u003e- `'inline'` — Inline reused schemas. Defaults to `'inline'` |\n|                    |\n\n##### `override`\n\nThe `override` function allows you to customize the rendered OpenAPI schema. It receives an object with the following properties:\n\n| Property     | Type                  | Description                                                                                                       |\n| ------------ | --------------------- | ----------------------------------------------------------------------------------------------------------------- |\n| `jsonSchema` | `Object`              | The OpenAPI schema object being generated. You can modify this object to change the rendered schema.              |\n| `zodSchema`  | `ZodType`             | The original Zod schema being converted to OpenAPI. You can use this to access Zod-specific properties.           |\n| `io`         | `'input' \\| 'output'` | The context in which the schema is being rendered. `'input'` for request bodies/params, `'output'` for responses. |\n\nThis allows you to transform the schema based on your own rules or requirements. For example, if you\n\n1. Wanted to change how dates are rendered in the output context because a typical JSON serializer will transform them to a string\n2. Change all union outputs to be oneOf instead of anyOf\n\n```typescript\ncreateDocument(doc, {\n  override: ({ jsonSchema, zodSchema, io }) =\u003e {\n    const def = zodSchema._zod.def;\n    if (def.type === 'date' \u0026\u0026 io === 'output') {\n      jsonSchema.type = 'string';\n      jsonSchema.format = 'date-time';\n      return;\n    }\n    if (def.type === 'union') {\n      jsonSchema.oneOf = jsonSchema.anyOf;\n      delete jsonSchema.anyOf;\n      return;\n    }\n  },\n});\n```\n\n##### `outputIdSuffix`\n\nThe `outputIdSuffix` option allows you to set a suffix for output schema IDs when the schema is used in both a request and response context. This is useful for distinguishing between input and output schemas.\n\n##### `allowEmptySchema`\n\nThe `allowEmptySchema` option allows you to control whether or not this library will throw when it encounters an empty schema. By default this library will not throw if it encounters an `z.any()` or `z.unknown()` schema.\n\nThis allows you to customize how this library handles [unrepresentable](https://zod.dev/json-schema?id=unrepresentable) Zod schemas.\n\neg. If you wanted to allow `z.custom()` to be rendered as an empty schema, you can set the `allowEmptySchema` option as follows:\n\n```typescript\ncreateDocument(doc, {\n  allowEmptySchema: {\n    custom: true, // Allow empty schemas for `z.custom()` in all contexts\n    set: { output: true }, // Allow empty schemas for `z.set()` only in an output context\n  },\n});\n```\n\n##### `cycles` and `reused`\n\nThese options are exposed directly from the Zod. Read the [documentation](https://zod.dev/json-schema?id=unrepresentable#cycles) for more information on how to use these options.\n\n#####\n\n### `createSchema`\n\nCreates an OpenAPI Schema Object along with any registered components. OpenAPI 3.1.0 Schema Objects are fully compatible with JSON Schema.\n\n```typescript\nimport * as z from 'zod/v4';\nimport { createSchema } from 'zod-openapi';\n\nconst jobId = z.string().meta({\n  description: 'A unique identifier for a job',\n  example: '12345',\n  id: 'jobId',\n});\n\nconst title = z.string().meta({\n  description: 'Job title',\n  example: 'My job',\n});\n\nconst job = z.object({\n  jobId,\n  title,\n});\n\nconst { schema, components } = createSchema(job);\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eCreates the following object:\u003c/summary\u003e\n  \n  ```json\n  {\n    \"schema\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"jobId\": {\n          \"$ref\": \"#/components/schemas/jobId\"\n        },\n        \"title\": {\n          \"type\": \"string\",\n          \"description\": \"Job title\",\n          \"example\": \"My job\"\n        }\n      },\n      \"required\": [\"jobId\", \"title\"]\n    },\n    \"components\": {\n      \"jobId\": {\n        \"type\": \"string\",\n        \"description\": \"A unique identifier for a job\",\n        \"example\": \"12345\"\n      }\n    }\n  }\n  ```\n\u003c/details\u003e\n\n#### CreateSchemaOptions\n\n`createSchema` takes an optional `CreateSchemaOptions` parameter which includes all options from [CreateDocumentOptions](#createdocumentoptions) plus the following:\n\n```typescript\nconst { schema, components } = createSchema(job, {\n  // Input/Output context - controls how schemas are generated\n  io: 'input', // 'input' for request bodies/params, 'output' for responses\n  // Component handling\n  schemaComponents: { jobId: z.string() }, // Pre-defined components to use\n  schemaComponentRefPath: '#/definitions/', // Custom path prefix for component references\n  opts: {}, // Create Document Options,\n});\n```\n\n### Request Parameters\n\nQuery, Path, Header \u0026 Cookie parameters can be created using the `requestParams` key under the `method` key as follows:\n\n```typescript\ncreateDocument({\n  paths: {\n    '/jobs/{a}': {\n      put: {\n        requestParams: {\n          path: z.object({ a: z.string() }),\n          query: z.object({ b: z.string() }),\n          cookie: z.object({ cookie: z.string() }),\n          header: z.object({ 'custom-header': z.string() }),\n        },\n      },\n    },\n  },\n});\n```\n\nIf you would like to declare parameters in a more traditional way you may also declare them using the [parameters](https://swagger.io/docs/specification/describing-parameters/) key. The definitions will then all be combined.\n\n```ts\ncreateDocument({\n  paths: {\n    '/jobs/{a}': {\n      put: {\n        parameters: [\n          z.string().meta({\n            param: {\n              name: 'job-header',\n              in: 'header',\n            },\n          }),\n        ],\n      },\n    },\n  },\n});\n```\n\n### Request Body\n\nWhere you would normally declare the [media type](https://swagger.io/docs/specification/media-types/), set the `schema` as your Zod Schema as follows.\n\n```typescript\ncreateDocument({\n  paths: {\n    '/jobs': {\n      get: {\n        requestBody: {\n          content: {\n            'application/json': { schema: z.object({ a: z.string() }) },\n          },\n        },\n      },\n    },\n  },\n});\n```\n\nIf you wish to use OpenAPI syntax for your schemas, simply add an OpenAPI schema to the `schema` field instead.\n\n### Responses\n\nSimilarly to the [Request Body](#request-body), simply set the `schema` as your Zod Schema as follows. You can set the response headers using the `headers` key.\n\n```typescript\ncreateDocument({\n  paths: {\n    '/jobs': {\n      get: {\n        responses: {\n          200: {\n            description: '200 OK',\n            content: {\n              'application/json': { schema: z.object({ a: z.string() }) },\n            },\n            headers: z.object({\n              'header-key': z.string(),\n            }),\n          },\n        },\n      },\n    },\n  },\n});\n```\n\n### Callbacks\n\n```typescript\ncreateDocument({\n  paths: {\n    '/jobs': {\n      get: {\n        callbacks: {\n          onData: {\n            '{$request.query.callbackUrl}/data': {\n              post: {\n                requestBody: {\n                  content: {\n                    'application/json': { schema: z.object({ a: z.string() }) },\n                  },\n                },\n                responses: {\n                  200: {\n                    description: '200 OK',\n                    content: {\n                      'application/json': {\n                        schema: z.object({ a: z.string() }),\n                      },\n                    },\n                  },\n                },\n              },\n            },\n          },\n        },\n      },\n    },\n  },\n});\n```\n\n### Creating Components\n\nOpenAPI allows you to define reusable [components](https://swagger.io/docs/specification/components/) and this library allows you to replicate that in two separate ways.\n\n1. Auto registering schema\n2. Manually registering schema\n\n#### Schema\n\nIf we take the example in `createDocument` and instead create `title` as follows\n\n##### Auto Registering Schema\n\n```typescript\nconst title = z.string().meta({\n  description: 'Job title',\n  example: 'My job',\n  id: 'jobTitle', // \u003c- new field\n});\n```\n\nWherever `title` is used in schemas across the document, it will instead be created as a reference.\n\n```json\n{ \"$ref\": \"#/components/schemas/jobTitle\" }\n```\n\n`title` will then be outputted as a schema within the components section of the documentation.\n\n```json\n{\n  \"components\": {\n    \"schemas\": {\n      \"jobTitle\": {\n        \"type\": \"string\",\n        \"description\": \"Job title\",\n        \"example\": \"My job\"\n      }\n    }\n  }\n}\n```\n\nThis is a great way to create less repetitive Open API documentation. There are some Open API features like [discriminator mapping](https://swagger.io/docs/specification/data-models/inheritance-and-polymorphism/) which require all schemas in the union to contain a ref.\n\n##### Manually Registering Schema\n\nAnother way to register schema instead of adding a `ref` is to add it to the components directly. This will still work in the same way as `ref`. So whenever we run into that Zod type we will replace it with a reference.\n\neg.\n\n```typescript\nconst title = z.string().meta({\n  description: 'Job title',\n  example: 'My job',\n});\ncreateDocument({\n  components: {\n    schemas: {\n      jobTitle: title, // this will register this Zod Schema as jobTitle unless `id` in `.meta()` is specified on the type\n    },\n  },\n});\n```\n\n#### Parameters\n\nQuery, Path, Header \u0026 Cookie parameters can be similarly registered:\n\n```typescript\n// Easy auto registration\nconst jobId = z.string().meta({\n  description: 'Job ID',\n  example: '1234',\n  param: { id: 'jobRef' },\n});\n\ncreateDocument({\n  paths: {\n    '/jobs/{jobId}': {\n      put: {\n        requestParams: {\n          header: z.object({\n            jobId,\n          }),\n        },\n      },\n    },\n  },\n});\n\n// or more verbose auto registration\nconst jobId = z.string().meta({\n  description: 'Job ID',\n  example: '1234',\n  param: { in: 'header', name: 'jobId', id: 'jobRef' },\n});\n\ncreateDocument({\n  paths: {\n    '/jobs/{jobId}': {\n      put: {\n        parameters: [jobId],\n      },\n    },\n  },\n});\n\n// or manual registration\nconst otherJobId = z.string().meta({\n  description: 'Job ID',\n  example: '1234',\n  param: { in: 'header', name: 'jobId' },\n});\n\ncreateDocument({\n  components: {\n    parameters: {\n      jobRef: jobId,\n    },\n  },\n});\n```\n\n#### Response Headers\n\nResponse headers can be similarly registered:\n\n```typescript\nconst header = z.string().meta({\n  description: 'Job ID',\n  example: '1234',\n  header: { id: 'some-header' },\n});\n\n// or\n\nconst jobIdHeader = z.string().meta({\n  description: 'Job ID',\n  example: '1234',\n});\n\ncreateDocument({\n  components: {\n    headers: {\n      someHeaderRef: jobIdHeader,\n    },\n  },\n});\n```\n\n#### Responses\n\nEntire Responses can also be registered\n\n```typescript\nconst response: ZodOpenApiResponseObject = {\n  description: '200 OK',\n  content: {\n    'application/json': {\n      schema: z.object({ a: z.string() }),\n    },\n  },\n  id: 'some-response',\n};\n\n//or\n\nconst response: ZodOpenApiResponseObject = {\n  description: '200 OK',\n  content: {\n    'application/json': {\n      schema: z.object({ a: z.string() }),\n    },\n  },\n};\n\ncreateDocument({\n  components: {\n    responses: {\n      'some-response': response,\n    },\n  },\n});\n```\n\n#### Callbacks\n\nCallbacks can also be registered\n\n```typescript\nconst callback: ZodOpenApiCallbackObject = {\n  id: 'some-callback'\n  post: {\n    responses: {\n      200: {\n        description: '200 OK',\n        content: {\n          'application/json': {\n            schema: z.object({ a: z.string() }),\n          },\n        },\n      },\n    },\n  },\n};\n\n//or\n\nconst callback: ZodOpenApiCallbackObject = {\n  post: {\n    responses: {\n      200: {\n        description: '200 OK',\n        content: {\n          'application/json': {\n            schema: z.object({ a: z.string() }),\n          },\n        },\n      },\n    },\n  },\n};\n\ncreateDocument({\n  components: {\n    callbacks: {\n      'some-callback': callback,\n    },\n  },\n});\n```\n\n#### Path Items\n\nPath Items can also be registered\n\n```typescript\nconst pathItem: ZodOpenApiPathItemObject = {\n  id: 'some-path-item',\n  get: {\n    responses: {\n      200: {\n        description: '200 OK',\n        content: {\n          'application/json': {\n            schema: z.object({ a: z.string() }),\n          },\n        },\n      },\n    },\n  },\n};\n\n// or\n\ncreateDocument({\n  components: {\n    pathItems: {\n      'some-path-item': pathItem,\n    },\n  },\n});\n```\n\n#### Security Schemes\n\nSecurity Schemes can be registered for authentication methods:\n\n```typescript\ncreateDocument({\n  components: {\n    securitySchemes: {\n      bearerAuth: {\n        type: 'http',\n        scheme: 'bearer',\n        bearerFormat: 'JWT',\n        description: 'JWT Authentication',\n      },\n    },\n  },\n});\n```\n\n#### Links\n\nLinks can be registered to describe relationships between operations:\n\n```typescript\nconst link: ZodOpenApiLinkObject = {\n  id: 'getUserById',\n  operationId: 'getUser',\n  parameters: {\n    userId: '$request.path.id',\n  },\n  description: 'Link to get user by id',\n};\n\n// or\n\ncreateDocument({\n  components: {\n    links: {\n      getUserById: {\n        operationId: 'getUser',\n        parameters: {\n          userId: '$request.path.id',\n        },\n        description: 'Link to get user by id',\n      },\n    },\n  },\n});\n```\n\n#### Examples\n\nExamples can be registered to provide sample values for schemas:\n\n```typescript\nconst example: ZodOpenApiExampleObject = {\n  id: 'userExample',\n  summary: 'A sample user',\n  value: {\n    id: '123',\n    name: 'Jane Doe',\n    email: 'jane@example.com',\n  },\n};\n\n// or\n\ncreateDocument({\n  components: {\n    examples: {\n      userExample: {\n        summary: 'A sample user',\n        value: {\n          id: '123',\n          name: 'Jane Doe',\n          email: 'jane@example.com',\n        },\n      },\n    },\n  },\n});\n```\n\n### Zod Types\n\nZod types are composed of two different parts: the input and the output. This library decides which type to create based on if it is used in a request or response context.\n\nInput:\n\n- Request Parameters (query, path, header, cookie)\n- Request Body\n\nOutput:\n\n- Response Body\n- Response Headers\n\nIn general, you want to avoid using a registered input schema in an output context and vice versa. This is because the rendered input and output schemas of a simple Zod schema will differ, even with a simple Zod schema like `z.object()`.\n\n```typescript\nconst schema = z.object({\n  name: z.string(),\n});\n```\n\nInput schemas (request bodies, parameters):\n\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"name\": {\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\"name\"]\n}\n```\n\nOutput schemas (responses):\n\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"name\": {\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\"name\"],\n  \"additionalProperties\": false\n}\n```\n\nWhen the same schema is referenced in both input and output contexts, the library generates two separate component schemas. This happens automatically when a schema with an ID is used in both contexts.\n\nYou can customize the output schema name by providing an `outputId`:\n\n```ts\nconst schema = z\n  .object({\n    name: z.string(),\n  })\n  .meta({\n    id: 'MyObject',\n    outputId: 'MyObjectResponse', // Customize the output schema name\n  });\n```\n\nYou can also set a global suffix for output schemas or use `z.looseObject()` and `z.strictObject()` to have explicit control over the schema behavior.\n\n\u003e **⚠️ Note:** If your registered schema contains dynamically created lazy components, they won't be reused between input and output schemas.\n\n## Supported OpenAPI Versions\n\nCurrently the following versions of OpenAPI are supported\n\n- `3.1.0` (minimum version)\n- `3.1.1`\n\nSetting the `openapi` field will change how the some of the components are rendered.\n\n```ts\ncreateDocument({\n  openapi: '3.1.0',\n});\n```\n\nAs an example `z.string().nullable()` will be rendered differently\n\n`3.0.0`\n\n```json\n{\n  \"type\": \"string\",\n  \"nullable\": true\n}\n```\n\n`3.1.0`\n\n```json\n{\n  \"type\": [\"string\", \"null\"]\n}\n```\n\n## Examples\n\nSee the library in use in the [examples](./examples/) folder.\n\n- Simple - [setup](./examples/simple/createSchema.ts) | [openapi.yml](./examples/simple/openapi.yml) | [redoc documentation](https://samchungy.github.io/zod-openapi/examples/simple/redoc-static.html)\n\n## Ecosystem\n\n- [fastify-zod-openapi](https://github.com/samchungy/fastify-zod-openapi) - Fastify plugin for zod-openapi. This includes type provider, Zod schema validation, Zod schema serialization and Swagger UI support.\n\n- [eslint-plugin-zod-openapi](https://github.com/samchungy/eslint-plugin-zod-openapi) - Eslint rules for zod-openapi. This includes features which can autogenerate Typescript comments for your Zod types based on your `description`, `example` and `deprecated` fields.\n\n## Version Information\n\nFor information about changes and migration from v4 to v5, see the [v5 migration guide](./docs/v5.md).\n\n## Development\n\n### Prerequisites\n\n- Node.js LTS\n- pnpm\n\n```shell\npnpm\npnpm build\n```\n\n### Test\n\n```shell\npnpm test\n```\n\n### Lint\n\n```shell\n# Fix issues\npnpm format\n\n# Check for issues\npnpm lint\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamchungy%2Fzod-openapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamchungy%2Fzod-openapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamchungy%2Fzod-openapi/lists"}