API Client Generator

Category: Code Generation October 15, 2025

Generate type-safe API client code from OpenAPI/Swagger specifications with error handling.

APICode GenerationTypeScriptOpenAPIClient SDK
# API Client Generator

Generate a complete, type-safe API client library from OpenAPI/Swagger specifications with proper error handling, authentication, and retries.

## Generated Client Features

### 1. Type Safety
- Generate TypeScript interfaces for all models
- Type-safe request/response handling
- Enum types for fixed values
- Generic types for paginated responses
- Discriminated unions for polymorphic types

### 2. HTTP Client
- Configurable base URL
- Request/response interceptors
- Automatic retries with exponential backoff
- Timeout handling
- Cancel token support

### 3. Authentication
- Bearer token support
- API key authentication
- OAuth 2.0 flow
- Token refresh logic
- Credential storage

### 4. Error Handling
- Typed error responses
- HTTP status code handling
- Network error handling
- Validation errors
- Custom error classes

## Example Output

### Generated Types
```typescript
// Generated from OpenAPI schema
export interface User {
  id: number;
  email: string;
  name: string;
  role: UserRole;
  createdAt: string;
  updatedAt: string;
}

export enum UserRole {
  Admin = 'admin',
  User = 'user',
  Guest = 'guest'
}

export interface PaginatedResponse<T> {
  data: T[];
  page: number;
  pageSize: number;
  total: number;
}

export interface ApiError {
  code: string;
  message: string;
  details?: Record<string, string[]>;
}

Generated Client

export class ApiClient {
  private baseURL: string;
  private token?: string;
  
  constructor(config: ApiConfig) {
    this.baseURL = config.baseURL;
    this.token = config.token;
  }
  
  // Users endpoint
  async getUsers(params?: {
    page?: number;
    pageSize?: number;
    role?: UserRole;
  }): Promise<PaginatedResponse<User>> {
    return this.request<PaginatedResponse<User>>('GET', '/users', { params });
  }
  
  async getUser(id: number): Promise<User> {
    return this.request<User>('GET', `/users/${id}`);
  }
  
  async createUser(data: CreateUserRequest): Promise<User> {
    return this.request<User>('POST', '/users', { data });
  }
  
  async updateUser(id: number, data: UpdateUserRequest): Promise<User> {
    return this.request<User>('PUT', `/users/${id}`, { data });
  }
  
  async deleteUser(id: number): Promise<void> {
    return this.request<void>('DELETE', `/users/${id}`);
  }
  
  // Core request method
  private async request<T>(
    method: string,
    path: string,
    options?: RequestOptions
  ): Promise<T> {
    const url = `${this.baseURL}${path}`;
    const headers = {
      'Content-Type': 'application/json',
      ...(this.token && { Authorization: `Bearer ${this.token}` }),
      ...options?.headers,
    };
    
    try {
      const response = await fetch(url, {
        method,
        headers,
        body: options?.data ? JSON.stringify(options.data) : undefined,
        signal: options?.signal,
      });
      
      if (!response.ok) {
        throw await this.handleErrorResponse(response);
      }
      
      if (response.status === 204) {
        return undefined as T;
      }
      
      return await response.json();
    } catch (error) {
      if (error instanceof ApiError) throw error;
      throw new NetworkError('Network request failed', error);
    }
  }
  
  private async handleErrorResponse(response: Response): Promise<ApiError> {
    const body = await response.json().catch(() => ({}));
    return new ApiError(
      body.code || `HTTP_${response.status}`,
      body.message || response.statusText,
      body.details
    );
  }
}

Usage Example

// Initialize client
const api = new ApiClient({
  baseURL: 'https://api.example.com/v1',
  token: 'your-auth-token',
});

// Use type-safe methods
try {
  const users = await api.getUsers({ page: 1, pageSize: 20, role: UserRole.Admin });
  console.log(`Found ${users.total} users`);
  
  const user = await api.getUser(users.data[0].id);
  console.log(user.name);
  
  const newUser = await api.createUser({
    email: 'new@example.com',
    name: 'New User',
    role: UserRole.User,
  });
  
} catch (error) {
  if (error instanceof ApiError) {
    console.error(`API Error: ${error.code} - ${error.message}`);
    if (error.details) {
      console.error('Validation errors:', error.details);
    }
  } else if (error instanceof NetworkError) {
    console.error('Network error:', error.message);
  }
}

Generation Checklist

  • All endpoints covered
  • Request/response types generated
  • Authentication implemented
  • Error handling complete
  • Retries with backoff
  • Request cancellation supported
  • Documentation generated
  • Example code provided
  • Tests generated
  • Published to npm/registry