AI Tools Compared

Most engineers write good code comments but hate writing documentation. Modern AI can transform those inline comments into professional API documentation: OpenAPI specs, Markdown guides, and interactive API references. This guide covers the best tools and workflows.

Why AI-Generated Docs Matter

Manual API documentation drifts. Code changes but docs don’t. AI tools solve this by:

A single integration can generate docs for 50 endpoints in 2 minutes.

Extracting Comments: The Foundation

Before AI can generate docs, extract code comments into a format AI understands:

Example: Python FastAPI with good comments

from fastapi import FastAPI, HTTPException, Query
from pydantic import BaseModel
from typing import Optional

app = FastAPI()

class PaymentRequest(BaseModel):
    """Request body for initiating a payment."""
    amount: float  # Payment amount in USD
    currency: str  # ISO 4217 currency code (USD, EUR, GBP)
    idempotency_key: str  # Unique key to prevent duplicate charges
    metadata: Optional[dict] = None  # Custom key-value pairs (max 5KB)

class PaymentResponse(BaseModel):
    """Response after payment processing."""
    transaction_id: str  # Unique identifier for this transaction
    status: str  # PENDING, COMPLETED, FAILED
    amount: float  # Amount charged in requested currency
    timestamp: str  # ISO 8601 timestamp of transaction

@app.post("/payments", response_model=PaymentResponse)
async def create_payment(request: PaymentRequest) -> PaymentResponse:
    """
    Process a payment using Stripe.

    This endpoint initiates a payment charge against the authenticated user's
    payment method. Idempotency keys prevent duplicate charges if the request
    is retried.

    Args:
        request: PaymentRequest containing amount, currency, and idempotency_key

    Returns:
        PaymentResponse with transaction_id and status

    Raises:
        HTTPException(400): Invalid currency or amount format
        HTTPException(409): Idempotency key already used with different amount
        HTTPException(422): Payment method declined or insufficient funds

    Example:
        ```bash
 curl -X POST http://localhost:8000/payments \
 -H "Content-Type: application/json" \
 -d '{"amount": 99.99, "currency": "USD", "idempotency_key": "unique-123"}'
        ```

    Rate limit: 100 requests per minute
    Authentication: Bearer token required
    """
    # Implementation details...
    pass

Claude for OpenAPI Specification Generation

Claude excels at understanding code structure and generating precise OpenAPI 3.0 specs.

Example: Ask Claude to generate OpenAPI from code

Prompt:
Generate a complete OpenAPI 3.0 specification (YAML format) from this
Python FastAPI code. Include request/response schemas, status codes,
rate limits, and authentication requirements.

[Paste code above]

Claude output (partial):

openapi: 3.0.3
info:
  title: Payment API
  version: 1.0.0
  description: Process payments with idempotency support

servers:
  - url: https://api.example.com
    description: Production
  - url: http://localhost:8000
    description: Development

paths:
  /payments:
    post:
      summary: Process a payment
      description: Initiate a payment charge with automatic idempotency handling
      operationId: createPayment
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PaymentRequest'
      responses:
        '200':
          description: Payment processed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentResponse'
        '400':
          description: Invalid request format or currency
        '409':
          description: Idempotency key conflict with different amount
        '422':
          description: Payment method declined or validation failed
      security:
        - BearerAuth: []
      x-rateLimit:
        limit: 100
        window: 60s

components:
  schemas:
    PaymentRequest:
      type: object
      required:
        - amount
        - currency
        - idempotency_key
      properties:
        amount:
          type: number
          format: float
          example: 99.99
          description: Payment amount in specified currency
        currency:
          type: string
          pattern: '^[A-Z]{3}$'
          example: USD
          description: ISO 4217 currency code
        idempotency_key:
          type: string
          example: unique-123
          description: Unique identifier to prevent duplicate charges
        metadata:
          type: object
          additionalProperties: true
          description: Custom metadata (max 5KB)

  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

Python Script: Extract Comments and Generate Docs

import ast
import anthropic
import json

def extract_function_docs(python_file_path: str) -> list[dict]:
    """Extract docstrings and type hints from Python file."""
    with open(python_file_path, 'r') as f:
        tree = ast.parse(f.read())

    functions = []
    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            docstring = ast.get_docstring(node) or "No documentation"
            args = [arg.arg for arg in node.args.args]
            functions.append({
                "name": node.name,
                "docstring": docstring,
                "args": args,
                "line": node.lineno
            })
    return functions

def generate_api_docs(function_docs: list[dict], format: str = "markdown") -> str:
    """Use Claude to generate formatted API documentation."""
    client = anthropic.Anthropic()

    prompt = f"""Convert these extracted function docstrings into professional {format} API documentation.
Include request/response examples, error codes, and rate limits where applicable.

Functions:
{json.dumps(function_docs, indent=2)}

Generate {format} that would appear in an API reference guide."""

    message = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=2048,
        messages=[{"role": "user", "content": prompt}]
    )
    return message.content[0].text

