API documentation is the interface to your interface. It’s the first thing a developer touches after deciding your API might solve a problem, and it’s often the last thing they read before walking away from the integration. For teams of 20–200 engineers, documentation isn’t a nice-to-have artifact. It’s a support-cost multiplier, an adoption lever, and a quiet statement about how seriously you take the people building on your work. This article covers REST APIs, webhooks, SDK generation, and the internal documentation systems that keep them honest. It’s not about GraphQL, except where the contrast clarifies a REST decision.
Good API documentation cuts down on “how do I…” tickets, shortens time-to-first-call, and makes your API feel predictable. Bad documentation does the opposite: it creates a shadow support team, breeds workarounds, and turns your changelog into a horror story. The goal here is practical, no-nonsense guidance for mid-to-senior engineers who own or influence documentation at companies where the API is a product, not a side effect.

Start with the Developer’s First Question: “What Can I Do with This?”
Most API docs fail before the first endpoint. They open with authentication, base URLs, and a wall of parameters. That’s like handing someone a map of the kitchen before telling them what’s for dinner. The first 150 words of your documentation should answer three questions: what is this API for, what can I build with it, and what do I need to know before I start. If a developer can’t answer those questions in under a minute, you’ve already lost them.
For a REST API, that means a short, concrete overview with a real use case. Not “Our API provides programmatic access to your data.” Something like: “Create a webhook that fires when an invoice is paid, then use the Invoices endpoint to fetch the line items and post them to your accounting system.” That sentence tells a developer what the API does, what they can build, and which endpoints matter. It also sets the stage for the semantic cluster that follows: resources, representations, HTTP methods, status codes, pagination, rate limits, and error handling.
Adjacent concepts matter here. Developers will look for terms like idempotency, webhook signatures, sandbox environments, API keys, OAuth scopes, and versioning. If your documentation doesn’t use those words in the places developers expect them, they’ll assume the feature doesn’t exist. That’s not a documentation problem; it’s a trust problem.
Structure Documentation Like a Decision Tree, Not a Novel
Developers read documentation in short, goal-directed bursts. They’re not reading for pleasure. They’re trying to answer a question and get back to their code. Your structure should reflect that. Use a hierarchy that moves from concept to task to reference, and make each level scannable.
The Three-Layer Model
Most effective API documentation follows a three-layer model:
- Concepts – what the API does, how it thinks about resources, and the mental model behind it.
- Guides – step-by-step instructions for common tasks, like “Create your first webhook” or “Handle pagination.”
- Reference – the endpoint-by-endpoint details: methods, parameters, request bodies, response schemas, and error codes.
This isn’t a new idea. It’s the same structure used by Stripe, Twilio, and most developer tools that people actually enjoy using. The difference is that those teams treat the three layers as a single system, not three separate documents. A developer should be able to jump from a concept to a guide to a reference without losing context.
For a REST API, the reference layer is where most of the pain lives. Every endpoint should include:
- The HTTP method and path, with a clear description of what it does.
- Authentication requirements, including scopes or roles.
- Request parameters, with types, defaults, and constraints.
- A request example that actually works.
- A response example with the full schema, not a truncated version.
- Error codes and what they mean in plain language.
If you’re generating SDKs from an OpenAPI specification, the reference layer is also your source of truth. That means the spec must be complete and accurate, not just “good enough for the docs site.” A missing nullable field or an undocumented error code will show up as a bug in every generated SDK. That’s a maintainability problem, not a documentation problem.

