Skip to content

Validated at runtime, not just typed at compile time.

Generate types, a fetch client, React Query hooks, and Zod schemas from one spec. Opt into Zod and the generated client validates every request and response body at runtime, so bad data fails at the boundary, not three components deep.
Install npm install -D @codewithagents/openapi-gen

Tested against 128 real-world specs (Stripe, GitHub, Spotify, OpenAI) in CI on every commit.


Real output from the Petstore 3.0 spec, generated by the toolchain and committed to the repo. This is what CI compiles on every PR.

// client.ts — auto-generated by @codewithagents/openapi-gen
import type { Pet, Order } from './models.js'
import { getConfig, type ClientConfig } from './client-config.js'
import { z } from 'zod'
import { PetSchema, OrderSchema } from './schemas.js'
export class ApiError extends Error {
constructor(
public readonly status: number,
public readonly body: unknown
) {
super(`API error ${status}`)
this.name = 'ApiError'
}
}
// Validates both request and response bodies at runtime against Zod schemas.
export async function addPet(body: Pet, config?: Partial<ClientConfig>): Promise<Pet> {
PetSchema.parse(body)
const res = await _request('POST', '/pet', { body }, config)
return PetSchema.parse(await res.json())
}
export async function findPetsByStatus(
params: { status: 'available' | 'pending' | 'sold' },
config?: Partial<ClientConfig>
): Promise<Pet[]> {
const searchParams = new URLSearchParams()
if (params?.status != null) searchParams.set('status', String(params.status))
const res = await _request('GET', '/pet/findByStatus', { searchParams }, config)
return z.array(PetSchema).parse(await res.json())
}

Generates clean, type-safe code from real-world specs like:

  • Stripe
  • GitHub
  • Spotify
  • OpenAI
  • Adyen
  • + 123 more in CI

Each package is independent, but they compose. A single OpenAPI spec drives everything from server contract to form field error UX.

The CodeWithAgents OpenAPI package pipeline An OpenAPI spec feeds openapi-gen, which produces TypeScript types, Zod schemas, and a fetch client. The fetch client feeds openapi-react-query for React Query hooks and openapi-server for a typed service interface and router. api-errors is a runtime package that maps any API error shape to form field errors. OpenAPI spec openapi-gen TypeScript types models.ts Zod schemas yours to extend Fetch client client.ts openapi-react-query React Query v5 hooks openapi-server service interface + router api-errors Runtime, no codegen. Maps any API error shape to form fields.

One source of truth. When the spec changes, re-run the generators and the compiler tells you exactly what broke.


@codewithagents/openapi-gen

Types, fetch client, and Zod schemas from your OpenAPI spec. Learn more

@codewithagents/openapi-react-query

React Query v5 hooks, generated. Learn more

@codewithagents/openapi-server

Typed service interface and optional router for Hono, Express, or Fastify. Learn more

@codewithagents/api-errors

Map API errors to form field errors. Learn more


Validated, not just typed

Generate Zod schemas from your spec, then enable runtime validation with one config field (input_schema). The fetch client checks both request and response bodies against your schemas, so bugs surface at the boundary, not deep in your UI.

Proven on 128 real specs

Stripe, GitHub, Spotify, OpenAI, Adyen, AWS, and more. Every spec is generated and compiled in CI on every commit. Not benchmarked once and forgotten.

Code you own

Output is plain TypeScript files in your repo. No runtime black box, no proprietary client to call into. Adjust, extend, delete. The compiler is your upgrade guide.

OpenAPI 3.1 first-class

Full support for $ref, allOf, anyOf, oneOf, nullable, and 3.1.1 keyword changes. 3.0.x is supported in practice: 8 of our 13 showcase specs are 3.0.x and all compile. A few 3.0-only constructs like nullable are not yet normalized to 3.1 semantics. No Swagger 2.0.

Native fetch. Zero added bundle weight.

The generated client uses only native fetch. No axios, no wrapper libraries. Nothing from the codegen packages ends up in your bundle.

ESM, strict mode, Prettier-ready

Every generated file compiles with strict: true and "type": "module". Output passes prettier --check with your own config.


  1. Install the generator.

    Terminal window
    npm install -D @codewithagents/openapi-gen

    For React Query hooks, also add:

    Terminal window
    npm install -D @codewithagents/openapi-react-query && npm install @tanstack/react-query
  2. Create a config file in your project root.

    {
    "input_openapi": "./openapi.json",
    "output": "./src/api"
    }

    Point input_openapi at your spec (JSON or YAML, local path or URL). The output directory is created automatically.

  3. Run the generator and import the output.

    Terminal window
    npx openapi-gen

    Then use the generated barrel directly:

    import { configureClient, getPetById, useFindPetsByStatus } from './src/api'
    configureClient({ baseUrl: 'https://petstore3.swagger.io/api/v3' })
    const pet = await getPetById('1')
    const { data, isLoading } = useFindPetsByStatus({ status: 'available' })



Quickstart

Go from a spec file to a working typed client in five minutes. Read the quickstart

GitHub

Source code, issues, and the compatibility matrix across 128 specs. View on GitHub