Skip to main content
โšก Calmops

OpenAPI Specification: Documentation & Code Generation

Introduction

OpenAPI (formerly Swagger) has become the industry standard for documenting REST APIs. It enables automatic documentation generation, client SDK generation, and API testing. However, many teams write OpenAPI specs as an afterthought, resulting in incomplete or inaccurate documentation.

This comprehensive guide covers OpenAPI specification design and implementation.


Core Concepts

OpenAPI

Specification for describing REST APIs in machine-readable format.

Schema

Definition of data structure and validation rules.

Path

API endpoint (e.g., /users/{id}).

Operation

HTTP method on a path (GET, POST, etc.).

Parameter

Input to an operation (query, path, header, body).

Response

Output from an operation.

Component

Reusable schema or parameter definition.


OpenAPI Document Structure

openapi: 3.0.0
info:
  title: User API
  version: 1.0.0
  description: API for managing users
  contact:
    name: API Support
    email: [email protected]
  license:
    name: MIT

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

paths:
  /users:
    get:
      summary: List users
      operationId: listUsers
      tags:
        - Users
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: per_page
          in: query
          schema:
            type: integer
            default: 20
      responses:
        '200':
          description: List of users
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserList'
        '401':
          description: Unauthorized
    
    post:
      summary: Create user
      operationId: createUser
      tags:
        - Users
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserCreate'
      responses:
        '201':
          description: User created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          description: Invalid input
        '401':
          description: Unauthorized

  /users/{userId}:
    get:
      summary: Get user
      operationId: getUser
      tags:
        - Users
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: User details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          description: User not found
    
    put:
      summary: Update user
      operationId: updateUser
      tags:
        - Users
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserUpdate'
      responses:
        '200':
          description: User updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          description: User not found
    
    delete:
      summary: Delete user
      operationId: deleteUser
      tags:
        - Users
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: integer
      responses:
        '204':
          description: User deleted
        '404':
          description: User not found

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
          format: int64
        email:
          type: string
          format: email
        name:
          type: string
        created_at:
          type: string
          format: date-time
      required:
        - id
        - email
        - name
        - created_at
    
    UserCreate:
      type: object
      properties:
        email:
          type: string
          format: email
        name:
          type: string
        password:
          type: string
          format: password
      required:
        - email
        - name
        - password
    
    UserUpdate:
      type: object
      properties:
        email:
          type: string
          format: email
        name:
          type: string
    
    UserList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/User'
        pagination:
          type: object
          properties:
            page:
              type: integer
            per_page:
              type: integer
            total:
              type: integer
  
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

security:
  - bearerAuth: []

Code Generation

Generate Python Client

# Using openapi-generator
openapi-generator generate -i openapi.yaml -g python -o ./python-client

# Using datamodel-code-generator
datamodel-code-generator --input openapi.yaml --output models.py

Generated Client Usage

from openapi_client import ApiClient, Configuration
from openapi_client.api.users_api import UsersApi

# Configure API
config = Configuration(host="https://api.example.com/v1")
config.api_key["Authorization"] = "your-token"

# Create API client
api_client = ApiClient(config)
users_api = UsersApi(api_client)

# List users
users = users_api.list_users(page=1, per_page=20)

# Create user
new_user = users_api.create_user(
    user_create={
        "email": "[email protected]",
        "name": "John Doe",
        "password": "secure-password"
    }
)

# Get user
user = users_api.get_user(user_id=1)

# Update user
updated_user = users_api.update_user(
    user_id=1,
    user_update={"name": "Jane Doe"}
)

# Delete user
users_api.delete_user(user_id=1)

Generate TypeScript Client

# Using openapi-generator
openapi-generator generate -i openapi.yaml -g typescript-axios -o ./ts-client

Documentation Generation

Swagger UI

from flask import Flask
from flasgger import Swagger

app = Flask(__name__)
swagger = Swagger(app, template_file='openapi.yaml')

# Access at http://localhost:5000/apidocs/

ReDoc

<!DOCTYPE html>
<html>
<head>
    <title>API Documentation</title>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
    <style>
        body {
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
    <redoc spec-url='openapi.yaml'></redoc>
    <script src="https://cdn.jsdelivr.net/npm/redoc@latest/bundles/redoc.standalone.js"></script>
</body>
</html>

Best Practices

  1. Keep Spec Updated: Update spec with code changes
  2. Use Components: Reuse schemas and parameters
  3. Document Errors: Document all error responses
  4. Use Examples: Provide example requests/responses
  5. Version API: Include version in spec
  6. Security: Document authentication requirements
  7. Rate Limiting: Document rate limits
  8. Pagination: Document pagination parameters
  9. Filtering: Document filtering options
  10. Testing: Generate tests from spec

External Resources

OpenAPI

Code Generation

Documentation


Conclusion

OpenAPI specification is essential for modern API development. By maintaining accurate specs, you enable automatic documentation, client generation, and testing.

Start with a clear spec, generate documentation and clients, and keep the spec synchronized with your implementation.

OpenAPI specifications are the foundation of API-first development.

Comments