Skip to main content
The @hey-api/sdk plugin generates type-safe functions for each API operation in your OpenAPI specification. It works seamlessly with the TypeScript plugin to provide full type safety.

Installation

The SDK plugin is included when you install @hey-api/openapi-ts:
npm install @hey-api/openapi-ts --save-dev

Configuration

Add the plugin to your openapi-ts.config.ts:
import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
  input: './openapi.yaml',
  output: {
    path: './src/client',
  },
  plugins: [
    '@hey-api/typescript',
    '@hey-api/sdk',
  ],
});

What It Generates

The SDK plugin generates a sdk.gen.ts file containing type-safe functions for each API operation:
// sdk.gen.ts
import { client } from './client.gen';
import type { GetUsersData, GetUsersResponse, GetUsersErrors } from './types.gen';

export const getUsers = <ThrowOnError extends boolean = false>(
  parameters?: GetUsersData,
  options?: Options<never, ThrowOnError>
) => {
  return client.get<GetUsersResponse, GetUsersErrors, ThrowOnError>({
    url: '/users',
    ...options,
    ...parameters,
  });
};

export const createUser = <ThrowOnError extends boolean = false>(
  parameters: CreateUserData,
  options?: Options<never, ThrowOnError>
) => {
  return client.post<CreateUserResponse, CreateUserErrors, ThrowOnError>({
    url: '/users',
    ...options,
    ...parameters,
  });
};

Configuration Options

operations

Define the structure of generated SDK operations.
operations
string | object
default:"'flat'"
  • 'flat' - Standalone functions, no container (tree-shakeable)
  • 'byTags' - One class per operation tag
  • 'single' - All operations in a single class/container
  • Custom function for full control
{
  name: '@hey-api/sdk',
  operations: 'flat',
}
Generates standalone functions:
import { getUsers, createUser } from './sdk.gen';

const { data } = await getUsers();

Advanced Operations Configuration

operations.container
'class'
default:"'class'"
Type of container for grouped operations (currently only supports 'class').
operations.containerName
string | function | object
default:"'Sdk'"
Customize container names. For 'single' strategy, sets the root container name. For 'byTags', transforms tag names.
operations.methods
'instance' | 'static'
default:"'instance'"
  • 'instance' - Instance methods, requires instantiation: new ClassName()
  • 'static' - Static methods, no instantiation required: ClassName.method()
operations.nesting
'operationId' | 'id' | function
default:"'operationId'"
  • 'operationId' - Split operationId by delimiters (e.g., users.listUsers.list())
  • 'id' - Use operation id as-is, no nesting
  • Custom function for full control
operations.nestingDelimiters
RegExp
default:"/[.]/"
Delimiters for splitting operationId (only when nesting: 'operationId').
{
  name: '@hey-api/sdk',
  operations: {
    strategy: 'byTags',
    container: 'class',
    containerName: '{{name}}Api',
    methods: 'static',
    nesting: 'operationId',
    nestingDelimiters: /[./]/,
    methodName: '{{name}}',
    segmentName: '{{name}}',
  },
}

paramsStructure

Define how request parameters are structured in generated SDK methods.
paramsStructure
'grouped' | 'flat'
default:"'grouped'"
  • 'grouped' - Separates parameters by transport layer (body, query, path, header)
  • 'flat' - Merges all parameters into a single object
{
  name: '@hey-api/sdk',
  paramsStructure: 'grouped',
}
// Usage
await updateUser({
  path: { userId: '123' },
  body: { name: 'Jane' },
  query: { notify: true },
});

responseStyle

Note: This feature works only with the Fetch client. Define the shape of the return value from SDK calls.
responseStyle
'fields' | 'data'
default:"'fields'"
  • 'fields' - Returns multiple fields (data, error, response, etc.)
  • 'data' - Returns only the data field
{
  name: '@hey-api/sdk',
  responseStyle: 'fields',
}
const { data, error, response } = await getUsers();

if (error) {
  console.error(error);
} else {
  console.log(data);
}

client

Use an internal client instance to send HTTP requests.
client
string | boolean
default:"true"
  • true - Automatically choose the client from your defined plugins (defaults to @hey-api/client-fetch)
  • Client plugin name (e.g., '@hey-api/client-axios')
  • false - Don’t use an internal client
{
  name: '@hey-api/sdk',
  client: '@hey-api/client-axios',
}

