API Documentation skill for Claude Code

First successful call in under five minutes. Claude treats the OpenAPI spec as the single source for reference and writes guides that link into it. Every endpoint gets real request and response examples in curl, JavaScript and Python, every error code gets a cause and a fix, and cross-cutting pages cover auth, pagination, rate limits, idempotency and webhooks. The spec is linted and checked against the running API so it cannot drift.

  • nameapi-documentation
  • size246 lines · ≈2,250 tokens
  • files1
  • licenseMIT
  • updated

What Claude sees before loading it

This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.

description: Writes HTTP API documentation developers can integrate from without asking questions — a quickstart to the first successful call, authentication, per-endpoint reference with request and response examples in curl and SDK languages, error catalog, pagination, rate limits, idempotency, webhooks, and versioning — driven from an OpenAPI 3.1 spec that is linted and checked against the running API. Use when documenting a REST API, writing or fixing an OpenAPI spec, building an API reference page, or when integrators keep filing support tickets.

Try asking

  • Write API docs for our billing endpoints, starting from the Express routes
  • Our OpenAPI spec is missing error responses and examples. Fix it
  • Write a quickstart that gets a developer to their first successful API call

Use it when

  • Documenting a REST or HTTP API for external or internal integrators
  • Writing or repairing an OpenAPI specification
  • Integrators keep asking the same questions in support
  • Adding webhooks, pagination, or rate limit documentation

Skip it when

  • You need the docs website framework, navigation and search, use docs-site instead
  • You are designing contract tests rather than documentation, use contract-testing instead

How to check the result

Redocly lint passes, every documented curl example succeeds against the sandbox in a script, and a newcomer finishes the quickstart in under five minutes.

The common mistake it prevents

Documenting only the 200 response, so integrators discover 409, 422 and 429 behavior in production and file tickets to learn the fix.

~/.claude/skills/api-documentation/SKILL.md

--- name: api-documentation description: Writes HTTP API documentation developers can integrate from without asking questions — a quickstart to the first successful call,… license: MIT ---

API docs are done when a developer can get a successful response within five minutes of opening them, every endpoint has a copy-pasteable request and a real response, every error the API can return is documented with its fix, and the reference is generated from a spec that is validated against the running service.

Ground rules

  • The OpenAPI document is the source of truth for reference. Guides are hand-written and link into it. Never maintain endpoint details in two places.
  • Examples are real: captured from a sandbox, with realistic values ("amount": 2500, "currency": "usd"), never "string" or 0.
  • Document behavior, not just shape: defaults, limits, ordering, idempotency, side effects, and what happens on retry.
  • Every response a client must handle is documented, including 4xx and 5xx.
  • Time to first call is the metric. Optimize the quickstart before anything else.

Doc set structure

docs/api/
  quickstart.md         first authenticated call in < 5 min
  authentication.md     key types, scopes, where to get them, rotation
  errors.md             error format and catalog
  pagination.md
  rate-limits.md
  idempotency.md
  webhooks.md           events, payloads, signature verification, retries
  versioning.md         policy + changelog link
  guides/               task how-tos (e.g. "Accept a payment", "Sync users")
  reference/            generated from openapi.yaml
openapi.yaml

Workflow

- [ ] 1. Gather: routes, auth model, error shapes, limits (from code and infra config)
- [ ] 2. Write or repair openapi.yaml; lint it
- [ ] 3. Capture real request/response examples from a sandbox
- [ ] 4. Write the quickstart and cross-cutting pages
- [ ] 5. Write task guides for the top 3–5 integration jobs
- [ ] 6. Render the reference; verify spec against the running API

1. Gather from the source

grep -rnE '@(Get|Post|Put|Patch|Delete)\(|router\.(get|post|put|patch|delete)\(|@app\.(get|post|put|patch|delete)\(' src | head -50
grep -rnE 'status\((4|5)[0-9]{2}\)|HTTPException\(|raise .*Error' src | head -50

Ask the owners what the code does not show: rate-limit numbers, retention, SLA, sandbox URL, versioning policy.

2. OpenAPI 3.1 essentials

openapi: 3.1.0
info: { title: Billing API, version: "2026-10-01" }
servers:
  - url: https://api.example.com/v1
  - url: https://sandbox.api.example.com/v1
security: [{ bearerAuth: [] }]
paths:
  /invoices:
    post:
      operationId: createInvoice
      summary: Create an invoice
      description: Creates a draft invoice. Drafts are not sent until you call `POST /invoices/{id}/send`.
      parameters:
        - in: header
          name: Idempotency-Key
          schema: { type: string, maxLength: 255 }
          description: Reuse the same key to safely retry. Keys expire after 24 hours.
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/InvoiceCreate" }
            example: { customer_id: "cus_9f2k", amount: 2500, currency: "usd", due_date: "2026-11-01" }
      responses:
        "201":
          description: Invoice created
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Invoice" }
        "422": { $ref: "#/components/responses/ValidationError" }
        "429": { $ref: "#/components/responses/RateLimited" }
