How to Auto-Generate Internal API Documentation with Claude
How to build a documentation pipeline that extracts your route table deterministically, uses Claude to describe only real endpoints, regenerates on every merge — and what to do about the forgotten endpoints the first run always finds.
Published
The short answer: Extract the route table from your codebase deterministically first, then let Claude describe only those endpoints — parameters, responses, error semantics — and regenerate on every merge through CI. Grounding the model in a real list is what stops it inventing endpoints. Expect the first run to surface things nobody knew were still exposed.
Every engineering team has the same document. It was written carefully when the service launched, it was accurate for about five weeks, and it now describes three endpoints that no longer exist while omitting the eleven added since. Nobody trusts it, so nobody updates it, so it decays further. New joiners read the source instead, which is what the document was supposed to prevent.
The decay is structural rather than cultural. Documentation lives in one system and changes in another, and only a person noticing the gap connects them. That is exactly the kind of mechanical, high-context, low-judgement work a language model does well — provided you constrain what it is allowed to claim.
Why Do Internal API Docs Always Rot First?
Internal docs decay faster than public ones for reasons worth naming, because each one shapes how you automate.
No external pressure. A public API breaks customers when its docs are wrong. An internal one breaks a colleague, who walks over and asks, and the workaround becomes tribal knowledge instead of a documentation fix.
The author moves on. Internal services are often written by one or two people who hold the whole model in their heads. When they change teams, the docs stop being a summary of shared understanding and become the only record — right at the moment nobody is maintaining them.
Documentation is not in the definition of done. Merging requires tests and a review. It rarely requires a docs update, so the doc is always a step behind by design.
Nobody knows the true endpoint count. Services accumulate debug routes, internal admin paths, a health check somebody extended, and endpoints for a feature that was deprecated but never removed. Any documentation effort that starts from what people remember starts from an incomplete list.
That last point is the important one, and it changes the shape of the solution: the goal is not to write prose faster. It is to derive the list of endpoints from the code itself, so the documentation cannot silently omit what nobody remembers.
What Can Claude Actually Generate From a Codebase?
Endpoint Reference, Examples, and Error Semantics
Given a route handler and the types it touches, a model reliably produces the descriptive layer: what the endpoint is for, what each parameter means, what a realistic request and response look like, and which errors the code can actually return. This is the bulk of an API reference by volume, and the part engineers most dislike writing.
It is also good at the connective tissue that hand-written docs skip. Which endpoints require which authentication. What the pagination convention is. Which fields are nullable and under what conditions. Whether an operation is idempotent. These are readable from the code but tedious to compile by hand, and their absence is what makes a reference technically complete and practically useless.
Two honest limits. First, the model describes what the code does, not what it should do — if the implementation contradicts the intended contract, you get documentation of the bug. Second, it cannot know undocumented business context: why a field exists, which consumer depends on the odd behaviour, or that a parameter is ignored in production because of a config flag. Those still come from people.
Should the Source of Truth Be Code, a Spec, or Both?
Most frameworks can already emit an OpenAPI specification from annotations or type definitions, and that machine-generated spec is a much better foundation than a model reading files. It is exhaustive by construction and cannot hallucinate a route that does not exist.
So use both, in a specific order. Generate or extract the spec deterministically — from framework annotations, or by parsing your router definitions — and treat that as the authoritative list of endpoints and their shapes. Then pass it to the model along with the relevant handler code and ask for descriptions, examples, and prose. The model enriches; it does not enumerate.
This ordering is the single most important design decision in the pipeline. A model asked to "document this repository" will produce plausible endpoints that do not exist, and their plausibility is precisely what makes them hard to catch in review. A model asked to "describe these fourteen endpoints, and say so if the code is unclear" is working within a fact it cannot invent around.
A Practical Pipeline — Generate, Review, Publish, Regenerate
Start by extracting the route table on every merge to your main branch. Framework tooling, a build-time spec generator, or a small script that parses router files — whatever is deterministic. This artefact is the contract.
Diff it against the previous run. Most merges change nothing relevant, and only regenerating prose for what changed keeps cost and review load proportionate. A new endpoint, a changed signature, or a removed route triggers work; a refactor that touches no interface does not.
For each changed endpoint, send the model the spec entry, the handler source, the types it references, and the previous description if one exists. Ask it to preserve human edits where they remain accurate and flag where they no longer match the code, rather than overwriting them — otherwise every carefully-written explanation gets replaced by generic prose on the next run, and the team stops adding them.
Then publish through review, not directly. The pipeline should open a pull request against a docs repository or your wiki rather than committing generated content unattended. This keeps a human in the loop cheaply, gives you a diff to skim rather than a document to read, and means a bad generation is a rejected PR instead of a published error. Where the docs live matters less than that they are generated rather than remembered — the same principle covered in our piece on keeping Confluence documentation in sync with Claude.
AI-Generated Docs vs Spec-First Tooling vs Hand-Written Docs
- Coverage — Spec-first tooling wins outright. It documents every route by construction, while a model-only approach documents what it was shown and hand-written docs document what someone remembered.
- Readability and usefulness — AI-generated wins. A raw OpenAPI render tells you a field is a string; the useful version tells you what to put in it and what happens if you get it wrong.
- Accuracy of the endpoint list — Spec-first wins, and this is the one that matters most. Never let a model be the source of the list.
- Staying current — Spec-first and AI-generated both win over hand-written, because both regenerate automatically. Hand-written docs are accurate exactly once.
- Capturing intent and business context — Hand-written wins. Why an endpoint exists and which consumer depends on its quirk is not in the code.
- Setup effort — Hand-written wins short-term, spec-first is moderate if your framework supports it, and a full AI pipeline with CI integration and review flow is the largest investment.
The combination that works is all three: spec-first for the list, AI for the description, and humans for intent — with the pipeline preserving human edits rather than steamrolling them.
What This Exposes — and Why That Is the Real Value
The first full run of a pipeline like this is usually more interesting than the documentation it produces.
Endpoints nobody remembers. Debug routes from an incident two years ago, an admin path added for a one-off migration, a v1 that was supposed to be retired when v2 shipped. Each is a live, reachable surface.
Missing or inconsistent authentication. Compiling which endpoints enforce which checks is exactly the exercise that reveals the handler where the middleware was never applied. It is rarely malicious and almost always a refactor that moved a route out from behind a guard.
Secrets in examples and fixtures. Models generating example requests draw on what they were shown, and test fixtures are full of real-looking tokens that are sometimes real. Scan generated output for credential patterns before publishing — and treat anything found as a live secret to rotate.
Undocumented internal-only assumptions. Endpoints safe because "only the internal network can reach them", which is a statement about network topology someone made three architecture changes ago.
The honest response to a list of forgotten, possibly-unauthenticated endpoints is not a wiki page. It is a test of whether they are reachable and what they expose, which is what penetration testing is for. Documentation tells you what you have; only testing tells you whether it is safe — and "we just discovered forty endpoints nobody remembered" is one of the better reasons to book one.
Getting This Right — Source-Code Confidentiality, API Keys, and When to Bring in IT
Sending proprietary source code to a third-party model is a real decision, not a formality, and it deserves a deliberate answer rather than an engineer's individual judgement in the moment.
Read the terms that apply to the specific tier you are using — commercial and API tiers commonly differ from consumer products on retention and training, and terms change, so check current documentation rather than what a colleague remembers. Then decide scope: many organisations are comfortable sending application code and firmly not comfortable sending anything from a repository holding customer data fixtures, cryptographic material, or code under a client confidentiality clause. Write that boundary down, because the alternative is each engineer deciding privately.
The mechanics matter too. The pipeline needs a repository token and a model API key living in CI. Use short-lived, least-privilege credentials scoped to the specific repositories, store them in your CI provider's secrets store rather than in configuration files, and rotate them on a schedule someone actually owns. A generation pipeline with broad organisation-wide read access is a meaningful piece of your attack surface. Our AI+ support practice covers building this kind of tooling with those controls in place from the start, and managed IT support handles the identity, access and secret lifecycle around it once more than one team depends on it. Brocent has run managed IT across Asia since our founding in Beijing in 2007, with headquarters in Singapore and a Hong Kong office since 2016.
Frequently Asked Questions
Is it safe to send proprietary source code to an AI model?
It depends on the tier and the code, and it should be a documented decision rather than a per-engineer judgement. Check what the provider's current terms say about retention and training for your specific plan, and set an explicit boundary on which repositories are eligible — application logic is a very different question from a repository containing credentials, customer data fixtures, or code covered by a client confidentiality obligation.
Will it hallucinate endpoints that do not exist?
Yes, if you let it enumerate. That is why the route list must come from deterministic extraction — framework spec generation or parsing your router definitions — and the model's job is restricted to describing entries on that list. Constrained this way, invented endpoints stop being a realistic failure mode.
How do we keep the docs in sync with the code?
Trigger regeneration in CI on merge rather than on a schedule or by hand. Diff the extracted spec, regenerate only what changed, and open a pull request for review. Anything requiring someone to remember to run it will drift within a quarter.
What do we do about endpoints it finds that nobody documented?
Triage rather than document. For each one, establish whether it is still used, what authentication it enforces, and what it exposes. Remove what is dead, secure what is live, and only then write it up. Documenting an unauthenticated forgotten endpoint just publishes it more clearly.
Will it overwrite explanations our engineers wrote?
Only if you build it that way, and it is the failure that kills adoption. Pass the existing description in as context and instruct the model to preserve accurate human text, flag what no longer matches the code, and add only what is missing. If engineers see their explanations replaced by generic prose, they stop writing them.
Does this replace an OpenAPI spec?
No — it depends on one. The spec is the authoritative machine-readable contract that also drives client generation and testing. This pipeline adds the human-readable layer on top, which is the part a raw spec render does poorly.
Where to Start
Pick one service, ideally a mid-sized internal one that people complain about. Extract its route table deterministically and compare that list against whatever documentation exists — that comparison alone is usually the moment the project gets funded. Then generate descriptions for the endpoints that survive triage, wire regeneration into CI behind a pull request, and set the credential scope before you widen it to other repositories. If the first run turns up endpoints nobody can account for, and you would rather know what they actually expose than guess, get in touch.
Share:
Ready to take action?
Turn these insights into a roadmap for your business.
Book a 15-minute no-obligation consultation with our APAC IT experts. We'll review your current setup and provide a tailored IT roadmap within 24 hours.
Free Checklist
10 Critical Checks Before Expanding IT to Greater China
PIPL compliance, network segmentation, bilingual helpdesk setup, and more — everything your IT team needs before Day 1 in China.
Request the checklist →📬 Monthly Asia IT Insights
China compliance updates, cybersecurity alerts, and IT tips for APAC teams — once a month.
No spam. Unsubscribe anytime.