# Usage
docs = extract_function_docs("api.py")
markdown = generate_api_docs(docs, format="markdown")
print(markdown)

GPT-4 for Markdown Documentation

GPT-4 generates clear, user-friendly Markdown documentation quickly.

Example: From code to user guide

Prompt:
Convert this FastAPI code into a comprehensive getting-started guide
for developers. Include authentication setup, example requests/responses,
and common errors.

[Paste code]

GPT-4 generates polished guides faster than Claude, though with slightly less technical precision.

Tool Comparison: Documentation Generation

Tool Strength Best For Cost
Claude API Detailed OpenAPI specs, understands complex types Production API specs $0.003/1K tokens
GPT-4 User-friendly guides, examples Developer guides, tutorials $0.03/1K tokens
Swagger Editor AI Live spec editing, validation Interactive spec building Free (open source)
Speakeasy SDK generation from specs Multi-language SDKs $199/month+
Mintlify Template-based docs site Polished docs site Free tier available

Workflow: Comment → OpenAPI → Website

Step 1: Extract comments

# Use AST parsing for Python, similar tools for other languages
python extract_docs.py api.py > extracted_comments.json

Step 2: Claude generates OpenAPI

cat extracted_comments.json | claude-api \
  "Generate OpenAPI 3.0 spec from these comments" > openapi.yaml

Step 3: Validate spec

# Use built-in validators
swagger-cli validate openapi.yaml

Step 4: Generate docs site

# Use Swagger UI, ReDoc, or Mintlify
docker run -p 8080:8080 \
  -v $(pwd)/openapi.yaml:/spec/openapi.yaml \
  swaggerapi/swagger-ui

Code Example: End-to-End Documentation Generation

#!/usr/bin/env python3
"""
Automated API documentation generator.
Extracts comments from FastAPI app and generates OpenAPI spec.
"""

import ast
import json
from typing import Any
import anthropic
import yaml

class APIDocGenerator:
    def __init__(self, api_file: str):
        self.api_file = api_file
        self.client = anthropic.Anthropic()

    def extract_endpoints(self) -> list[dict[str, Any]]:
        """Extract FastAPI endpoint definitions and docstrings."""
        with open(self.api_file, 'r') as f:
            content = f.read()

        tree = ast.parse(content)
        endpoints = []

        for node in ast.walk(tree):
            if isinstance(node, ast.FunctionDef):
                # Look for decorators like @app.post, @app.get
                decorators = [
                    d.attr if hasattr(d, 'attr') else str(d)
                    for d in node.decorator_list
                ]
                if any('app.' in str(d) for d in decorators):
                    endpoints.append({
                        "function": node.name,
                        "docstring": ast.get_docstring(node),
                        "decorators": decorators,
                        "args": [arg.arg for arg in node.args.args]
                    })

        return endpoints

    def generate_openapi_spec(self, endpoints: list[dict[str, Any]]) -> dict:
        """Use Claude to generate OpenAPI spec from endpoints."""
        message = self.client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=4096,
            messages=[
                {
                    "role": "user",
                    "content": f"""Generate an OpenAPI 3.0.3 specification (valid YAML) from these FastAPI endpoints.
Include detailed schemas, examples, error responses, and security definitions.

Endpoints:
{json.dumps(endpoints, indent=2)}

Return ONLY valid YAML (no markdown code blocks, no explanations)."""
                }
            ]
        )

        spec_yaml = message.content[0].text
        return yaml.safe_load(spec_yaml)

    def save_openapi_yaml(self, spec: dict, output_file: str = "openapi.yaml"):
        """Save OpenAPI spec to YAML file."""
        with open(output_file, 'w') as f:
            yaml.dump(spec, f, default_flow_style=False, sort_keys=False)
        print(f"OpenAPI spec saved to {output_file}")

    def generate_markdown_docs(self, endpoints: list[dict[str, Any]]) -> str:
        """Generate Markdown documentation from endpoints."""
        message = self.client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=2048,
            messages=[
                {
                    "role": "user",
                    "content": f"""Generate professional Markdown API documentation from these endpoints.
Include examples, parameter descriptions, and error codes.

Endpoints:
{json.dumps(endpoints, indent=2)}

Generate well-structured Markdown with sections for each endpoint."""
                }
            ]
        )
        return message.content[0].text