Write for the Developer Who Is Slightly Annoyed
Your reader isn’t a blank slate. They’ve probably integrated with other APIs, and they have opinions about how those integrations went. They’re slightly annoyed because they have to learn yet another API, and they’re hoping yours won’t waste their time. Write for that person.
That means:
- Use the imperative mood. “Call
POST /invoicesto create an invoice.” Not “ThePOST /invoicesendpoint can be used to create an invoice.” The first sentence tells the developer what to do. The second tells them what’s possible. They want the first. - Put the example first. Show the request and response before explaining every parameter. Developers learn by pattern matching, not by reading prose.
- Be specific about errors. “Returns a 400 error if the
amountis negative” is more useful than “Returns an error for invalid input.” The first sentence tells the developer what to fix. The second tells them to guess. - Avoid jargon that only your team uses. If you call something a “ledger entry” internally, but every other API calls it a “transaction,” use “transaction.” Consistency with the wider ecosystem reduces cognitive load.
Dry humor has a place here, but only if it doesn’t mock the reader. A note like “If you send a DELETE request to /invoices, you will delete all invoices. This is not a bug. It is a feature with excellent documentation.” That kind of aside can make a dense reference page feel less like a tax form. But use it sparingly. The goal is to deflate hype, not to turn your docs into a stand-up routine.
Webhooks: Document the Contract, Not Just the Payload
Webhooks are the part of API documentation that most teams get wrong. They document the payload, but they forget the contract. A webhook isn’t just a POST request to a customer’s server. It’s a promise about delivery, retries, ordering, and security. If you don’t document that promise, developers will build fragile integrations and then blame you when they break.
For every webhook event, document:
- The event name and trigger. What exactly causes this event to fire? Is it fired once per resource, or can it fire multiple times?
- The payload schema. Include every field, even the ones that seem obvious. A missing
idfield will cause more support tickets than any other single omission. - Delivery semantics. Do you retry failed deliveries? How many times? What’s the backoff schedule? Do you guarantee at-least-once or at-most-once delivery?
- Security. How do you sign requests? What header contains the signature? How should the receiver verify it? If you don’t document this, developers will either ignore it or invent their own scheme.
- Ordering. Are events delivered in the order they occurred? If not, say so. A developer who assumes ordering and then sees events arrive out of order will spend hours debugging a problem that isn’t theirs.
Here’s a before-and-after example for a webhook section:
Before:
POST /webhooks/invoice.paid
Body: { "invoice_id": "inv_123" }
After:
POST /webhooks/invoice.paid
Trigger: Fires when an invoice transitions to paid status.
Delivery: At-least-once. Retries up to 5 times with exponential backoff.
Ordering: Not guaranteed. Use the event timestamp to order events.
Security: Signed with HMAC-SHA256. Signature in X-Signature header.
Body: {
"invoice_id": "inv_123",
"amount_paid": 1000,
"currency": "usd",
"paid_at": "2025-01-15T14:30:00Z"
}
The second version answers the questions a developer will actually ask. The first version creates those questions.
SDK Generation: Documentation as a Build Artifact
If you generate SDKs from an OpenAPI specification, your documentation isn’t just a website. It’s a build input. That changes how you write it. Every description, every example, every schema constraint becomes part of the generated code. A vague description like “The amount” becomes a useless comment in the SDK. A missing enum becomes a stringly-typed parameter that invites bugs.
Treat your OpenAPI spec as code. Review it in pull requests. Lint it for missing descriptions, inconsistent naming, and invalid examples. Run a contract test that verifies the spec matches the actual API behavior. If the spec and the API disagree, the SDK will be wrong, and the documentation will be a lie. That’s worse than no documentation at all.
For teams that maintain SDKs in multiple languages, the spec is the single source of truth. That means the spec must be complete enough to generate idiomatic code in each language. A field that’s optional in the API but required in the SDK is a bug. A response schema that omits a nullable field will cause a runtime error in a strongly typed language. These aren’t documentation issues; they’re API design issues that documentation exposes.
One practical approach: write the spec first, then generate the documentation and the SDKs from it. If the spec is good, both outputs are good. If the spec is bad, you’ll see the problems in both places, which is exactly what you want. The alternative—writing docs and SDKs by hand and trying to keep them in sync—is a recipe for drift and resentment.