components:
  securitySchemes:
    bearerAuth: { type: http, scheme: bearer }
  responses:
    ValidationError:
      description: The request body failed validation.
      content:
        application/problem+json:
          schema: { $ref: "#/components/schemas/Problem" }

Rules: every operation has operationId, summary (verb phrase), description with behavior, request example, and all response codes. Schemas document format, minimum/maximum, enum, nullable via type: [string, "null"] (3.1), and readOnly fields.

Lint:

npx @redocly/cli lint openapi.yaml
# or Spectral with a ruleset file containing: extends: ["spectral:oas"]
npx @stoplight/spectral-cli lint openapi.yaml

3. Endpoint reference entry (what each must contain)

PartContent
Title + one-line purpose“Create an invoice”
BehaviorSide effects, defaults, ordering, async processing
AuthRequired scope (invoices:write)
ParametersName, in, type, required, default, constraints, description
Request examplecurl + 1–2 SDK languages
Response exampleReal JSON, success case
ErrorsCodes specific to this endpoint with causes
RelatedLinked endpoints, webhooks fired

Request examples in three forms:

curl https://api.example.com/v1/invoices \
  -H "Authorization: Bearer $EXAMPLE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c1e5a0e-2f5b-4c62-9d1d-1f0e9d0f8a11" \
  -d '{"customer_id":"cus_9f2k","amount":2500,"currency":"usd","due_date":"2026-11-01"}'
const res = await fetch("https://api.example.com/v1/invoices", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.EXAMPLE_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ customer_id: "cus_9f2k", amount: 2500, currency: "usd", due_date: "2026-11-01" }),
});
const invoice = await res.json();
import os, requests
r = requests.post("https://api.example.com/v1/invoices",
    headers={"Authorization": f"Bearer {os.environ['EXAMPLE_API_KEY']}"},
    json={"customer_id": "cus_9f2k", "amount": 2500, "currency": "usd", "due_date": "2026-11-01"},
    timeout=10)
r.raise_for_status()

4. Cross-cutting pages

Quickstart (template):

1. Get a sandbox key: Dashboard → Developers → API keys (starts with `sk_test_`).
2. Make your first call:  curl … /v1/me  → shows expected JSON
3. Create something real: curl … POST /v1/invoices → expected JSON
4. Next: Accept a payment (guide), Webhooks, Errors

Errors: document the format once (RFC 9457 problem details recommended), then a catalog.

{
  "type": "https://docs.example.com/errors/invalid-due-date",
  "title": "Invalid due date",
  "status": 422,
  "detail": "due_date must be on or after the issue date (2026-10-19).",
  "instance": "/v1/invoices",
  "request_id": "req_8f2a1c"
}
CodeHTTPCauseFix
invalid-due-date422due_date before issue dateSend a date ≥ today
customer-not-found404Unknown customer_id or wrong environmentCheck the ID exists in sandbox vs. live
rate-limited429Over 100 req/s per keyBack off; honor Retry-After

Pagination: state the style (cursor recommended), page size default and max, ordering, and show the loop:

let cursor;
do {
  const page = await list({ limit: 100, starting_after: cursor });
  handle(page.data);
  cursor = page.has_more ? page.data.at(-1).id : undefined;
} while (cursor);

Rate limits: numbers per key/endpoint, headers returned, 429 behavior, recommended backoff (exponential with jitter, honor Retry-After).

Webhooks: event list with payload examples, signature verification code, retry schedule, ordering guarantees (usually none), idempotent handling advice.

Versioning: how versions are selected (URL, header, date), deprecation notice period, link to changelog (see changelog-release-notes).

6. Render and verify

npx @redocly/cli build-docs openapi.yaml -o dist/api-reference.html

Or render with Scalar, Redoc, Stoplight Elements, or the docs-site framework’s OpenAPI plugin.

  • Contract-check the spec against the running API in CI (Schemathesis, Dredd, or schema-validating integration tests; see contract-testing). A spec that drifts from reality is worse than none.
  • Run every curl example from the docs against the sandbox in a script; fail CI on non-2xx where success is documented.

Gotchas

  • Examples with "string", 0, or true everywhere teach nothing; generated SDK docs often do this, so override with real examples.
  • Undocumented defaults (page size, sort order, timezone) become breaking changes when you change them, because clients depend on them anyway.
  • Secret-looking example keys trigger secret scanners; use an obvious fake prefix (sk_test_EXAMPLE) or an env var.
  • Missing Content-Type in curl examples produces confusing 415/400 errors for readers.
  • Documenting only 200 responses guarantees support tickets about 409, 422, and 429.
  • Changing an operationId renames generated SDK methods: a breaking change.

Verification

  • npx @redocly/cli lint openapi.yaml passes with no errors.
  • A developer new to the API (or a clean shell) completes the quickstart in under five minutes using only the docs.
  • Every endpoint has request and response examples and lists its error codes.
  • Spec-vs-implementation check runs in CI.

About this skill

Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.

esc