OSS-first docs

These docs teach the open system first: contracts, generated surfaces, runtimes, governance, and incremental adoption. Studio shows up as the operating layer on top, not as the source of truth.

Generate client from schema

Automatically generate type-safe API clients in any language from your contracts.

Client Development Problems

  • Writing API clients is repetitive
  • Manual clients have type mismatches
  • Keeping clients in sync with APIs
  • Language-specific client maintenance

Automated Solutions

  • Generate clients for multiple languages
  • Type-safe request/response handling
  • Automatic client updates from contracts
  • Consistent error handling across languages

Contract Definition

Define your API contract once, generate clients for any language.

src/contracts/api.contract.ts
import { defineContract } from '@contractspec/lib.contracts-spec';
import { SchemaModel, ScalarTypeEnum } from '@contractspec/lib.schema';

export const ApiContract = defineContract({
  name: 'MyAPI',
  version: '1.0.0',
  baseUrl: 'https://api.example.com',
  operations: {
    getUsers: {
      goal: 'Retrieve paginated list of users',
      method: 'GET',
      path: '/users',
      input: new SchemaModel({
        type: 'object',
        properties: {
          page: { type: 'integer', minimum: 1, default: 1 },
          limit: { type: 'integer', minimum: 1, maximum: 100, default: 20 },
        },
      }),
      output: new SchemaModel({
        type: 'object',
        properties: {
          users: {
            type: 'array',
            items: {
              type: 'object',
              properties: {
                id: { type: 'string', required: true },
                email: { type: 'string', required: true },
                name: { type: 'string', required: true },
              },
            },
          },
          pagination: {
            type: 'object',
            properties: {
              page: { type: 'integer', required: true },
              limit: { type: 'integer', required: true },
              total: { type: 'integer', required: true },
            },
          },
        },
      }),
    },
    createUser: {
      goal: 'Create a new user account',
      method: 'POST',
      path: '/users',
      input: new SchemaModel({
        type: 'object',
        properties: {
          email: { type: 'string', format: 'email', required: true },
          name: { type: 'string', minLength: 1, required: true },
        },
      }),
      output: new SchemaModel({
        type: 'object',
        properties: {
          id: { type: 'string', required: true },
          email: { type: 'string', required: true },
          name: { type: 'string', required: true },
          createdAt: { type: 'string', format: 'date-time', required: true },
        },
      }),
    },
  },
  metadata: {
    description: 'User management API with authentication',
    tags: ['users', 'authentication'],
  },
});

Generate Multiple Clients

Generate type-safe clients for any language from the same contract.

generate-clients
# Generate all supported language clients
contractspec generate clients \
  --contract ./src/contracts/api.contract.ts \
  --output ./generated/clients \
  --languages typescript,python,go,java,csharp

# Generate specific language client
contractspec generate clients \
  --contract ./src/contracts/api.contract.ts \
  --output ./generated/clients \
  --languages typescript \
  --format npm-package

# Options
# --with-types: Include TypeScript definitions
# --with-tests: Generate client test suites
# --with-docs: Include client documentation
# --framework: Use specific HTTP client framework

Generated Client Examples

Each generated client is fully type-safe and idiomatic.

TypeScript Client

generated/clients/typescript/index.ts
import { MyAPIClient } from './client';

const client = new MyAPIClient({
  baseUrl: 'https://api.example.com',
  apiKey: process.env.API_KEY,
});

// Type-safe method calls
const users = await client.getUsers({
  page: 1,
  limit: 10,
});

const newUser = await client.createUser({
  email: 'user@example.com',
  name: 'John Doe',
});

// Full type inference
// users: GetUsersResponse
// newUser: CreateUserResponse

Python Client

generated/clients/python/index.py
from myapi_client import MyAPIClient

client = MyAPIClient(
    base_url='https://api.example.com',
    api_key=os.getenv('API_KEY')
)

# Type-safe method calls
users = await client.get_users(
    page=1,
    limit=10
)

new_user = await client.create_user(
    email='user@example.com',
    name='John Doe'
)

# Full type hints
# users: GetUsersResponse
# new_user: CreateUserResponse

Go Client

generated/clients/go/client.go
package main

import (
    "context"
    "myapi_client"
)

func main() {
    client := myapi_client.NewMyAPIClient(
        myapi_client.WithBaseURL("https://api.example.com"),
        myapi_client.WithAPIKey(os.Getenv("API_KEY")),
    )
    
    // Type-safe method calls
    users, err := client.GetUsers(&myapi_client.GetUsersParams{
        Page: 1,
        Limit: 10,
    })
    
    newUser, err := client.CreateUser(&myapi_client.CreateUserParams{
        Email: "user@example.com",
        Name:  "John Doe",
    })
    
    // Full type checking at compile time
    // users: *GetUsersResponse
    // newUser: *CreateUserResponse
}

Advanced Features

Generated clients include enterprise-grade features out of the box.

client-features.ts
// Advanced client features
const client = new MyAPIClient({
  baseUrl: 'https://api.example.com',
  apiKey: 'your-api-key',
  
  // Retry configuration
  retryConfig: {
    maxRetries: 3,
    backoffMultiplier: 2,
    maxDelay: 30000,
  },
  
  // Request/Response interceptors
  interceptors: {
    request: [(config) => {
      // Add authentication headers
      config.headers.Authorization = `Bearer ${await getAuthToken()}`;
      return config;
    }],
    response: [(response) => {
      // Log API calls
      console.log(`API Call: ${response.config.method} ${response.config.url}`);
      return response;
    }],
  },
  
  // Error handling
  errorHandler: (error) => {
    if (error.status === 401) {
      // Refresh token and retry
      return refreshTokenAndRetry(error.originalRequest);
    }
    throw error;
  },
});

// Automatic request deduplication
const user1 = client.getUser({ id: '123' });
const user2 = client.getUser({ id: '123' }); // Uses cached result

// Request cancellation
const controller = new AbortController();
const promise = client.getUsers({ page: 1, signal: controller.signal });
controller.abort(); // Cancels the request
OSS docsStart with OSS. Adopt Studio when you want the operating layer.

Why ContractSpec

Keep educational and comparison content reachable without letting it define the primary OSS learning path.