Evolutiondocumentationexamplesguidesreferencecontract

Documentation Is Part of the Contract

For every consumer you never meet, the docs are the API. What must be documented is exactly what consumers are forced to assume — auth, errors, pagination, rate limits, idempotency, guarantees — and the examples are the most-executed code you ship. Undocumented behavior gets reverse-engineered and depended on anyway.

Follow the failure

Frame the contract

API design starts with a consumer, a design question and a guarantee — never with a URL.

Design question
Can a developer who will never talk to your team integrate correctly — including failure handling — from the docs alone?
Consumers
The developer at a partner company on a deadline, the internal engineer three teams away, the agent selecting operations from your reference — everyone whose only interface to your intentions is what you wrote down. For a public API, that is essentially everyone.
The promise
Complete docs guarantee that correct integration — happy path *and* failure path — is achievable from the written material alone, and that what is written is the truth the server actually serves.
RequirementConsumersResource ModelStyleContractValidationAuthorizationErrorsIdempotencyPaginationVersioningObservabilityEvolutionTrade-offs

The checklist is the contract's table of contents

What belongs in API docs is not a style question — it is derivable: everything a consumer is forced to assume must be written down, because whatever you leave out gets reverse-engineered from behavior and depended on anyway (What an API Contract Actually Is's core argument, now applied to prose). The checklist below is that principle unrolled. Most real docs cover the first three entries and stop; every entry after "operations" is where integrations actually go wrong, because the happy path is easy to guess and the guarantees are not.

Structure follows audience task. Getting-started answers "make one successful call in five minutes" — auth setup through first 200, nothing else; its length is your adoption funnel. Guides answer "accomplish this task" (accept a payment, process a webhook) as ordered walkthroughs. Reference answers "exactly what does this operation do" — generated from the spec so it cannot drift (see OpenAPI: Describing the Contract, Not Designing It), fleshed with the behavioral prose the spec cannot hold. The changelog and migration guides answer "what changed and what must I do" (see Deprecation as a Process, Not a Label). These four serve different moments in a consumer's life; a docs site that is only reference has abandoned the first and last moments to support tickets.

Examples are executable claims — and failure needs them most

Developers integrate by copying examples: the example is often the only part of the page that gets read, and it is certainly the part that gets pasted into production code. That gives examples a quality bar higher than prose — realistic values (not "foo"), consistent entities across pages (the same ord_812 traced through creation, retrieval and webhooks becomes a corpus that teaches the object model by osmosis), and mechanical verification: examples extracted and run against a real environment in CI, because a broken example is a bug that every new consumer hits on day one. Docs that cannot be tested drift exactly like specs that are not diffed (see Testing the Contract, Not Just the Code).

The examples that separate adequate docs from good ones are the failure examples. Every consumer will meet your 422, your 409 and your 429 — most docs never show them, so every consumer's error handling is improvised. Show the full exchange for each error family: what triggers it, the exact body, and what the client should *do* — parse which field, retry after what, surface what to whom. This is also where honesty pays twice: documented failure behavior is failure behavior consumers can code against, which converts your error taxonomy from an internal design into a working contract (see The Error Model: Structure Over Apology).

The example most docs omit: a failure, with the handling spelled out
Request
POST /v1/payments HTTP/1.1
Authorization: Bearer sk_test_…
Idempotency-Key: 8c1f4b2a-77aa-4f0e-9c1d-2e5a6b7c8d9e
Content-Type: application/json

{
  "amount": 1999,
  "currency": "EUR",
  "source": "card_expired_visa"
}
Response
HTTP/1.1 402 Payment Required
Request-Id: req_01J8ZQ…
Content-Type: application/json

{
  "error": {
    "code": "card_expired",
    "message": "The card has expired.",
    "request_id": "req_01J8ZQ…",
    "retryable": false
  }
}

Handling: not retryable — do NOT retry the same source.
Surface error.message to the payer; collect a new payment
method; reuse a fresh Idempotency-Key for the new attempt.

Docs drift like code, and honesty is a feature

Documentation has the same enemy as specs: drift. The server changes; the prose does not; consumers now integrate against fiction that carries your logo. The defenses are structural, not moral. Generate the reference from the governed spec so shapes cannot drift (see Schema-First vs Code-First). Test the examples in CI so they cannot rot. Put docs changes in the definition of done for every contract change — the PR that alters behavior updates the page, or it does not merge. And date or version the guides, because a 2024 walkthrough silently wrong about 2026 behavior is worse than a page that says "outdated" on it.

Two habits mark documentation written by teams that have been consumers themselves. First, document the sharp edges: cursor expiry windows, eventual-consistency delays ("the object may take up to a few seconds to appear in list results" — see Consistency as a Contract Clause), rate-limit interactions with batch endpoints. Every documented limitation is a support ticket pre-answered and a trust deposit; the alternative is consumers discovering the edge in production and wondering what else you did not mention. Second, write the non-guarantees — error text may change, field order is not promised, new enum values will appear. Those sentences are what keep your own evolution options open (Backward Compatibility: The Real Rules is enforceable only if consumers were told the rules).

Reference-shaped, truth-shaped hole
1GET /v1/orders
2Returns the orders.
3
4Parameters:
5 limit (integer, optional)
6
7Response: 200 OK
8{ "data": [ Order ] }
9
10# unstated: default/max limit, order,
11# pagination, staleness, error shapes,
12# whether new fields/enum values appear.
13# every consumer now assumes answers.
The same endpoint, documented as a contract
1GET /v1/orders
2Lists orders, newest first (created_at desc,
3id desc tiebreakordering is guaranteed).
4
5limit: default 25, max 100. Results are
6paginated (cursorsee Pagination guide);
7new orders may take ~1s to appear (see
8Consistency). Responses MAY gain fields
9and `status` MAY gain values without
10noticesee Compatibility rules.
11
12Errors: 401, 403, 422 (examples below).

The left version documents the shape and leaves every guarantee to the consumer's imagination. The right version costs six sentences and answers precisely the questions whose wrong guesses become integration bugs and support load.

Key points

  • For consumers you never meet, docs are the API: whatever is undocumented gets reverse-engineered and depended on anyway.
  • The checklist is derivable — auth, errors, pagination, limits, idempotency, guarantees, change policy — because it is exactly what consumers are otherwise forced to assume.
  • Four structures for four moments: getting-started, task guides, spec-generated reference, changelog/migration — reference alone abandons the first and last to support.
  • Examples are the most-executed code you ship: realistic, consistent across pages, and run in CI — and failure examples matter more than happy-path ones.
  • Fight drift structurally: generated reference, tested examples, docs-in-definition-of-done, dated guides.
  • Documented limitations and explicit non-guarantees are features — they pre-answer support tickets and keep your evolution rights intact.

Follow the failure

How the contract fails or gets misused, hop by hop — and what it costs when it completes.

  1. 1
    Team → docs: publishes an endpoint list with parameter tables; guarantees, errors and limits feel obvious to the people who built them, so nobody writes them.
  2. 2
    Consumers → docs: copy the one happy-path example, guess at error handling, and infer pagination and ordering from observed behavior.
  3. 3
    Server → change: a deploy changes default ordering — a behavior no doc ever promised but every consumer inferred.
  4. 4
    Consumers → support: integrations misbehave; tickets ask questions the docs should have answered; the team answers them one by one, in private, forever.
  5. 5
    Docs → fiction: two years of undocumented changes later, even the team routes around the docs — the real contract now lives in a support engineer's head.
What breaks
  • Every consumer improvises failure handling: retries on non-retryable errors (duplicate side effects), no backoff on 429s, error strings parsed as API (see Retryability: Telling Clients What To Do Next).
  • Support load scales with consumer count instead of flattening — each undocumented answer is delivered privately N times rather than written once.
  • Docs drift converts documentation from asset to liability: consumers integrate against fiction with your name on it, and discovering which pages are true becomes their job.

Design, observe, evolve

A contract decision is incomplete until you know how you would notice it failing and how it changes later.

Design the contract
  • • Write docs against the checklist and review them like contract text — a missing guarantees section is a defect, not a style gap.
  • • Generate reference from the governed spec, and hand-write the behavioral prose the spec cannot hold (idempotency, consistency, extensibility) next to each operation.
  • • Test examples in CI against a real environment, keep one consistent entity cast across all pages, and show a full request/response exchange for every error family.
  • • Make docs part of the definition of done for any contract change, and date or version every guide so staleness is visible instead of silent.
Observe in production
  • • Cluster support tickets by which doc page should have answered them — the cluster map is your docs backlog, ranked by real cost.
  • • Track time-to-first-successful-call for new consumers (sandbox telemetry): it is the getting-started guide's quality, measured.
  • • Watch integration errors per endpoint (422 shapes, retry storms after 429): they concentrate where failure documentation is thinnest.
Evolve without breaking
  • • Docs are where evolution meets consumers: deprecation notices, changelogs and migration guides are documentation artifacts, and their credibility is set by the docs' everyday accuracy (see [[deprecation]]).
  • • Spec-generated reference inherits contract governance for free — every approved spec diff updates the reference; the prose half still needs the definition-of-done rule to keep pace (see [[api-migration]]).
  • • Written non-guarantees compound: each one is a future change you can make without a migration program, which is the cheapest evolution capital an API accumulates.
What it costs
  • • Complete docs are genuinely expensive — writing, example plumbing, CI verification, upkeep on every change — and the payoff accrues to consumers and future support load, not to this sprint.
  • • Documented guarantees are commitments: every promise written down (ordering, consistency, limits) constrains the implementation exactly as [[what-is-an-api-contract]] says it will.
  • • Internal APIs justify a thinner version — generated reference plus a guarantees paragraph may be the right cost — but "thinner" is a chosen point on the same checklist, not an exemption from it (see [[public-vs-internal-apis]]).

Misconceptions

Claim
“Our OpenAPI reference is complete documentation.”
Reality
The reference documents shapes. Getting-started, task guides, failure examples, and the guarantee prose (idempotency, consistency, extensibility, limits) are the parts consumers get burned without — and none of them live in the spec (see OpenAPI: Describing the Contract, Not Designing It).
Claim
“Good APIs are self-documenting; if we need docs, the design is bad.”
Reality
A guessable design reduces the reference burden — it cannot express guarantees. No URL naming convention tells a consumer whether a retry double-charges, how long a cursor lives, or whether status gains values. Those are sentences, and someone must write them.
Claim
“Documenting our limits and consistency delays makes the API look bad.”
Reality
Consumers hit the limits either way; the only choice is whether they hit them with a documented answer or in production with a mystery. Honesty converts sharp edges from incidents into handled cases — and it is the providers who hide edges that lose integrator trust.