Skip to main content
Technology & EngineeringApi Design194 lines

API Documentation

OpenAPI and Swagger documentation practices for generating accurate, maintainable API references

Quick Summary23 lines
You are an expert in OpenAPI/Swagger documentation for designing robust APIs.

## Key Points

- url: https://api.example.com/v1
- BearerAuth: []
- Include realistic `example` values for every schema property so interactive documentation shows meaningful sample responses.
- Use `operationId` on every path operation to produce clean, predictable function names in generated SDKs.
- Add `description` fields to parameters, schemas, and responses — the spec is only as useful as its explanations.
- Writing the spec once and never updating it, causing documentation drift that erodes consumer trust.
- Omitting error response schemas, leaving consumers to guess the structure of 4xx and 5xx responses.

## Quick Example

```bash
# Generate a TypeScript client from the spec
npx openapi-typescript-codegen \
  --input ./openapi.yaml \
  --output ./sdk \
  --client axios
```
skilldb get api-design-skills/API DocumentationFull skill: 194 lines
Paste into your CLAUDE.md or agent config

API Documentation — API Design

You are an expert in OpenAPI/Swagger documentation for designing robust APIs.

Core Philosophy

Overview

API documentation is the primary interface between your API and its consumers. The OpenAPI Specification (OAS) provides a machine-readable format that powers interactive docs, client SDK generation, and contract testing. Treating documentation as code ensures it stays accurate as the API evolves.

Core Concepts

OpenAPI Specification Structure

openapi: 3.1.0
info:
  title: User Service API
  version: 1.2.0
  description: Manages user accounts and profiles.
  contact:
    email: api-team@example.com

servers:
  - url: https://api.example.com/v1
    description: Production

paths:
  /users:
    get:
      summary: List users
      operationId: listUsers
      tags: [Users]
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        '200':
          description: A paginated list of users
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserList'

components:
  schemas:
    User:
      type: object
      required: [id, name, email]
      properties:
        id:
          type: integer
          example: 42
        name:
          type: string
          example: Alice
        email:
          type: string
          format: email
          example: alice@example.com
    UserList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/User'
        pagination:
          $ref: '#/components/schemas/Pagination'

Reusable Components

Define schemas, parameters, and responses in components and reference them with $ref to avoid duplication.

components:
  parameters:
    PageLimit:
      name: limit
      in: query
      schema:
        type: integer
        default: 20
        maximum: 100
  responses:
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

Security Schemes

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    ApiKey:
      type: apiKey
      in: header
      name: X-API-Key

security:
  - BearerAuth: []

Implementation Patterns

Code-First with Auto-Generation

Generate the spec from annotated code so it never drifts from the implementation.

# FastAPI generates OpenAPI automatically from type hints
from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str
    email: str

    model_config = {
        "json_schema_extra": {
            "examples": [{"id": 42, "name": "Alice", "email": "alice@example.com"}]
        }
    }

@app.get("/users/{user_id}", response_model=User, tags=["Users"])
def get_user(user_id: int):
    """Retrieve a single user by their ID."""
    ...

Contract Testing

Use the OpenAPI spec as a contract to validate that the implementation matches the documentation.

// Using Prism for contract testing
// prism mock openapi.yaml        — run a mock server
// prism proxy openapi.yaml http://localhost:8000 — validate live traffic

// Schemathesis for property-based testing
// schemathesis run http://localhost:8000/openapi.json

SDK Generation

# Generate a TypeScript client from the spec
npx openapi-typescript-codegen \
  --input ./openapi.yaml \
  --output ./sdk \
  --client axios

Best Practices

  • Include realistic example values for every schema property so interactive documentation shows meaningful sample responses.
  • Use operationId on every path operation to produce clean, predictable function names in generated SDKs.
  • Add description fields to parameters, schemas, and responses — the spec is only as useful as its explanations.

Common Pitfalls

  • Writing the spec once and never updating it, causing documentation drift that erodes consumer trust.
  • Omitting error response schemas, leaving consumers to guess the structure of 4xx and 5xx responses.

Anti-Patterns

Over-engineering for hypothetical scale. Building for millions of users when you have hundreds adds complexity without value. Solve today's problems first.

Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide well wastes time and introduces unnecessary risk.

Premature abstraction. Creating elaborate frameworks and utilities before you have enough concrete cases to know what the abstraction should look like produces the wrong abstraction.

Neglecting error handling at boundaries. Internal code can trust its inputs, but system boundaries (user input, APIs, file I/O) require defensive validation.

Skipping documentation for obvious code. What is obvious to you today will not be obvious to your colleague next month or to you next year.

Install this skill directly: skilldb add api-design-skills

Get CLI access →