Quickstart
Full walkthrough of installing and running the generator from scratch.
This guide is for developers who already have a TypeScript project with an OpenAPI generator set up and want to switch to openapi-zod-ts. It covers the mental model shift, the step-by-step switch, and what to watch for.
Many OpenAPI generators follow a pattern where the generated code depends on a runtime client library that the generator itself publishes. Your code calls into that runtime, and the generated types describe its API. The generator ships a package to dependencies, not just devDependencies.
This toolchain works differently:
models.ts, client.ts, client-config.ts, and (optionally) schemas.ts live in your repository. They are plain TypeScript you can read, extend, and commit like any other file.openapi-zod-ts) is a devDependency. The generated client.ts uses only native fetch. Nothing is added to your production bundle that your project did not already have.input_schema to your config, the generator bootstraps a Zod schemas.ts file once, then never overwrites it. You add error messages and business rules. The generator warns on drift but your schema stays yours.Schema.parse(body) before sending and Schema.parse(await res.json()) after receiving.Remove the old generator.
Uninstall the previous generator and any runtime packages it required:
# example: remove hey-api packagesnpm uninstall @hey-api/client-fetch @hey-api/openapi-ts
# example: remove orvalnpm uninstall orvalDelete the old generated output directory and any existing generator config files (orval.config.ts, openapi-ts.config.ts, etc.).
Install openapi-zod-ts.
npm install -D openapi-zod-tsIf you also want React Query hooks, add the hooks package:
npm install -D @codewithagents/openapi-react-queryIf your old setup relied on MSW or Faker mocks (orval and kubb both ship mock
generation), add @codewithagents/openapi-msw. It generates MSW v2 handlers
with seeded Faker data from the same spec, so you do not lose mocking when you
switch:
npm install -D @codewithagents/openapi-mswCreate the config file.
Create openapi-zod-ts.config.json in your project root:
{ "input_openapi": "./openapi.json", "output": "./src/api"}Optional fields for a fuller setup:
{ "input_openapi": "./openapi.json", "output": "./src/api", "input_schema": "./src/api/schemas.ts", "baseUrl": "https://api.example.com", "server_client": true}| Field | Required | Description |
|---|---|---|
input_openapi | Yes | Path to your OpenAPI spec (JSON or YAML) |
output | Yes | Directory to write the generated files |
input_schema | No | Path to a user-owned Zod schema file. Bootstrapped on first run, never overwritten after that. |
baseUrl | No | Default base URL embedded in client-config.ts |
server_client | No | When true, also generates server.ts with a createServerClient() factory |
Run the generator.
npx openapi-zod-tsThis writes the following files to your output directory:
| File | Contents |
|---|---|
models.ts | TypeScript interfaces for every schema |
client.ts | One typed async function per API operation |
client-config.ts | configureClient() and getConfig() |
index.ts | Barrel re-export of all three files above |
Update your imports.
Replace imports from the old generator’s runtime with imports from your generated barrel:
// Before: importing from a runtime packageimport { createClient } from '@hey-api/client-fetch'
// After: importing from your own generated codeimport { configureClient, listTasks, ApiError } from './src/api'Call configureClient once at app startup:
import { configureClient } from './src/api'
configureClient({ baseUrl: 'https://api.example.com', token: () => getAccessToken(), // sync or async, called per request})Add a generate script to package.json.
{ "scripts": { "generate": "openapi-zod-ts" }}// orval.config.ts (illustrative, your config may differ)import { defineConfig } from 'orval'
export default defineConfig({ myApi: { input: './openapi.json', output: { target: './src/api/client.ts', client: 'react-query', }, },})// package.json dependencies (illustrative){ "devDependencies": { "orval": "^7.x" }, "dependencies": { "axios": "^1.x" }}{ "input_openapi": "./openapi.json", "output": "./src/api"}{ "scripts": { "generate": "openapi-zod-ts" }, "devDependencies": { "openapi-zod-ts": "^2.0.0" }}int64 fields are now number, not bigintIn v1, fields with format: int64 generated bigint in TypeScript and z.bigint() in Zod schemas. In v2 they generate number and z.number().
The rationale: JSON.stringify throws when a value contains a bigint, and JSON.parse never produces a bigint. This makes bigint unworkable for any fetch-based API client. Precision is therefore limited to Number.MAX_SAFE_INTEGER (2^53-1), and the generated TypeScript type carries an inline comment to make that explicit:
export interface Order { id: number /* int64, precision limited to 2^53-1 */}How to fix your schemas.ts: The generator never overwrites schemas.ts, so any z.bigint() you wrote (or that v1 bootstrapped) for an int64 property will produce a TypeScript compile error against the regenerated number types. Find those fields and replace z.bigint() with z.number(), removing any BigInt(...) conversions at call sites.
// Before (v1)export const OrderSchema = z.object({ id: z.bigint(),})
// After (v2)export const OrderSchema = z.object({ id: z.number(),})Re-running the generator after upgrading picks up several typing improvements:
$ref are now typed as their actual inline object shape instead of Record<string, unknown>.number (#300): path parameters with type: integer or type: number are now number in the generated function signature instead of string.ids[] are typed number[] or string[] depending on the item schema, instead of always string.Accept: application/json header on all requests: every generated fetch call now sends Accept: application/json automatically.None of these change the runtime behavior of existing working calls, but regenerating will improve type safety and remove unnecessary casts.
Quickstart
Full walkthrough of installing and running the generator from scratch.
Types and fetch client
Complete configuration reference, generated file details, and advanced usage.
React Query hooks
Generate typed useQuery and useMutation hooks on top of the generated client.
Mock data with MSW
Generate MSW v2 handlers with seeded Faker data from the same spec. The replacement for orval or kubb mock generation.