Hey API: Your OpenAPI Spec Just Wrote Your Entire Frontend Client
Every frontend developer knows the ritual. The backend team ships a new API version, you open the Swagger docs, and you start the tedious work of updating your TypeScript interfaces, fetch functions, and validation schemas. Three hours later you discover a typo in a field name that broke everything. Hey API (@hey-api/openapi-ts) exists to make that entire process a single command.
@hey-api/openapi-ts is an OpenAPI-to-TypeScript code generator that produces production-ready SDKs, validation schemas, data-fetching hooks, and more from any valid OpenAPI specification. It powers projects at Vercel, PayPal, and OpenCode, and with nearly a million weekly downloads on npm, it has become the go-to tool for teams that refuse to let their frontend types drift out of sync with their backend contracts.
The Plugin Buffet
What sets Hey API apart from other OpenAPI generators is its plugin architecture. Instead of a monolithic output, you pick and choose exactly what you need from over 20 plugins organized across several categories:
- HTTP Clients: Fetch API, Axios, Ky, Next.js, Nuxt, Angular, and more
- Validators: Zod, Valibot, Ajv, Arktype, Joi, Yup, and others
- State Management: TanStack Query (React Query), SWR, Zustand, Pinia Colada
- Web Frameworks: Fastify, Express, Hono, Nest, Elysia, and more
- Mocking and Testing: MSW, Faker, Nock, Supertest
Need typed React Query hooks with Zod validation and a Fetch-based client? Enable three plugins. Just want TypeScript interfaces? Use the core type plugin alone. The architecture means you never carry code you do not need.
Getting Started
Install @hey-api/openapi-ts as a dev dependency alongside the runtime client of your choice:
npm install @hey-api/openapi-ts -D -E
npm install @hey-api/client-fetch
yarn add @hey-api/openapi-ts -D -E
yarn add @hey-api/client-fetch
You can also skip installation entirely and run it with npx for a quick test:
npx @hey-api/openapi-ts -i path/to/spec.json -o src/client
Add a convenience script to your package.json:
{
"scripts": {
"openapi-ts": "openapi-ts"
}
}
Wiring Up Your First Spec
The Configuration File
Create an openapi-ts.config.ts at your project root. This is where you tell Hey API what to generate:
import { defineConfig } from '@hey-api/openapi-ts';
export default defineConfig({
input: 'https://api.example.com/openapi.json',
output: 'src/client',
plugins: [
'@hey-api/typescript',
'@hey-api/sdk',
{
name: '@hey-api/client-fetch',
runtimeConfigPath: './src/api-config.ts',
},
],
});
The input field accepts a file path, a URL, or even an OpenAPI spec object. The output folder is where all generated code lands, and you should treat it as a dependency rather than editing it by hand.
Running the Generator
npm run openapi-ts
That single command reads your spec, runs every configured plugin, and writes fully typed TypeScript files to src/client. You get interfaces for every schema, an SDK with methods for every endpoint, and a configured HTTP client ready to make requests.
Using the Generated Client
import { client } from './client/sdk.gen';
const { data, error } = await client.getUsers({
query: { page: 1, limit: 20 },
});
if (data) {
// data is fully typed based on the OpenAPI response schema
console.log(data.users[0].email);
}
Every parameter, request body, and response type is inferred directly from the spec. Rename a field on the backend, regenerate, and the TypeScript compiler immediately flags every spot in your codebase that needs updating.
React Query Hooks in Seconds
Generating TanStack Query Integration
For React applications, the TanStack Query plugin is where Hey API truly shines. Add it to your config:
import { defineConfig } from '@hey-api/openapi-ts';
export default defineConfig({
input: './specs/api.yaml',
output: 'src/client',
plugins: [
'@hey-api/typescript',
'@hey-api/sdk',
'@hey-api/client-fetch',
'@tanstack/react-query',
],
});
After regeneration, you get ready-made hooks for every endpoint:
import { useGetUsersQuery, useCreateUserMutation } from './client/@tanstack/react-query.gen';
function UserList() {
const { data, isLoading } = useGetUsersQuery({
query: { page: 1 },
});
const createUser = useCreateUserMutation();
const handleCreate = () => {
createUser.mutate({
body: { name: 'Alice', email: 'alice@example.com' },
});
};
if (isLoading) return <p>Loading...</p>;
return (
<ul>
{data?.users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
No manual query key management, no hand-written fetch functions, no guessing at response types. The generated hooks handle caching, refetching, and error states through TanStack Query while keeping every type perfectly aligned with the spec.
Adding Runtime Validation with Zod
Stack the Zod plugin on top to get validation schemas that match your generated types:
import { defineConfig } from '@hey-api/openapi-ts';
export default defineConfig({
input: './specs/api.yaml',
output: 'src/client',
plugins: [
'@hey-api/typescript',
'@hey-api/sdk',
'@hey-api/client-fetch',
'@tanstack/react-query',
'zod',
],
});
The generated Zod schemas let you validate API responses at runtime, catching issues that static types alone cannot:
import { UserSchema } from './client/zod.gen';
const parsed = UserSchema.safeParse(unknownData);
if (parsed.success) {
console.log(parsed.data.email);
}
This is especially useful when consuming third-party APIs where you cannot fully trust the response shape.
Multi-Spec Workflows and CI Integration
Processing Multiple Specs
Real-world projects often consume more than one API. Hey API supports array-based configurations for running multiple jobs:
import { defineConfig } from '@hey-api/openapi-ts';
export default defineConfig([
{
input: 'https://auth.example.com/openapi.json',
output: 'src/clients/auth',
plugins: ['@hey-api/typescript', '@hey-api/sdk', '@hey-api/client-fetch'],
},
{
input: 'https://billing.example.com/openapi.json',
output: 'src/clients/billing',
plugins: ['@hey-api/typescript', '@hey-api/sdk', '@hey-api/client-fetch'],
},
]);
Each job gets its own output directory with fully isolated types and clients.
Programmatic API for CI Pipelines
For automated workflows, use the programmatic API directly:
import { createClient } from '@hey-api/openapi-ts';
async function generate() {
await createClient({
input: process.env.OPENAPI_SPEC_URL!,
output: 'src/client',
plugins: [
'@hey-api/typescript',
'@hey-api/sdk',
'@hey-api/client-fetch',
'@tanstack/react-query',
],
});
}
generate();
Drop this into a CI step that runs whenever the backend spec changes. Your pull request will include the regenerated client code, and reviewers can see exactly what changed in the generated types alongside any application code that needs updating.
Customizing the Parser
If your OpenAPI spec needs preprocessing, such as filtering out internal endpoints or patching inconsistencies, use the parser option:
import { defineConfig } from '@hey-api/openapi-ts';
export default defineConfig({
input: './specs/api.yaml',
output: 'src/client',
parser: {
// validate and modify the spec before generation
validate: true,
},
plugins: ['@hey-api/typescript', '@hey-api/sdk'],
});
How It Stacks Up
Hey API occupies a sweet spot in the OpenAPI tooling landscape. Compared to Orval, it offers more plugins and flexibility while Orval provides simpler, more opinionated defaults. Against openapi-typescript (by drwpow), Hey API generates full SDKs and hooks rather than just types. And unlike the Java-based OpenAPI Generator, it is TypeScript-native with a lighter toolchain and modern plugin system.
The breadth of the plugin ecosystem, spanning HTTP clients, validators, state management libraries, web frameworks, and mocking tools, is unmatched by any single competing project.
Wrapping Up
@hey-api/openapi-ts turns your OpenAPI specification into a complete, typed frontend toolkit with a single command. Whether you need just TypeScript interfaces or a full stack of React Query hooks, Zod schemas, and a configured HTTP client, the plugin architecture lets you generate exactly what your project demands and nothing more.
The days of manually syncing frontend types with backend contracts are over. Point Hey API at your spec, pick your plugins, and let the generator handle the rest. Your future self, staring at a breaking API change at 4 PM on a Friday, will thank you for it.