Generate TypeScript clients from OpenAPI 3.x specifications.
- Supports OpenAPI 3.0.x and 3.1.x specifications
- Three output formats: Fetch API, Axios, and Angular
- Fully typed TypeScript output with models and API classes
- Accepts specs as Python dictionaries or JSON strings
- Automatic validation of OpenAPI specifications
Python backend frameworks like FastAPI and django-ninja already generate OpenAPI specs from your type hints. This library enables those frameworks to take the next step: generating TypeScript clients that mirror your backend types exactly. Framework authors can integrate openapi-ts-client to give their users end-to-end type safety with zero manual type definitions.
pip install openapi-ts-clientOr install from source:
git clone https://github.com/fa-krug/openapi-ts-client.git
cd openapi-ts-client
pip install -e .# Generate from file
openapi-ts-client ./openapi.json
# Specify output format and directory
openapi-ts-client ./openapi.json -f axios -o ./src/api
# Generate from URL
openapi-ts-client https://api.example.com/openapi.json
# Generate from stdin
cat openapi.json | openapi-ts-client -
# Use config file
openapi-ts-client --config ./my-config.json
# Verbose output
openapi-ts-client ./openapi.json -vCreate openapi-ts-client.json for repeated use:
{
"clients": [
{
"input": "./specs/users-api.json",
"format": "fetch",
"output": "./src/api/users"
},
{
"input": "./specs/orders-api.json",
"format": "axios",
"output": "./src/api/orders"
}
]
}Then run:
openapi-ts-client| Option | Description | Default |
|---|---|---|
-f, --format |
Output format: fetch, axios, angular | fetch |
-o, --output |
Output directory | ./generated |
-c, --config |
Config file path | openapi-ts-client.json |
--no-validate |
Skip OpenAPI spec validation | - |
--clean |
Clear output directory before generating | - |
--force |
Continue even if output directory is not empty (may overwrite files) | - |
-q, --quiet |
Suppress all output except errors | - |
-v, --verbose |
Show detailed progress | - |
from openapi_ts_client import generate_typescript_client, ClientFormat
# Load your OpenAPI spec (from file, URL, or inline)
with open("openapi.json", "r") as f:
spec = f.read()
# Generate a TypeScript client
result = generate_typescript_client(
openapi_spec=spec,
output_format=ClientFormat.FETCH,
output_path="./generated/api"
)
print(result)
# Output: TypeScript Fetch client generated for 'My API' v1.0.0 (OpenAPI 3.0.0). Output: /path/to/generated/apifrom openapi_ts_client import generate_typescript_client, ClientFormat
# Inline OpenAPI 3.x specification
spec = {
"openapi": "3.0.0",
"info": {
"title": "My API",
"version": "1.0.0"
},
"paths": {
"/users": {
"get": {
"summary": "Get all users",
"operationId": "getUsers",
"responses": {
"200": {
"description": "Success"
}
}
}
}
}
}
# Generate with defaults (Fetch client, temp directory)
result = generate_typescript_client(spec)from openapi_ts_client import generate_typescript_client
# Load spec from a JSON file (as string)
with open("openapi.json", "r") as f:
json_string = f.read()
result = generate_typescript_client(json_string, output_path="./src/api")import yaml
from openapi_ts_client import generate_typescript_client
# Load spec from YAML (convert to dict)
with open("openapi.yaml", "r") as f:
spec = yaml.safe_load(f)
result = generate_typescript_client(spec, output_path="./src/api")The package supports three output formats, each optimized for different use cases:
Native browser Fetch API client with no external dependencies.
from openapi_ts_client import generate_typescript_client, ClientFormat
result = generate_typescript_client(
spec,
output_format=ClientFormat.FETCH,
output_path="./generated/fetch-client"
)Generated structure:
fetch-client/
├── index.ts # Main entry point, exports all
├── runtime.ts # HTTP client runtime utilities
├── apis/
│ ├── index.ts # Exports all API classes
│ ├── PetApi.ts # API class for /pet endpoints
│ ├── StoreApi.ts # API class for /store endpoints
│ └── UserApi.ts # API class for /user endpoints
└── models/
├── index.ts # Exports all model interfaces
├── Pet.ts # TypeScript interface for Pet
├── Order.ts # TypeScript interface for Order
└── User.ts # TypeScript interface for User
Usage in TypeScript:
import { Configuration, PetApi, Pet } from './generated/fetch-client';
const config = new Configuration({
basePath: 'https://api.example.com',
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
}
});
const petApi = new PetApi(config);
// Get a pet by ID
const pet: Pet = await petApi.getPetById({ petId: 1 });
// Create a new pet
const newPet = await petApi.addPet({
pet: { name: 'Fluffy', status: 'available' }
});Client using the popular Axios HTTP library with interceptors support.
from openapi_ts_client import generate_typescript_client, ClientFormat
result = generate_typescript_client(
spec,
output_format=ClientFormat.AXIOS,
output_path="./generated/axios-client"
)Generated structure:
axios-client/
├── index.ts # Main entry point
├── api.ts # All API classes and interfaces
├── base.ts # Base API class
├── common.ts # Common utilities
└── configuration.ts # Configuration class
Usage in TypeScript:
import { Configuration, PetApi } from './generated/axios-client';
import axios from 'axios';
const config = new Configuration({
basePath: 'https://api.example.com',
accessToken: 'YOUR_TOKEN'
});
const petApi = new PetApi(config);
// Get a pet by ID
const response = await petApi.getPetById(1);
const pet = response.data;
// With custom Axios instance (for interceptors)
const axiosInstance = axios.create();
axiosInstance.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${getToken()}`;
return config;
});
const petApiWithInterceptors = new PetApi(config, undefined, axiosInstance);Angular-optimized client with injectable services and RxJS Observables.
from openapi_ts_client import generate_typescript_client, ClientFormat
result = generate_typescript_client(
spec,
output_format=ClientFormat.ANGULAR,
output_path="./generated/angular-client"
)Generated structure:
angular-client/
├── index.ts # Main entry point
├── api.module.ts # Angular module for importing
├── api.base.service.ts # Base service class
├── configuration.ts # Configuration class
├── provide-api.ts # Standalone provider function
├── api/
│ ├── api.ts # Exports all services
│ ├── pet.service.ts # Injectable PetService
│ ├── store.service.ts # Injectable StoreService
│ └── user.service.ts # Injectable UserService
└── model/
├── models.ts # Exports all models
├── pet.ts # Pet interface
├── order.ts # Order interface
└── user.ts # User interface
Usage in Angular:
// app.module.ts
import { ApiModule, Configuration } from './generated/angular-client';
@NgModule({
imports: [
ApiModule.forRoot(() => new Configuration({
basePath: 'https://api.example.com'
}))
]
})
export class AppModule { }
// Or with standalone components (Angular 14+)
// app.config.ts
import { provideApi } from './generated/angular-client';
export const appConfig = {
providers: [
provideApi({
basePath: 'https://api.example.com'
})
]
};// pet.component.ts
import { Component, inject } from '@angular/core';
import { PetService, Pet } from './generated/angular-client';
@Component({
selector: 'app-pet',
template: `<div>{{ pet?.name }}</div>`
})
export class PetComponent {
private petService = inject(PetService);
pet: Pet | null = null;
ngOnInit() {
this.petService.getPetById(1).subscribe(pet => {
this.pet = pet;
});
}
}Generate a TypeScript client from an OpenAPI specification.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
openapi_spec |
dict | str |
required | The OpenAPI specification as a dictionary or JSON string |
output_format |
ClientFormat |
ClientFormat.FETCH |
The output client format |
output_path |
str | Path | None |
None |
Output directory (uses temp dir if not specified) |
skip_validation |
bool |
False |
Skip OpenAPI specification validation |
clean |
bool |
False |
Clear the output directory before generating. Cannot be used together with force. |
force |
bool |
False |
Continue generation even if output directory is not empty. Files will be overwritten but existing files not part of the generated output will remain. Cannot be used together with clean. |
Returns:
str: A status message with generation details
Raises:
ValueError: If the specification is invalid or missing required fieldsTypeError: Ifopenapi_specis neither a dict nor a string
| Value | Description |
|---|---|
ClientFormat.FETCH |
Native Fetch API client (default) |
ClientFormat.AXIOS |
Axios HTTP library client |
ClientFormat.ANGULAR |
Angular-optimized client with services |
- OpenAPI 3.0.x
- OpenAPI 3.1.x
- Primitive types (string, number, integer, boolean)
- Arrays and objects
- Enums
$refreferencesallOf,anyOf,oneOfcompositions- Nullable types
- All HTTP methods (GET, POST, PUT, DELETE, PATCH, etc.)
- Path parameters
- Query parameters
- Request bodies (JSON, form data)
- Response types
- Operation tags (for grouping into API classes)
- API Key authentication
- Bearer token authentication
- OAuth2 flows
- Basic authentication
- Python 3.8+
Runtime dependencies:
jinja2>=3.1.0- Template engineopenapi-core>=0.19.0- OpenAPI spec validation
For using generated clients:
- Node.js with TypeScript
- Axios (for Axios client)
- Angular 14+ (for Angular client)
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Lint and format
ruff check src --fix
ruff format src
# Setup pre-commit hooks
pre-commit installThis project builds on the excellent work of the OpenAPI Generator team. Their years of effort creating robust code generation templates provided the foundation that made openapi-ts-client possible. Thank you for your contributions to the open-source community.
MIT License - see LICENSE for details.