How do you handle API documentation and ensure it stays up-to-date?
Documentation: the docs come from the spec, not a hand-written copy
Hand-written docs are a second copy of what the code does, and copies go out of date. A spec that generates the reference, clients and checks cannot go out of date.
For this question · chapters 1 and 2 of 3
Two copies, and only one runs
- The same API shape is written down twice, but only the copy in the handler code runs. A person typed the reference page from that code some time ago. Nothing links the reference page to the handler. Every documentation problem you have ever had starts with these two unlinked copies.
- No line of code refers to the hand-written docs page. So release v1.5 changes only the handler. The handler renames the field created to created_at, removes avatar_url, and adds display_name. The docs page stays the same. So the page is now wrong in three places: one field renamed, one field removed, and one new field it never mentions.
- The commit that made the docs page wrong passes the unit tests and the integration tests. The deploy then ships v1.5 on that same commit. There is no fourth check for the docs page, so zero checks read it. Nothing you own reads that page.
- A partner has only the hand-written docs page, so the partner trusts it. Nine days later, the partner's integration sends avatar_url and reads the created field. The partner never learns that display_name exists. Now someone who does not work for you is doing your testing.
- Two calls fail in two different ways, and the quiet failure is worse. The write gets a 400 response that names the field, so the bug gets fixed within an hour. The read returns undefined with no error, so the code that makes that call ships. Both failures reach you as a support ticket, the slowest way you have to find a bug.
One spec, many outputs
- There are two ways to get one OpenAPI file. Write the file first and generate the handlers from it, or annotate the handlers and generate the file from them. Both ways produce the same file: 14 paths and 9 schemas, with 22 examples and 11 error codes. Five outputs could come from that file, but today a person types every one of them.
- The reference page is now an output of the spec file, so nobody types the page any more. Every path, field and example on the page comes from that file, so the page always matches the code. The difference from chapter one is in how the page is built. The page does not depend on anyone remembering to update it.
- In chapter one, a renamed field broke the partner's integration. Here the same spec file generates client libraries in four languages. Nobody writes those libraries by hand. So a field renamed in the spec changes in all four libraries on the next release. A build step now handles the exact change that broke the partner's integration.
- The examples in the spec file are enough for a mock server to answer requests. The mock server replies before the real endpoint exists. So your partner waits zero days and starts building on day one. The examples in a spec are also worth writing properly, because a server is going to return them.
- At the edge, the schema refuses any request with a field the schema does not define. The schema returns a 400 that names that field. So the spec file has a new role: the document that describes the API now enforces the API. A document you can run cannot be wrong without anyone noticing.
- Drift, where the code no longer matches the spec, now fails the build. In CI, contract tests use the spec file as the test fixture and check every response against the matching schema. So a handler that drops a field fails the build. Chapter one's bug would have failed the build on your machine the day the bug shipped, not nine days later in a stranger's ticket.
- Generation from the spec stops here, and this is the honest half of the answer. People write why to call this endpoint and how auth works end to end. They also write what to do about each error, and migration notes for a breaking change. An integrator reads these four documents first. Generation removes drift, but it does not write the explanation.
The same API shape is written down twice, but only the copy in the handler code runs. A person typed the reference page from that code some time ago. Nothing links the reference page to the handler. Every documentation problem you have ever had starts with these two unlinked copies.
© LearnThatStack - diagrams may not be republished without permission.
Want a quick review of the fundamentals? See the API Design cheatsheet.
74 of 92 API Design answers are in Pro.
Full answers, code samples, and AI explanations that go simpler or deeper. Cancel anytime.
- Full answers + code
- AI explanations, simpler or deeper
- 1,000 AI credits / month
- Cancel anytime