# Usage
if __name__ == "__main__":
    generator = APIDocGenerator("api.py")

    # Extract endpoints
    endpoints = generator.extract_endpoints()
    print(f"Found {len(endpoints)} endpoints")

    # Generate OpenAPI spec
    spec = generator.generate_openapi_spec(endpoints)
    generator.save_openapi_yaml(spec)

    # Generate Markdown docs
    markdown = generator.generate_markdown_docs(endpoints)
    with open("API_DOCS.md", "w") as f:
        f.write(markdown)
    print("Markdown docs saved to API_DOCS.md")

Best Practices

1. Write clear docstrings: AI generates better docs from detailed comments.

# Good - Claude can extract this
def transfer_funds(source_id: str, destination_id: str, amount: float):
    """
    Transfer funds between accounts.

    Args:
        source_id: Unique identifier of source account (must be active)
        destination_id: Unique identifier of destination account
        amount: Transfer amount in USD (min $0.01, max $1,000,000)

    Returns:
        Transfer confirmation with transaction ID and timestamp

    Raises:
        ValueError: Invalid account IDs or amount out of range
        RuntimeError: Insufficient funds or account frozen
    """

2. Include examples in comments: AI uses these in documentation.

# Example in comment - AI extracts for docs
"""
curl -X POST /transfers \
  -H "Authorization: Bearer token" \
  -d '{"source_id": "acc_123", "destination_id": "acc_456", "amount": 50.00}'
"""

3. Specify rate limits and auth in comments

"""
Rate limit: 100 requests per minute per account
Authentication: Bearer token (JWT) required
Webhook events: transfer.completed, transfer.failed
"""

Keeping Docs in Sync with Code Changes

The biggest documentation problem is not generation — it is staleness. API docs that drift from the actual implementation erode developer trust faster than having no docs at all.

Treat documentation generation as part of your CI/CD pipeline rather than a manual step. Add a workflow job that regenerates the OpenAPI spec on every push to main and commits the result:

# .github/workflows/docs.yml
name: Regenerate API Docs

on:
  push:
    branches: [main]
    paths:
      - 'api/**/*.py'
      - 'src/**/*.py'

jobs:
  regenerate-docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - name: Install dependencies
        run: pip install anthropic pyyaml fastapi
      - name: Generate OpenAPI spec
        run: python generate_docs.py
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
      - name: Commit updated spec
        run: |
          git config --local user.email "docs-bot@example.com"
          git config --local user.name "Docs Bot"
          git add openapi.yaml API_DOCS.md
          git diff --staged --quiet || git commit -m "docs: regenerate API docs from code"
          git push

This approach eliminates documentation drift entirely for teams that already use CI. The cost per regeneration is typically under $0.10 for a medium-sized API.

Language-Specific Comment Extraction Strategies

Different languages need different extraction approaches. Python’s ast module works well, but TypeScript, Go, and Java each have better-suited tooling.

TypeScript with TSDoc: TypeScript projects using TSDoc can use the @microsoft/tsdoc parser to extract structured comments programmatically. The parsed output includes parameter descriptions, return types, and examples that map directly to OpenAPI request/response schemas.

Go with go/doc: Go’s standard library includes go/doc for parsing godoc comments. An AI-assisted workflow extracts function signatures and their associated comments, then uses Claude to generate REST endpoint documentation even though Go’s HTTP handlers often lack the explicit structure of FastAPI.

Java with Javadoc: Java’s javadoc tool produces XML output that AI can consume directly. Pass the Javadoc XML to Claude with a prompt asking for OpenAPI 3.0 output, and it resolves cross-references between @param, @return, and @throws tags into proper schema definitions.

The universal principle: get your comment data into a structured intermediate format (JSON or XML) before handing it to the AI. Unstructured text extraction produces inconsistent documentation quality.

Validating AI-Generated OpenAPI Specs

AI-generated OpenAPI specs frequently contain subtle errors: incorrect schema references, missing required fields in the top-level info object, or invalid HTTP status codes. Always validate before publishing.

# Install validation tools
npm install -g @stoplight/spectral-cli swagger-cli

# Validate with Spectral (checks style + correctness)
spectral lint openapi.yaml

# Validate with swagger-cli (checks schema validity)
swagger-cli validate openapi.yaml

Spectral supports custom rulesets, letting you enforce your team’s API design standards automatically — for example, requiring all endpoints to have a description, or flagging generic 400 responses without a response schema.

Add both validators to your CI pipeline and treat spec validation failures the same as test failures: block the PR until resolved. This creates a positive feedback loop where developers improve their code comments because they see immediate feedback when the AI-generated docs fail validation.

Choosing the Right Tool for Your Documentation Needs

The comparison table in this guide covers Claude and GPT-4 as AI backends, but the most important decision is not which AI to use — it is which documentation format to target.

Start with OpenAPI generation even if you only plan to display Markdown docs initially. A valid OpenAPI spec is reusable: tools can generate client libraries, test suites, and mock servers from it at any time.

Built by theluckystrike — More at zovo.one