Published on 27 March 2025 by Andrew Owen
(7 minutes)
I was recently asked for my favorite resources and best practices for writing clear and structured API docs. I’ve developed my own style for writing API docs, but up until now I haven’t published it. Although I’ve mainly worked with REST APIs, this guidance applies equally to GraphQL and any other APIs. But before I get to writing style, the most important requirement for good API docs is a good API. If you’re using REST, validate it with Stoplight. If endpoints are inconsistent in how they handle common parameters, there’s no way to write around the problem. This seems to be more of an issue with REST and may account for the move away from REST toward GraphQL. The next thing that you need is static, searchable docs. Don’t expect your GraphQL users to find the information they need by browsing your schema in Apollo. Don’t expect your REST users to scroll to the bottom of the Swagger UI page to find out how to format data for a given endpoint. If you need a no-budget solution, Redocly CLI and Magidoc are good places to start for REST and GraphQL respectively. Unless you use AWS hosting (which doesn’t play nicely with Magidoc’s clean URLs). And don’t think that you’re done when you’ve published your schema. Developers need workflows, code examples and reference information to understand how they are expected to use your API. Ideally, this information should live in a public developer portal. Your rivals are not going to be able to clone your product by examining your API. And even if they start adding features based on it, you’ll always be several steps ahead.
General style guidelines
When I became an API writer I found that, just like other software, docs are often an afterthought. But if you want people to use your APIs, they need to be well documented. However, API writing isn’t the same as traditional technical writing. Use a terse, factual writing style. Sentence fragments are desirable. Avoid adjectives and adverbs. You need to provide:
Complete information about each API component.
Contact details in case developers have questions or require additional assistance.
Flow charts showing the sequence of the most commonly used methods for common use cases.
Getting Started guides showing how to develop a program for a common use cases.
Performance and tuning information.
Sample programs demonstrating common use cases.
Working code snippets for each method, function, and resource. You don’t need complete examples, but show a common use of that element.
Unless you are writing exclusively for an internal audience, use American English and don’t translate your API schema. The language should be simple enough for a developer to follow without requiring translation.
Endpoint names
lower case (except initialisms and acronyms)
descriptive (action—objects—criteria)
as brief as possible
active voice
use CRUD for the action (create, read, update, delete)
include all match criteria (example: by user or ID)
Example: read API key by ID
Endpoint descriptions
Sentence case.
descriptive (action—objects—criteria)
brief sentences
passive voice
human readable actions. Example:
POST: Creates
GET: Retrieves
PUT: Updates
DELETE: Removes
Example: Retrieves details of a registered API key for the current user by ID.
for REST provide at least the minimum boilerplate text for each response
Example: 404 Not found: The URI isn’t valid, or the requested resource doesn’t exist.
REST specific guidelines
I’ve documented the principles of REST APIs elsewhere. No-one follows them, which is why APIs are described as RESTful. HTTP methods should be used consistently for specific tasks.
Method
CRUD
Typical response code
POST
Create
201 Created
GET
Read
200 Success
PUT
Update
202 Accepted
DELETE
Delete
204 No Content
The other HTTP methods are:
HEAD — Almost identical to GET, but without the response body.
OPTIONS — Describes the communication options for the target resource.
PATCH — Applies partial modifications to a resource.
I would recommend avoiding these three in public APIs, although you may have reasons to use them internally.
Boilerplate text
One of the limitations of the current generation of Markdown and REST API doc tools is that they have little to no support for automated content reuse. For that reason, you should keep a list of standard definitions and valid payload examples. For example:
Address — Use your company’s main address.
Barcode — 019000000002 (UPC-A format including check digit)
Brand — Ownbrand (too generic to be registered as a trademark)
Country — USA (ISO 3166-1 alpha-3 format)
Credit card number — 4111111111111111 (Use any CVV, NAME and future EXPIRY DATE. Keep purchase value under $500. https://docs.stripe.com/testing)
URL — www.example.com (example.com is reserved for documentation)
HTTP response codes
You should provide as much response code information as possible. The minimum acceptable level of documentation is the number, a meaningful short description and an explanation for typical use cases.
1xx: information
100 — Continue.
101 — Switching protocols.
102 — Processing.
103 — Early hints.
2xx: success
200 — Success: Object created or fetched.
201 — Created: Object created or replaced.
202 — Accepted: Processing asynchronous request.
203 — Non-authoritative Information.
204 — No content.
205 — Reset content.
206 — Partial content.
207 — Multi-status.
208 — Already reported.
226 — Instance-manipulations used.
3xx: redirection
300 — Multiple choices.
301 — Moved permanently.
302 — Found.
303 — See other.
304 — Not modified.
305 — Use proxy.
306 — Switch proxy.
307 — Temporary redirect.
308 — Permanent redirect.
4xx: client errors
400 — Bad request: The request wasn’t valid or can’t be otherwise
served. Typical when there is a syntax error in the request. Further
details of the error are provided in the response payload body.
401 — Unauthorized: Missing or incorrect authentication credentials.
402 — Payment required.
403 — Forbidden: The request is understood, but it was refused or
access was denied. The response payload body provides further details of
the error.
404 — Not found: The URI isn’t valid, or the requested resource doesn’t exist.
405 — Method not allowed: The requested resource doesn’t support the method.
406 — Not acceptable.
407 — Proxy authentication required.
408 — Request timeout.
409 — Conflict.
410 — Gone.
411 — Length required.
412 — Precondition failed.
413 — Payload too large: The request is larger than the server is able to process.
414 — URI too long.
415 — Unsupported media type.
416 — Range can’t be satisfied.
417 — Expectation failed.
418 — I’m a teapot (don’t ask).
421 — Misdirected request.
422 — Entity can’t be processed: The request was well-formed, but the data couldn’t be processed due to semantic errors.
423 — Locked.
424 — Failed dependency.
425 — Too early.
426 — Upgrade required.
428 — Precondition required.
429 — Too many requests.
431 — Request header fields too large.
451 — Unavailable for legal reasons.
5xx: server errors
500 — Internal server error: This is usually a temporary error, for
example in a high load situation or if an endpoint is temporarily having
issues.