Meta Description: Generate client SDKs automatically from OpenAPI specs. Learn tools, best practices, and how to maintain type-safe SDKs for multiple languages.
Keywords: sdk generation, openapi sdk, api client generation, openapi generator, type-safe sdk, client libraries
Word Count: ~2,300 words
You've built an API. Now developers need client libraries for JavaScript, Python, Go, Java, and more.
Writing SDKs manually is time-consuming. Every API change requires updating multiple SDKs. Documentation gets out of sync.
Auto-generate SDKs from your OpenAPI specification instead.
Why Auto-Generate SDKs?
Consistency
Generated SDKs match your API exactly. No manual translation errors.
Maintenance
Update your OpenAPI spec, regenerate SDKs. All clients stay in sync.
Type Safety
Generated SDKs include types from your OpenAPI schemas. Catch errors at compile time.
Documentation
SDKs include inline documentation from your OpenAPI descriptions.
Multi-Language Support
Generate SDKs for 20+ languages from one specification.
OpenAPI Generator
OpenAPI Generator is the most popular tool for SDK generation.
Installation
npm install -g @openapitools/openapi-generator-cli
Or use Docker:
docker pull openapitools/openapi-generator-cli
Generate JavaScript SDK
openapi-generator-cli generate \
-i openapi.yaml \
-g javascript \
-o ./sdks/javascript \
--additional-properties=projectName=petstore-sdk,projectVersion=1.0.0
This creates a complete JavaScript SDK with: - API client classes - Model classes - TypeScript definitions - README with examples - Package.json
Generate Python SDK
openapi-generator-cli generate \
-i openapi.yaml \
-g python \
-o ./sdks/python \
--additional-properties=packageName=petstore_sdk,packageVersion=1.0.0
Generate Go SDK
openapi-generator-cli generate \
-i openapi.yaml \
-g go \
-o ./sdks/go \
--additional-properties=packageName=petstore
Supported Languages
OpenAPI Generator supports 50+ languages and frameworks: - JavaScript/TypeScript - Python - Go - Java - C# - Ruby - PHP - Swift - Kotlin - Rust - And many more
Using Generated SDKs
JavaScript/TypeScript
import { PetStoreApi, Configuration } from 'petstore-sdk';
const config = new Configuration({
basePath: 'https://api.petstoreapi.com/v1',
accessToken: 'your-api-key'
});
const api = new PetStoreApi(config);
// Get a pet
const pet = await api.getPet({ id: '123' });
console.log(pet.name);
// Create a pet
const newPet = await api.createPet({
createPetRequest: {
name: 'Max',
species: 'DOG',
breed: 'Golden Retriever'
}
});
// List pets with filters
const pets = await api.listPets({
species: 'DOG',
status: 'AVAILABLE',
limit: 20
});
Python
from petstore_sdk import PetStoreApi, Configuration
config = Configuration(
host='https://api.petstoreapi.com/v1',
access_token='your-api-key'
)
api = PetStoreApi(config)
# Get a pet
pet = api.get_pet(id='123')
print(pet.name)
# Create a pet
new_pet = api.create_pet(
create_pet_request={
'name': 'Max',
'species': 'DOG',
'breed': 'Golden Retriever'
}
)
# List pets with filters
pets = api.list_pets(
species='DOG',
status='AVAILABLE',
limit=20
)
Go
package main
import (
"context"
"fmt"
petstore "github.com/yourorg/petstore-sdk-go"
)
func main() {
config := petstore.NewConfiguration()
config.Host = "api.petstoreapi.com"
config.Scheme = "https"
config.AddDefaultHeader("Authorization", "Bearer your-api-key")
client := petstore.NewAPIClient(config)
// Get a pet
pet, _, err := client.PetsApi.GetPet(context.Background(), "123").Execute()
if err != nil {
panic(err)
}
fmt.Println(pet.Name)
// Create a pet
newPet := petstore.NewCreatePetRequest("Max", "DOG")
newPet.SetBreed("Golden Retriever")
created, _, err := client.PetsApi.CreatePet(context.Background()).
CreatePetRequest(*newPet).
Execute()
if err != nil {
panic(err)
}
}
Customizing Generated SDKs
Configuration File
Create config.yaml:
generatorName: typescript-fetch
inputSpec: openapi.yaml
outputDir: ./sdks/typescript
additionalProperties:
npmName: "@yourorg/petstore-sdk"
npmVersion: "1.0.0"
supportsES6: true
withInterfaces: true
useSingleRequestParameter: true
Generate with config:
openapi-generator-cli generate -c config.yaml
Custom Templates
Override default templates:
openapi-generator-cli generate \
-i openapi.yaml \
-g typescript-fetch \
-o ./sdks/typescript \
-t ./templates/typescript
Create templates/typescript/api.mustache to customize API class generation.
Post-Processing
Add custom code after generation:
#!/bin/bash
# Generate SDK
openapi-generator-cli generate -i openapi.yaml -g javascript -o ./sdk
# Add custom utilities
cp ./custom/utils.js ./sdk/src/utils.js
# Update package.json
jq '.scripts.test = "jest"' ./sdk/package.json > ./sdk/package.json.tmp
mv ./sdk/package.json.tmp ./sdk/package.json
# Install dependencies and build
cd ./sdk
npm install
npm run build
Best Practices
1. Version Your SDKs
Match SDK versions to API versions:
# openapi.yaml
info:
version: "1.2.0"
Generate with version:
openapi-generator-cli generate \
-i openapi.yaml \
-g python \
--additional-properties=packageVersion=1.2.0
2. Include Examples in OpenAPI
Examples become SDK documentation:
paths:
/pets:
post:
summary: Create a pet
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreatePetRequest'
examples:
dog:
summary: Create a dog
value:
name: "Max"
species: "DOG"
breed: "Golden Retriever"
Generated SDK includes this example in documentation.
3. Use Descriptive Names
Good OpenAPI names become good SDK names:
# Bad
paths:
/p:
get:
operationId: gp
# Good
paths:
/pets:
get:
operationId: listPets
4. Add Descriptions
Descriptions become SDK comments:
paths:
/pets/{id}:
get:
summary: Get a pet by ID
description: |
Retrieves detailed information about a specific pet.
Requires read:pets permission.
parameters:
- name: id
in: path
description: The unique identifier of the pet
required: true
schema:
type: string
format: uuid
Generated SDK:
/**
* Get a pet by ID
*
* Retrieves detailed information about a specific pet.
* Requires read:pets permission.
*
* @param id The unique identifier of the pet
*/
async getPet(id: string): Promise<Pet>
5. Automate SDK Publishing
# .github/workflows/publish-sdks.yml
name: Publish SDKs
on:
release:
types: [published]
jobs:
publish-javascript:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Generate JavaScript SDK
run: |
openapi-generator-cli generate \
-i openapi.yaml \
-g javascript \
-o ./sdk
- name: Publish to npm
run: |
cd ./sdk
npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-python:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Generate Python SDK
run: |
openapi-generator-cli generate \
-i openapi.yaml \
-g python \
-o ./sdk
- name: Publish to PyPI
run: |
cd ./sdk
python setup.py sdist
twine upload dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
Alternative Tools
Swagger Codegen
Predecessor to OpenAPI Generator:
swagger-codegen generate \
-i openapi.yaml \
-l javascript \
-o ./sdk
OpenAPI TypeScript
TypeScript-specific generator:
npx openapi-typescript openapi.yaml --output ./types.ts
Generates TypeScript types only (no runtime code).
Orval
React Query + Axios generator:
npx orval --input openapi.yaml --output ./src/api
Generates React hooks for API calls.
Fern
Modern SDK generator with better customization:
fern generate --api openapi.yaml --language typescript
Testing Generated SDKs
Unit Tests
// test/pets.test.js
import { PetStoreApi } from '../sdk';
describe('PetsApi', () => {
let api;
beforeEach(() => {
api = new PetStoreApi({
basePath: 'http://localhost:3000',
accessToken: 'test-key'
});
});
test('getPet returns pet data', async () => {
const pet = await api.getPet({ id: '123' });
expect(pet.name).toBe('Max');
expect(pet.species).toBe('DOG');
});
test('createPet creates a new pet', async () => {
const newPet = await api.createPet({
createPetRequest: {
name: 'Bella',
species: 'CAT'
}
});
expect(newPet.id).toBeDefined();
});
});
Integration Tests
// test/integration.test.js
import { PetStoreApi } from '../sdk';
describe('Integration Tests', () => {
const api = new PetStoreApi({
basePath: process.env.API_URL,
accessToken: process.env.API_KEY
});
test('full pet lifecycle', async () => {
// Create
const created = await api.createPet({
createPetRequest: { name: 'Test Pet', species: 'DOG' }
});
// Read
const fetched = await api.getPet({ id: created.id });
expect(fetched.name).toBe('Test Pet');
// Update
const updated = await api.updatePet({
id: created.id,
updatePetRequest: { name: 'Updated Pet' }
});
expect(updated.name).toBe('Updated Pet');
// Delete
await api.deletePet({ id: created.id });
});
});
Maintaining SDKs
Versioning Strategy
Semantic Versioning: - Major: Breaking API changes - Minor: New features (backward compatible) - Patch: Bug fixes
Match API versions:
API v1.2.3 → SDK v1.2.3
Changelog
Generate changelogs from OpenAPI changes:
# Compare OpenAPI specs
openapi-diff old-openapi.yaml new-openapi.yaml > CHANGELOG.md
Deprecation Warnings
Mark deprecated endpoints in OpenAPI:
paths:
/pets/findByStatus:
get:
deprecated: true
summary: Find pets by status (deprecated)
description: Use GET /pets?status=AVAILABLE instead
Generated SDK includes deprecation warnings.
Auto-generating SDKs from OpenAPI specifications saves time, ensures consistency, and improves developer experience. Start with OpenAPI Generator, customize as needed, and automate publishing for seamless SDK maintenance.
Your developers get type-safe, well-documented client libraries that stay in sync with your API automatically.