fern

Feature-rich Rust logging library. Provides log level configuration, detailed output destination customization, and flexible formatting features. Suitable for scenarios requiring detailed log control in medium to large-scale Rust projects.

API GenerationOpenAPISDK GenerationTypeScriptPythonDocumentation GenerationGo

Library

Fern

Overview

Fern is "a tool that automatically generates SDKs and documentation from API definitions," developed as a core library for modern API development ecosystems. Taking definition files such as OpenAPI, AsyncAPI, and gRPC as input, it automatically generates multi-language SDKs including TypeScript, Python, Go, Java, Ruby, and interactive API documentation. It significantly streamlines the creation and maintenance of high-quality client libraries and documentation, providing an environment where developers can focus on building APIs.

Details

Fern 2025 edition is rapidly growing as a comprehensive SDK generation platform supporting next-generation API development workflows. Graduated from Y Combinator and trusted by over 150 companies including Square, LaunchDarkly, and Eleven Labs, it's a reliable tool. Supporting industry-standard formats including OpenAPI, it batch-generates multi-language SDKs from a single definition file. Generated SDKs are type-safe and output as practical code including authentication processing, error handling, and response processing.

Key Features

  • Multi-language SDK Generation: Supports TypeScript, Python, Go, Java, Ruby, C#, PHP
  • Comprehensive Input Formats: Supports OpenAPI, AsyncAPI, OpenRPC, gRPC, and proprietary formats
  • Automatic Documentation Generation: Automatically creates interactive API references and guides
  • Type-safe Code Generation: Design emphasizing static type checking and IDE support
  • Authentication & Error Handling: Standard equipped with features necessary for practical SDKs
  • Cloud & Local Execution: Flexible build environments and CI/CD integration

Pros and Cons

Pros

  • Automatically generates multi-language SDKs from API definitions, significantly reducing manual maintenance costs
  • Improved development efficiency through type-safe, high-quality client libraries
  • Compatibility with existing tools through support for industry-standard formats like OpenAPI
  • Reliability through enterprise adoption by Square, LaunchDarkly, and others
  • Enhanced API user experience through interactive documentation generation
  • Flexible development environment through CI/CD integration and both cloud and local support

Cons

  • Complexity in managing generated SDK impacts and dependencies when API design changes
  • Limitations in customizing generated code and addressing business-specific requirements
  • Concerns about long-term support and ecosystem maturity due to being a relatively new tool
  • Challenges in generation quality and performance optimization for complex API specifications
  • Lack of clarity in pricing structure and enterprise support for commercial use
  • Learning costs and migration costs from existing SDK development workflows

Reference Pages

Code Examples

Basic Setup

# Install Fern
npm install -g fern-api

# Initialize new project
fern init

# Check configuration files
ls -la fern/
# fern.config.yml
# generators.yml
# definition/

Creating API Definition Files

# fern/definition/api.yml - Fern proprietary format
name: User Management API
auth: BearerAuth
base-path: /api/v1

types:
  User:
    properties:
      id: string
      name: string
      email: string
      created_at: datetime

  CreateUserRequest:
    properties:
      name: string
      email: string

  UserResponse:
    properties:
      user: User
      message: optional<string>

services:
  UserService:
    auth: true
    base-path: /users
    endpoints:
      create:
        docs: Create a new user
        method: POST
        path: ""
        request: CreateUserRequest
        response: UserResponse

      get:
        docs: Get user information
        method: GET
        path: /{id}
        path-parameters:
          id: string
        response: User

      list:
        docs: Get user list
        method: GET
        path: ""
        query-parameters:
          page: optional<integer>
          limit: optional<integer>
        response: list<User>

SDK Generation Configuration

# fern/generators.yml
default-group: local
groups:
  local:
    generators:
      - name: fernapi/fern-typescript-node-sdk
        version: 0.15.0
        output:
          location: local-file-system
          path: ./generated/typescript
        config:
          organization: my-company
          sdk-name: my-api-sdk

      - name: fernapi/fern-python-sdk
        version: 2.0.0
        output:
          location: local-file-system
          path: ./generated/python
        config:
          organization: my-company
          package-name: my_api_sdk

      - name: fernapi/fern-docs
        version: 0.15.0
        output:
          location: local-file-system
          path: ./generated/docs

Converting from OpenAPI

# Import existing OpenAPI file
fern add openapi openapi.json

# Validate OpenAPI specification
fern check

# Convert from OpenAPI to Fern definition
fern generate --local

# Check generated SDKs
ls generated/
# typescript/
# python/
# docs/

Advanced Configuration (Custom Generation Options)

# generators.yml - Detailed configuration example
groups:
  production:
    generators:
      - name: fernapi/fern-typescript-node-sdk
        version: 0.15.0
        output:
          location: npm
          package-name: "@mycompany/api-sdk"
          token: ${NPM_TOKEN}
        config:
          organization: mycompany
          sdk-name: api-sdk
          bundle: true
          noDevDependencies: true
          extraDependencies:
            - name: axios
              version: "^1.0.0"

      - name: fernapi/fern-python-sdk
        version: 2.0.0
        output:
          location: pypi
          package-name: mycompany-api-sdk
          token: ${PYPI_TOKEN}
        config:
          organization: mycompany
          package-name: mycompany_api_sdk
          extra-dependencies:
            - requests>=2.25.0

      - name: fernapi/fern-docs
        version: 0.15.0
        output:
          location: github-pages
          repository: mycompany/api-docs
          token: ${GITHUB_TOKEN}
        config:
          title: "My Company API Documentation"
          favicon: ./assets/favicon.ico
          logo:
            dark: ./assets/logo-dark.png
            light: ./assets/logo-light.png

Generated SDK Usage Example

// TypeScript SDK usage example
import { MyApiClient } from '@mycompany/api-sdk';

const client = new MyApiClient({
  environment: 'production', // or 'staging'
  token: process.env.API_TOKEN
});

// Create user
const newUser = await client.userService.create({
  name: 'John Doe',
  email: '[email protected]'
});

console.log(`Created user: ${newUser.user.id}`);

// Get user list
const users = await client.userService.list({
  page: 1,
  limit: 10
});

users.forEach(user => {
  console.log(`${user.name} (${user.email})`);
});

// Error handling
try {
  const user = await client.userService.get('invalid-id');
} catch (error) {
  if (error.statusCode === 404) {
    console.log('User not found');
  } else {
    console.error('Unexpected error:', error.message);
  }
}

CI/CD Integration Example

# .github/workflows/generate-sdks.yml
name: Generate SDKs
on:
  push:
    paths:
      - 'fern/**'
  pull_request:
    paths:
      - 'fern/**'

jobs:
  generate-sdks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Install Fern
        run: npm install -g fern-api
      
      - name: Validate API definition
        run: fern check
      
      - name: Generate SDKs
        run: fern generate --group production
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
          PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Run SDK tests
        run: |
          cd generated/typescript && npm test
          cd generated/python && python -m pytest