01Start
Introduction
What swaggerz is, what it generates, and when another tool is the better fit.
swaggerz is a compiler. Its input is an API description: Swagger 2.0, or OpenAPI 3.0, 3.1 or 3.2, optionally patched by OpenAPI Overlays. Its output is the TypeScript or JavaScript client you would have written by hand: one function per operation, one type per model, typed errors, and nothing you do not import.
The generated code lives in your repository and has no dependency on swaggerz. You can read it, debug it and step through it; swaggerz is only a development dependency.
What you get
Section titled “What you get”- A function per operation, taking one
paramsobject, resolving with typed data and rejecting with errors typed per HTTP status. - A type per model, with documentation from the specification, separate request and response types where
readOnlyandwriteOnlydiffer, andDatevalues if you want them. - A small runtime in the client itself: URL building, parameter and body serialization (every style OpenAPI defines), authentication, middleware, retries and token refresh, over
fetchoraxios. - Optionally, TanStack Query hooks for React, Vue, Svelte and Solid, or SWR hooks, and Zod, Valibot or ArkType schemas that validate responses at runtime.
- Tools around the client: a linter for what makes the client worse, a local dashboard, and an MCP server that gives coding agents the exact generated functions.
How it is different
Section titled “How it is different”It is a compiler, not a template. Every specification version has its own adapter into one intermediate representation, so a Swagger 2.0 document and an OpenAPI 3.2 one produce the same kind of code, and features the client cannot represent are reported as diagnostics with a location instead of being silently dropped. The pipeline page shows the stages.
Every operation is its own module. There is no class per tag and no registry of endpoints, so bundlers keep only the operations an application imports, measured with esbuild, Rollup, Vite and webpack on tree-shaking.
Regeneration is safe. The same input gives byte-identical output, unchanged files are not rewritten, and files the generator does not own are never overwritten or deleted. See determinism and safety.
When to use something else
Section titled “When to use something else”- You want types only, and call the API by path with a thin fetch wrapper: openapi-typescript generates one declaration file and stays out of your runtime.
- You need server code: swaggerz generates clients. For webhooks and callbacks it generates handler types, but no routing or server stubs.
- You need a language other than TypeScript or JavaScript: openapi-generator covers dozens.
- Your API is not described by Swagger or OpenAPI: GraphQL, gRPC and AsyncAPI have their own generators.
What it looks like
Section titled “What it looks like”A specification on the left, the code swaggerz generates for it on the right. Hover a line on either side to see its counterpart.
openapi: 3.1.0info: title: Petstore version: '1.0'servers: - url: https://petstore.example.com/v1paths: /pets/{petId}: get: tags: [pets] summary: Find a pet by ID. description: Returns a single pet. operationId: getPetById parameters: - name: petId in: path required: true description: ID of the pet to return. schema: type: integer format: int64 minimum: 1 responses: '200': description: The pet. content: application/json: schema: $ref: '#/components/schemas/Pet' '404': description: No pet has this ID. content: application/json: schema: $ref: '#/components/schemas/Error' security: - api_key: []components: securitySchemes: api_key: type: apiKey in: header name: X-API-Key schemas: Pet: type: object required: [id, name] properties: id: type: integer format: int64 name: type: string example: Rex status: type: string description: Where the pet is in the store. enum: [available, pending, sold] Error: type: object required: [message] properties: message: type: stringpets/get-pet-by-id.ts
/* eslint-disable */// @generated by swaggerz. Do not edit: this file is overwritten on the next generation.
import { type RequestOptions, client } from '../client.js';import type { Error as ErrorModel } from '../models/error.js';import type { Pet } from '../models/pet.js';import { type ApiError, type RequestError, isApiError } from '../runtime/errors.js';import type { HttpStatus } from '../runtime/types.js';
/** Parameters of {@link getPetById}. */export type GetPetByIdParams = { /** * ID of the pet to return. * * @format int64 * @minimum 1 */ petId: number;};
/** Response data of {@link getPetById}. */export type GetPetByIdResponse = Pet;
/** Body of an error response of {@link getPetById}. */export type GetPetByIdErrorBody = ErrorModel;
/** * The `ApiError`s {@link getPetById} rejects with: one per documented status, so checking `status` narrows `body`. * * The last member covers statuses the specification does not document. */export type GetPetByIdApiError = | ApiError<ErrorModel, 404> | ApiError<unknown, Exclude<HttpStatus<1 | 3 | 4 | 5>, 404>>;
/** Everything {@link getPetById} rejects with: an `ApiError` for an error status, or a `RequestError` when no usable response arrived. */export type GetPetByIdError = GetPetByIdApiError | RequestError;
/** * Find a pet by ID. * * Returns a single pet. * * @remarks `GET /pets/{petId}` (operationId `getPetById`) * @param params - Request parameters. * @param options - Per-request options: `signal`, `timeout`, `headers`, `client`. * @returns `200` The pet * @throws {@link ApiError} `404` No pet has this ID; narrow it with {@link isGetPetByIdApiError}. * @throws {@link RequestError} When no usable response is received (network failure, timeout or invalid body). */export function getPetById(params: GetPetByIdParams, options?: RequestOptions): Promise<GetPetByIdResponse> { return (options?.client ?? client).request<GetPetByIdResponse>( { operationId: 'getPetById', method: 'GET', path: '/pets/{petId}', pathParams: { petId: params.petId }, accept: 'application/json', security: [['api_key']], }, options, );}
/** Whether `error` is an `ApiError` rejected by {@link getPetById}. It narrows to {@link GetPetByIdApiError}, so checking `status` afterwards narrows `body` too. */export function isGetPetByIdApiError(error: unknown): error is GetPetByIdApiError { return ( isApiError(error) && error.operationId === 'getPetById' && error.method === 'GET' );}models/pet.ts
/* eslint-disable */// @generated by swaggerz. Do not edit: this file is overwritten on the next generation.
export type Pet = { /** @format int64 */ id: number; /** @example "Rex" */ name: string; /** Where the pet is in the store. */ status?: 'available' | 'pending' | 'sold';};Next: generate a client for your API in the quick start.