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:
Flat Functions (default)
Usage
// 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
Flat (default)
By Tags
Single Container
{
name : '@hey-api/sdk' ,
operations : 'flat' ,
}
Generates standalone functions: import { getUsers , createUser } from './sdk.gen' ;
const { data } = await getUsers ();
{
name : '@hey-api/sdk' ,
operations : {
strategy : 'byTags' ,
containerName : '{{name}}Service' ,
},
}
Generates classes based on tags: import { UsersService } from './sdk.gen' ;
const users = new UsersService ();
const { data } = await users . getUsers ();
{
name : '@hey-api/sdk' ,
operations : {
strategy : 'single' ,
containerName : 'ApiClient' ,
methods : 'instance' ,
},
}
Generates a single class: import { ApiClient } from './sdk.gen' ;
const api = new ApiClient ();
const { data } = await api . getUsers ();
Advanced Operations Configuration
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.list → Users.list())
'id' - Use operation id as-is, no nesting
Custom function for full control
operations.nestingDelimiters
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 },
});
{
name : '@hey-api/sdk' ,
paramsStructure : 'flat' ,
}
// Usage
await updateUser ({
userId: '123' , // path param
name: 'Jane' , // body param
notify: true , // query param
});
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
Fields (default)
Data Only
{
name : '@hey-api/sdk' ,
responseStyle : 'fields' ,
}
const { data , error , response } = await getUsers ();
if ( error ) {
console . error ( error );
} else {
console . log ( data );
}
{
name : '@hey-api/sdk' ,
responseStyle : 'data' ,
}
try {
const data = await getUsers ();
console . log ( data );
} catch ( error ) {
console . error ( error );
}
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.
Disable if you’re handling auth yourself or defining it globally on the client.
{
name : '@hey-api/sdk' ,
auth : false , // Reduce generated code size
}
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
}
{
name : '@hey-api/sdk' ,
validator : '@hey-api/zod' ,
}
{
name : '@hey-api/sdk' ,
validator : {
request : '@hey-api/zod' , // Validate requests
response : false , // Don't validate responses
},
}
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
},
},
] ,
}) ;
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 Option New 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.