API documentation generated from code comments tends to be incomplete — developers document the “what” but skip the “why”, error cases, and usage examples. AI tools have moved the state of the art from “generate docstrings” to “generate complete API reference pages with examples, error tables, and usage patterns.”
Tools Compared
- Mintlify Writer — AI docstring and docs generation integrated into IDEs
- Speakeasy — Generates SDKs and docs from OpenAPI specs
- Swimm — Documentation that stays synchronized with code changes
- Claude / GPT-4o — Direct LLM approach for one-off doc generation
What Complete API Documentation Includes
For a REST endpoint:
## POST /api/v1/payments
### Authentication
Bearer token required. Token must have `payments:write` scope.
### Request Body
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
| amount | integer | Yes | 1 - 10,000,000 | Amount in cents |
| currency | string | Yes | ISO 4217 | 3-letter currency code |
| source | string | Yes | Stripe token | Payment source token |
### Response (201 Created)
```json
{
"id": "pay_1234abc",
"amount": 2999,
"currency": "USD",
"status": "pending",
"created_at": "2026-03-21T14:22:00Z"
}
Error Codes
| Status | Code | Description | |—|—|—| | 400 | invalid_amount | Amount is zero or negative | | 402 | card_declined | Card declined by issuer | | 422 | source_expired | Payment token is expired |
Most teams have the request body section. The error codes table and usage example are where documentation breaks down.
## Mintlify Writer
Mintlify Writer is a VS Code extension that generates docstrings and documentation from function code.
```python
# Before: undocumented FastAPI endpoint
@router.post("/payments")
async def create_payment(
payload: PaymentCreateRequest,
current_user: User = Depends(get_authenticated_user),
db: Session = Depends(get_db),
) -> PaymentResponse:
if payload.amount <= 0:
raise HTTPException(status_code=400, detail="invalid_amount")
charge = stripe.charge.create(
amount=payload.amount,
currency=payload.currency,
source=payload.source,
)
payment = Payment.create(db, charge, current_user.id)
return PaymentResponse.from_orm(payment)
Mintlify Writer generates:
"""
Create a new payment transaction.
Processes a payment charge through Stripe using the provided payment source.
Args:
payload: Payment creation data including amount (in cents), currency, and source token.
current_user: Authenticated user making the request.
db: Database session (injected by dependency).
Returns:
PaymentResponse: Created payment record with transaction ID and status.
Raises:
HTTPException (400): If amount is zero or negative.
HTTPException (402): If Stripe declines the charge.
"""
The docstring is accurate and useful. Weakness: doesn’t document the request body fields individually, and misses error codes not visible from the function body.
Speakeasy
Speakeasy starts from OpenAPI specs and generates SDKs, reference docs, and usage guides.
pip install speakeasy-cli
speakeasy generate openapi --source ./app/main.py --out openapi.yaml
speakeasy generate docs --schema openapi.yaml --out ./docs
Speakeasy’s OpenAPI generation from FastAPI is strong. The generated spec includes all routes with request/response schemas. The main differentiator: it generates SDK code (Python, TypeScript, Go, Java) from the spec, with authentication handling and error types built in.
Limitation: the generated OpenAPI spec often misses error details that aren’t in the Pydantic model (exceptions thrown deep in the stack).
Swimm
Swimm focuses on documentation that stays current. It links doc sections to specific code locations and alerts you when the code changes without a doc update.
# Webhook Processing
Webhooks are verified using HMAC-SHA256 before processing. The verification
key is read from the `WEBHOOK_SECRET` environment variable.
<!-- Swimm links to: src/webhooks/processor.ts:processWebhook -->
The [`processWebhook` function](../src/webhooks/processor.ts) validates
the signature before dispatching to the appropriate handler.
When processWebhook is renamed or its signature changes, Swimm marks the documentation as “out of sync” and requires a review before the PR can merge. Swimm is about keeping existing documentation accurate — not generating new documentation from scratch.
Using Claude for One-Off API Documentation
For generating complete documentation for undocumented APIs, a structured Claude prompt produces thorough output:
Generate complete API reference documentation for this endpoint.
Include: description, authentication requirements, all request body fields
with types/constraints, response schema with example, all possible error codes
with causes, and a curl example.
Here is the FastAPI route code:
[paste route function]
Here is the Pydantic request model:
[paste PaymentCreateRequest model]
Here are all the custom exceptions this endpoint can raise:
[paste exception classes]
With all models and exceptions provided, Claude generates documentation that includes every error code and request field constraint — including the ones not visible from the route function alone.
Example Claude error table output:
| Status | Code | Cause |
|---|---|---|
| 400 | invalid_amount | Amount field is zero, negative, or exceeds 10,000,000 cents |
| 400 | invalid_currency | Currency is not a valid ISO 4217 code |
| 402 | card_declined | Issuer declined the charge |
| 402 | insufficient_funds | Card has insufficient balance |
| 422 | source_expired | Stripe token has been used or is expired |
Comparison: When to Use Each Tool
| Tool | Best For | Cost |
|---|---|---|
| Mintlify Writer | Docstring generation as you code | Freemium |
| Speakeasy | OpenAPI to SDKs + reference docs | Paid |
| Swimm | Keeping existing docs current | Paid |
| Claude (direct) | Complete one-off documentation | API cost |
The pragmatic workflow: generate an OpenAPI spec from FastAPI/Express automatically, use Claude to generate human-readable reference pages with error tables and examples, then use Swimm to prevent those pages from going stale.
Generating TypeScript Types from API Responses
A useful doc artifact is a TypeScript client library. Most teams hand-maintain this.
# Using Speakeasy to auto-generate SDKs from OpenAPI
speakeasy generate sdk \
--schema openapi.yaml \
--out ./client-sdk-ts \
--lang typescript
This generates:
// auto/generated/client.ts
export interface PaymentCreateRequest {
amount: number; // in cents
currency: string; // ISO 4217 code
sourceToken: string; // Stripe token
}
export interface PaymentResponse {
id: string;
amount: number;
currency: string;
status: "pending" | "completed" | "failed";
createdAt: Date;
}
export class PaymentsClient {
async createPayment(request: PaymentCreateRequest): Promise<PaymentResponse> {
// implementation
}
}
Type-safe client code generated from the same schema that documents the API. No manual type duplication.
Interactive Documentation with Examples
Tools like Mintlify or ReadTheDocs can render markdown docs with embedded examples:
## POST /api/v1/payments
Create a payment charge through our gateway.
### Example Request
cURL:
\`\`\`bash
curl -X POST https://api.example.com/api/v1/payments \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 2999,
"currency": "USD",
"source": "tok_4242424242424242"
}'
\`\`\`
Python:
\`\`\`python
import requests
response = requests.post(
"https://api.example.com/api/v1/payments",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"amount": 2999,
"currency": "USD",
"source": "tok_4242424242424242"
}
)
payment = response.json()
Mintlify automatically renders code blocks with syntax highlighting and tabs for language selection.
Error Documentation Best Practices
The most useful error docs include:
- HTTP Status Code — What the client receives
- Error Code — Machine-readable identifier (e.g., “INSUFFICIENT_FUNDS”)
- User-Facing Message — What to show in UI
- Developer Notes — How to fix it in code
- Retry Strategy — Is this retryable? Exponential backoff?
Example:
### Error: 402 Payment Required
**Code:** `card_declined`
**Message (to show users):** "Your card was declined. Please try another payment method or contact your bank."
**Developer Notes:**
This error occurs when the payment processor (Stripe, etc.) declines the charge.
Common causes:
- Insufficient funds
- Card expired
- Card flagged for fraud
- Processing limits exceeded
**Retry Strategy:** Do NOT retry automatically. This error requires user intervention.
Inform the user and request a different payment method.
**Example Response:**
\`\`\`json
{
"error": {
"code": "card_declined",
"message": "Your card was declined",
"charge_id": "ch_1234abc",
"processor_message": "Card declined - contact issuer"
}
}
\`\`\`
Maintaining Docs During Refactors
Using Swimm or similar tools prevents docs from going stale during refactors.
Scenario: You rename an API endpoint from /api/v1/users to /api/v2/users.
Without doc linking:
- Docs stay outdated until someone manually updates them (days or weeks later)
- New developers follow old docs and hit 404s
With Swimm:
- Create a doc linked to the route definition:
<!-- Swimm links to: src/routes/users.ts:getUsersHandler --> The [`/api/v2/users` endpoint](../src/routes/users.ts) lists all users... -
When the route file changes, Swimm marks the doc as “out of sync”
- PR merges are blocked until the doc is reviewed and updated
This forces synchronization — outdated docs can’t be merged.
Cost Breakdown for Documentation Tools
| Tool | Setup | Monthly | Per-Endpoint Cost |
|---|---|---|---|
| Mintlify Writer (free) | 10 min | $0 | ~5 min docstring generation |
| Mintlify (paid) | 30 min | $29 | Hosting, analytics |
| Speakeasy SDK generation | 20 min | $0 (SDK) / varies (paid) | Automatic from OpenAPI |
| Swimm | 60 min (initial docs) | $49 | Doc sync auditing |
| Claude (direct) | 5 min per endpoint | API cost (~$0.01 per endpoint) | Most flexible |
For a 50-endpoint API:
- Mintlify Writer: 4 hours generation (free)
- Speakeasy: 20 min setup (free SDK generation)
- Claude direct: 50 min at ~$0.50 total cost
- Swimm: Setup takes time, pays off when docs change frequently
Related Articles
- AI Tools for Automated API Documentation from Code Comments
- Best AI Tools for Generating API Documentation From Code
- Best AI for Generating API Reference Documentation from Jsdo
- ChatGPT vs Claude for Writing API Documentation
- Claude vs ChatGPT for Converting REST API Documentation
Built by theluckystrike — More at zovo.one