auth

Include authentication mechanisms in generated functions.
auth
boolean
default:"true"
Disable if you’re handling auth yourself or defining it globally on the client.
{
  name: '@hey-api/sdk',
  auth: false, // Reduce generated code size
}

transformer

Transform response data before returning (e.g., convert ISO strings to Date objects).
transformer
string | boolean
default:"false"
  • true - Automatically choose transformer from your defined plugins
  • Transformer plugin name (e.g., '@hey-api/transformers')
  • false - No transformation
Transformation adds runtime overhead. Only use when necessary.
{
  name: '@hey-api/sdk',
  transformer: '@hey-api/transformers',
}

validator

Validate request and/or response data against schema.
validator
string | boolean | object
default:"false"
  • true - Automatically choose validator from your defined plugins
  • Validator plugin name (e.g., '@hey-api/zod')
  • Object with separate request and response validation settings
  • false - No validation
Validation adds runtime overhead. Only use when absolutely necessary.
{
  name: '@hey-api/sdk',
  validator: true, // Auto-detect validator plugin
}

examples

Generate code examples for SDK operations and attach them to the input source.
examples
boolean | object
default:"false"
Set to false to disable example generation entirely, or provide an object for fine-grained control.
{
  name: '@hey-api/sdk',
  examples: true,
}

Common Patterns

Basic API Client

import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
  input: './openapi.yaml',
  output: { path: './src/client' },
  plugins: [
    '@hey-api/typescript',
    '@hey-api/client-fetch',
    '@hey-api/sdk',
  ],
});

Class-Based SDK with Static Methods

import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
  input: './openapi.yaml',
  output: { path: './src/client' },
  plugins: [
    '@hey-api/typescript',
    '@hey-api/client-fetch',
    {
      name: '@hey-api/sdk',
      operations: {
        strategy: 'single',
        containerName: 'ApiClient',
        methods: 'static',
      },
    },
  ],
});
// Usage
import { ApiClient } from './client/sdk.gen';

const { data } = await ApiClient.getUsers();

Service-Based Architecture

import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
  input: './openapi.yaml',
  output: { path: './src/client' },
  plugins: [
    '@hey-api/typescript',
    '@hey-api/client-fetch',
    {
      name: '@hey-api/sdk',
      operations: {
        strategy: 'byTags',
        containerName: '{{name}}Service',
        methods: 'instance',
      },
    },
  ],
});
// Usage
import { UsersService, PostsService } from './client/sdk.gen';

const users = new UsersService();
const posts = new PostsService();

const { data: userData } = await users.list();
const { data: postData } = await posts.list();

Flat Structure with Validation

import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
  input: './openapi.yaml',
  output: { path: './src/client' },
  plugins: [
    '@hey-api/typescript',
    '@hey-api/client-fetch',
    '@hey-api/zod',
    {
      name: '@hey-api/sdk',
      operations: 'flat',
      paramsStructure: 'flat',
      validator: {
        request: '@hey-api/zod',
        response: false, // Skip response validation for performance
      },
    },
  ],
});

With Transformers

import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
  input: './openapi.yaml',
  output: { path: './src/client' },
  plugins: [
    '@hey-api/typescript',
    '@hey-api/client-fetch',
    '@hey-api/transformers',
    {
      name: '@hey-api/sdk',
      transformer: '@hey-api/transformers',
    },
  ],
});

Migration from Legacy Options

The following options are deprecated. Use the operations object instead.
Deprecated OptionNew Equivalent
asClass: trueoperations: { strategy: 'byTags' }
instance: trueoperations: { strategy: 'single', methods: 'instance' }
classNameBuilderoperations: { containerName }
methodNameBuilderoperations: { methodName }
operationId: trueoperations: { nesting: 'operationId' }
operationId: falseoperations: { nesting: 'id' }
classStructure: 'auto'operations: { nesting: 'operationId' }
classStructure: 'off'operations: { nesting: 'id' }

Next Steps

HTTP Clients

Choose an HTTP client for making requests.

Transformers

Transform response data at runtime.

Validators

Validate request and response data.

State Management

Integrate with TanStack Query or Pinia Colada.

Build docs developers (and LLMs) love