This post compares free OpenAPI generators:
| OpenAPI Generator | Fern | Hey API | Kiota | |
|---|---|---|---|---|
| Open-source | ✅ OSS | Open-core | ✅ OSS | ✅ OSS |
| Multi-language | ✅ 50+ | ✅ Major | ❌ TS only | ✅ Major |
| Server stubs | ✅ Yes | ⚠️ Limited | ❌ No | ❌ No |
| SDK quality | ⚠️ Variable | ✅ High | ✅ High (TS) | ✅ Strongly typed |
| Production defaults | ⚠️ Needs tuning | ✅ Included | ✅ Included | ✅ Included |
| Docs platform | ⚠️ Basic | ✅ Integrated | ⚠️ Limited | ❌ No |
| Extensibility | ✅ Templates | ⚠️ Platform | ✅ TS ecosystem | ⚠️ Limited |
| Best fit | Broad coverage | API product | TS apps | Large structured APIs |
OpenAPI Spec
Given the openapi.yaml:
openapi: 3.1.0
info:
title: Users API
version: 1.0.0
servers:
- url: https://api.example.com
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
schemas:
User:
type: object
required:
- id
- email
properties:
id:
type: string
email:
type: string
name:
type: string
security:
- bearerAuth: []
paths:
/v1/users/{id}:
get:
operationId: getUser
summary: Get a user by ID
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'200':
description: A user
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'401':
description: Unauthorized
OpenAPI Generator
OpenAPI Generator is an open source generator that supports many languages.
Prerequisites
Generate
Create openapi-generator.config.yaml:
generatorName: typescript-fetch
inputSpec: ./openapi.yaml
outputDir: ./sdk
additionalProperties:
npmName: '@your-org/sdk'
npmVersion: '0.1.0'
supportsES6: true
Generate the TypeScript SDK:
npx openapi-generator-cli generate -c openapi-generator.config.yaml
Build
Build the package:
npm --prefix sdk install
Usage
Code example:
import { Configuration, DefaultApi, type GetUserRequest } from './sdk';
const config = new Configuration({
accessToken: 'YOUR BEARER TOKEN',
});
const api = new DefaultApi(config);
const body: GetUserRequest = {
id: 'user-123',
};
api.getUser(body).then((user) => {
console.log(user.email);
});
Fern
Fern is an open-core generator with a focus on DX (developer experience).
Prerequisites
Generate
Initialize Fern:
npx fern-api init --openapi ./openapi.yaml
Generate the TypeScript SDK:
npx fern-api generate --local
Build
Go to the SDK folder:
cd ./sdks/typescript/
Add package.json:
{
"name": "@your-org/sdk",
"version": "0.1.0",
"type": "module",
"main": "dist/index.js",
"files": ["dist"]
}
Add tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"moduleResolution": "Node",
"declaration": true,
"outDir": "dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src"]
}
Build the package:
npx -p typescript tsc
Usage
Code example:
import { type Api, ApiClient } from './sdks/typescript';
const client = new ApiClient({
token: 'YOUR_TOKEN',
});
const user: Api.GetUserRequest = { id: 'user-123' };
client.getUser(user).then((user) => {
console.log(user.email);
});
Hey API
Hey API is a TypeScript codegen.
Prerequisites
Generate
Generate the TypeScript SDK:
npx @hey-api/openapi-ts -i ./openapi.yaml -o sdk/src
Build
Go to the SDK folder:
cd ./sdk/
Add package.json:
{
"name": "@your-org/sdk",
"version": "0.1.0",
"type": "module",
"main": "dist/index.js",
"files": ["dist"]
}
Add tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"moduleResolution": "Node",
"declaration": true,
"outDir": "dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src"]
}
Build the package:
npx -p typescript tsc
Usage
Code example:
import { type GetUserData, getUser } from './sdk';
import { client } from './sdk/dist/client.gen';
client.setConfig({
baseUrl: 'https://api.example.com',
auth() {
return 'YOUR_TOKEN';
},
});
const user: Pick<GetUserData, 'path'> = { path: { id: 'user-123' } };
getUser(user).then((user) => {
if (user.error) {
return console.error(user.error);
}
console.log(user.data.email);
});
Kiota
Kiota is an open-source generator developed by Microsoft.
Prerequisites
Generate
npx @kiota-community/kiota-gen generate --openapi ./openapi.yaml --language typescript --output sdk/src
Build
Go to the SDK folder:
cd ./sdk/
Add package.json:
{
"name": "@your-org/sdk",
"version": "0.1.0",
"type": "module",
"main": "dist/apiClient.js",
"files": ["dist"],
"dependencies": {
"@microsoft/kiota-bundle": "1.0.0-preview.99"
}
}
Install the dependencies:
npm i
Add tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"moduleResolution": "Node",
"declaration": true,
"outDir": "dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src"]
}
Build the package:
npx -p typescript tsc
Usage
Code example:
import {
AllowedHostsValidator,
AuthenticationProvider,
} from '@microsoft/kiota-abstractions';
import { FetchRequestAdapter } from '@microsoft/kiota-http-fetchlibrary';
import { createApiClient } from './sdk';
class StaticAuthProvider implements AuthenticationProvider {
private readonly allowedHosts = new AllowedHostsValidator(
new Set(['api.example.com']),
);
async authenticateRequest(requestInfo, additionalAuthenticationContext) {
const url =
requestInfo?.uri instanceof URL
? requestInfo.uri
: new URL(requestInfo?.uri ?? requestInfo?.url ?? '');
if (!this.allowedHosts.isUrlHostValid(url)) return;
requestInfo.headers ??= new Map<string, string>();
requestInfo.headers.set('Authorization', `Bearer YOUR_ACCESS_TOKEN`);
}
}
const adapter = new FetchRequestAdapter(new StaticAuthProvider());
adapter.baseUrl = 'https://api.example.com';
const client = createApiClient(adapter);
client.v1.users
.byId('user-123')
.get()
.then((user) => {
console.log(user.email);
});