Internal Documentation Systems: The API Docs You Don’t Publish
Not all API documentation is public. Internal APIs—the ones your own frontend, mobile apps, and services use—need documentation too. In fact, they need it more, because the consumers are your colleagues, and they won’t hesitate to interrupt you with questions.
An internal documentation system for APIs should answer the same questions as a public one, but with a different audience. Your colleagues already know the domain. They don’t need a conceptual overview of what an invoice is. They need to know which endpoint to call, what permissions they need, and what changed in the last deploy.
Practical tips for internal API docs:
- Keep them close to the code. A
docs/folder in the same repository is easier to maintain than a separate wiki. If the docs aren’t in the pull request, they won’t be updated. - Document the contract, not the implementation. Your colleagues don’t need to know which database table backs an endpoint. They need to know the request and response shapes, the error codes, and the rate limits.
- Use a changelog. Every breaking change should be documented in a way that’s easy to scan. A developer who upgrades a dependency and sees a new error should be able to find the explanation in under a minute.
- Make the docs searchable. If your internal docs are a pile of Markdown files with no search, they’re not docs. They’re a scavenger hunt.
Internal documentation is also where you can be more candid. You can write “This endpoint is slow because it does a full table scan. Don’t call it in a loop.” That kind of note would be embarrassing in public docs, but it’s exactly what your colleagues need to avoid a production incident.
Checklist: Before You Publish
Here’s a checklist you can use before publishing or updating API documentation. It’s not exhaustive, but it covers the failures that cause the most developer pain.
- Can a new developer make their first successful API call in under 10 minutes? If not, the getting-started guide is too long or too vague.
- Does every endpoint have a working request example? Copy-paste the example and run it. If it fails, fix it.
- Are all error codes documented with plain-language explanations? “500 Internal Server Error” isn’t an explanation. “500: The request timed out because the upstream payment provider didn’t respond” is.
- Are webhook delivery semantics documented? Retries, ordering, and security aren’t optional details.
- Is the OpenAPI spec linted and tested? If you generate SDKs, the spec is code. Treat it that way.
- Does the changelog clearly mark breaking changes? A developer should never discover a breaking change by reading a stack trace.
- Are the docs searchable and scannable? Headings, tables, and code blocks should do the heavy lifting. Prose should be short.
Decision Matrix: REST vs. GraphQL for Documentation Effort
This article is about REST, but a brief contrast with GraphQL can clarify a documentation decision. If you’re choosing between REST and GraphQL for a new API, the documentation burden is a real factor.
| Factor | REST | GraphQL |
|---|---|---|
| Endpoint discovery | Each resource has a predictable path. Docs list endpoints. | Single endpoint. Docs must explain the schema and query language. |
| Response shape | Fixed per endpoint. Easy to document with examples. | Client-defined. Docs must show many query examples. |
| Error handling | HTTP status codes plus a body. Straightforward to document. | Mostly 200 with errors in the body. Requires careful documentation of error types. |
| Versioning | Usually via URL or header. Docs can show versioned examples. | Often no versioning. Docs must explain deprecation and schema evolution. |
| SDK generation | OpenAPI spec is mature and widely supported. | Schema introspection is possible, but SDK generation is less standardized. |
For a team of 20–200 engineers, REST often wins on documentation effort because the tooling is more mature and the mental model is simpler. GraphQL can be the right choice for complex, client-driven data needs, but the documentation burden is higher. That’s not a reason to avoid GraphQL; it’s a reason to budget for it.
FAQ
How long should API documentation be?
Long enough to answer every question a developer will ask, and no longer. A good rule of thumb: the getting-started guide should be under 500 words. The reference for each endpoint should be under 300 words, not counting examples. If you need more than that, the API is probably too complex, or the documentation is repeating itself.
Should I document every possible error code?
Yes, but group them. Document the errors that are specific to each endpoint, and have a shared section for common errors like authentication failures, rate limits, and validation errors. A developer should never see an undocumented error code. If your API can return it, your docs should explain it.
How do I keep documentation in sync with the API?
Generate it from a spec, and test the spec against the API. If you’re using OpenAPI, run a contract test in CI that verifies the spec matches the actual responses. If you’re not using a spec, start. Hand-written docs that aren’t generated from a spec will drift. It’s not a question of if; it’s a question of when.
What is the most common mistake in API documentation?
Omitting the “why.” Developers don’t just need to know what an endpoint does; they need to know when to use it and what happens if they use it wrong. A parameter description like “The amount” isn’t documentation. “The amount to charge, in the smallest currency unit (e.g., cents for USD). Must be positive. If negative, the API returns a 400 error.” That is documentation.
For more on how documentation fits into a broader engineering culture, see our upcoming piece on internal documentation systems and how they reduce support load. If you have a documentation horror story or a pattern that works, send it in. We read everything, and we’re not afraid to name names—politely.










