Software Development with AI 10 min read Updated Jul 15, 2026

How to Write API Documentation With AI From Your Code

An endpoint exists but its docs don't, so "document this API" from code alone invents parameters, status codes, and an auth flow that were never real. Here's how to write API documentation with AI from the facts you provide, with unknowns flagged and checked against the real API.

Build an API Docs Prompt

When the endpoint works but nobody can tell how

The endpoint ships, and the docs never do. A teammate integrating against `POST /orders` guesses at the field names, gets a 422 they can't explain, and pings you to ask what the API actually wants. So you paste the handler into an AI and say "write the documentation for this API." It returns something that looks authoritative — an overview, a parameters table, an example response — and about a third of it is invented. It documents a `200` the endpoint never returns, describes an `Authorization` scheme the code doesn't use, and shows an example body missing the one required field. Anyone who follows it will hit the same 422 your teammate did, now with a document telling them they're doing it right.

The fix starts with what API documentation actually is: not prose about code, but an accurate contract — what the endpoint is for, how you authenticate, the exact request fields, a real response example, the errors it returns, and the limits it enforces. The model can draft all of that quickly, but only from what you actually give it — the code, the routes, real request and response examples, the auth mechanism, the behaviors you've observed. What NewPrompt gives you is the structure for that prompt, nothing more: it doesn't connect to your repository, API gateway, or a running endpoint, call the API, run your code, or check that the docs are true. The draft is a candidate you verify against the real implementation, because the model documents the API you described to it — not necessarily the one you shipped.

Why documenting from code alone drifts from the truth

Handing a model a code snippet and asking for docs feels like it should be exact — the answer is right there in the code. But a handler doesn't contain everything a consumer needs, and where the code is silent, the model fills in with what usually happens. Five kinds of drift result:

  • It invents status codes. The code returns a created resource; the model documents a generic `200 OK` instead of the `201` it actually sends, or lists a `500` the endpoint has no path to — plausible HTTP, wrong for this API.
  • It assumes an auth flow. Unless the auth is right there in the snippet, the model describes the most common scheme — a bearer token, an API key header — which may not be how this endpoint is actually protected.
  • It writes examples that don't run. A request body missing a required field, a header the API ignores, a value in the wrong format — the example looks real and fails on the first call.
  • It skips the errors. Happy-path docs are easy; the `422` on a bad field, the `409` on a duplicate, the rate-limit `429` are where integrators actually get stuck, and a code-only pass rarely covers them because the failure paths aren't all in one place.
  • It states undocumented behavior as fact. Whether the endpoint is idempotent, how it paginates, what it does on a partial failure — the model will often assert an answer rather than admit the code doesn't show it, turning an unknown into a confident, wrong line.

Step 1: Give the model the real API facts, not just the code

The draft is only as accurate as the inputs, so assemble more than the handler. Gather the route and method, the request the endpoint really expects (fields, types, which are required, formats), a real response body you've captured, the actual authentication it uses, the error responses you've seen, and any behavior you know from using it — pagination, idempotency, rate limits. A captured request/response pair is worth more than a paragraph of code, because it shows what the API does rather than what the code might do. Where you only have the code, say so, and where you have observed behavior, mark it as observed.

Be explicit about the boundary of what you're supplying. If you're documenting one endpoint, give the model that endpoint's facts and tell it not to generalize to routes it hasn't seen. If a field's format or a status code isn't something you can confirm, leave it out of the inputs rather than guessing — a gap you name is one the model can flag, but a wrong fact you supply is one it will faithfully document. The discipline here is the same one that separates real docs from fiction: the documentation describes what you can show, and marks the rest as to be confirmed.

Step 2: Ask for a fixed documentation structure

Ask for the docs in a fixed shape so nothing important gets skipped and every endpoint reads the same way: an overview of what the API area does, authentication, then per endpoint the purpose, the request parameters as a table, a runnable request example, a real response example, the error responses, and any rate limits or constraints. A consistent structure is what makes documentation usable — a developer learns where to look once and finds it in the same place for every endpoint.

The Markdown Output Builder builds a prompt that holds that structure — fixed headings and forced parameter tables and examples — so the model returns human-readable docs in a stable layout rather than a loose paragraph. The API Documentation Prompt is that setup already shaped for endpoints: Overview, Authentication, Endpoints, Error Handling, and Rate Limits, with parameter tables and runnable examples required, and it's clear about its lane — it writes human documentation, not a machine-readable OpenAPI schema. If you also need the response format pinned down precisely, defining that is the JSON Output Prompt Builder's job, separate from the prose docs. All of them build a prompt you run on your own material in your own AI tool.

Step 3: Forbid invention and flag what the code doesn't show

The rule that keeps docs honest is one line in the prompt: document only what the supplied material supports, and where it doesn't support something, write "not documented — confirm" rather than a plausible value. That turns the model's most dangerous habit — asserting an answer to look complete — into a visible flag you can resolve. A parameter whose format you didn't supply, a status code the code doesn't clearly return, an auth detail that isn't in the snippet: each becomes a marked gap, not a confident fiction that a reader will trust.

Undocumented behavior is where this matters most, because it's exactly what integrators need and exactly what a snippet often omits. Is the endpoint idempotent? How does it paginate? What happens on a partial failure? Tell the model that if the answer isn't in what you gave it, the correct line in the docs is "behavior not confirmed — verify against the API," not a guess dressed as a spec. A doc that admits three unknowns you then go and confirm is far more valuable than one that answers all three confidently and is wrong on two.

Step 4: Reconcile what the code says with what the API does

Code and live behavior aren't always the same thing, and documentation has to describe the behavior a consumer will actually get. A middleware you didn't paste may add an auth requirement the handler doesn't show; a validation layer may reject a field the handler appears to accept; a gateway may enforce a rate limit the code knows nothing about. So when you have both the code and an observed response, and they disagree, the observed behavior usually wins for the docs — and the disagreement itself is worth a note, because it often points at a layer you forgot to include.

Have the model surface these conflicts rather than silently pick a side: if the code implies one thing and your supplied example shows another, it should flag the mismatch for you to resolve, not average them into a confident sentence. Resolving it is a judgment for whoever owns the docs — you might trust the observed response, or realize the example was from an old version, or discover the missing middleware. Either way, the reconciled answer comes from you checking the real system, not from the model deciding which of your inputs it likes better.

Step 5: Verify the draft against the real API, then publish

The draft looks finished, which is exactly why it needs a pass before anyone integrates against it. Run the request examples against the real endpoint and confirm they work as written; check that the documented status codes are the ones it actually returns; confirm the auth is real by making an authenticated and an unauthenticated call; and try one error case — a missing field, a bad token — to see the failure the docs promise. Every "not documented — confirm" flag from the earlier steps is a checklist item here: resolve it against the running API, not against the model's guess.

This verification is yours to run, not NewPrompt's. NewPrompt structures the documentation prompt; it doesn't call your endpoint, execute your code, read your repository, or confirm a single response — the checking happens in your own environment, against your own API. Once the examples run, the codes match, and the flagged unknowns are resolved, the docs are true enough to publish; until then, they're a well-organized draft. Treat publication as the moment the documentation becomes a promise to every consumer who reads it — and only you can confirm the promise matches the API you actually shipped.

Common mistakes

The habits that ship documentation nobody can integrate against:

  • Documenting from the handler alone. A snippet omits middleware, gateways, and observed behavior; supply real request/response examples and the actual auth, not just the code.
  • Accepting invented status codes and auth. The model defaults to a generic `200` and a common auth scheme; require every code and auth detail to trace to what you supplied, or be flagged.
  • Shipping examples you never ran. A request body missing a required field reads fine and fails on the first call; run each example against the real endpoint before publishing.
  • Covering only the happy path. Integrators get stuck on the `422`, the `409`, the `429`; make the error responses a required section, not an afterthought.
  • Letting unknowns become confident lines. Idempotency, pagination, partial-failure behavior — if the material doesn't show it, the doc should say "confirm," not guess.
  • Trusting the draft as the docs. It describes the API you told the model about; verifying it against the API you shipped, and owning what's published, is yours — NewPrompt doesn't touch the endpoint.

A worked example: documenting POST /orders

Take a single endpoint, the code-only guess it produces, and the accurate documentation you get from the real facts.

A code-only pass invents a 200, an auth scheme, and a thin request; the fact-based draft documents the real 201, the required fields, the errors integrators hit, and flags the two things the code couldn't confirm
THE CODE-ONLY GUESS (what "document this API" invents):
  POST /orders
  Auth: Bearer token          <- assumed; not in the snippet
  Request: { items: [...] }    <- missing required fields
  Response: 200 OK { order }   <- endpoint actually returns 201
  Errors: 500 Internal Error   <- invented; no such path shown

THE FACTS YOU SUPPLY (from real requests/responses + what you know):
  - route: POST /orders ; auth: Bearer <token> (verified by a 401 test)
  - required: customer_id (uuid), items (non-empty array), currency (ISO)
  - optional: idempotency_key (header) -> observed: repeat key returns the
    same order (idempotent) BUT code snippet doesn't show it -> mark observed
  - success: 201 Created { order_id, status: "pending", total }
  - errors seen: 401 (no/invalid token), 422 (validation), 409 (duplicate
    idempotency_key with a different body)
  - rate limit: unknown -> not supplied

THE DOCUMENTATION IT DRAFTS (fixed structure, invention forbidden):
  ## POST /orders
  Purpose: create an order for a customer.
  Authentication: Bearer token (401 if missing or invalid).
  Request parameters
    | field           | in     | type   | required | notes                |
    | customer_id     | body   | string | yes      | uuid                 |
    | items           | body   | array  | yes      | non-empty            |
    | currency        | body   | string | yes      | ISO 4217             |
    | idempotency_key | header | string | no       | observed: idempotent |
  Example request / response
    -> { "customer_id": "...", "items": [...], "currency": "USD" }
    <- 201 { "order_id": "...", "status": "pending", "total": 42.00 }
  Errors: 401 (auth), 422 (validation), 409 (idempotency-key reuse, new body)
  Rate limits: NOT DOCUMENTED -- confirm against the API
  Idempotency: observed as idempotent on repeat key -- VERIFY (not in code)

STILL YOUR JOB:
  run the example against the real endpoint, confirm 201 and the error codes,
  test one 401 and one 422, and resolve the two flags. NewPrompt didn't call
  the API -- you did.

Where this fits in NewPrompt

Writing docs is one step in keeping documentation honest, and it sits inside a larger loop. The AI Code Documentation Workflow is that loop — have the model explain what the code really does, write it up as structured docs, then validate the format holds — and API documentation is the endpoint-shaped case of it. The pieces are small: the Markdown Output Builder holds the fixed doc structure, the API Documentation Prompt tunes it for endpoints (human docs, not OpenAPI), the JSON Output Prompt Builder pins a response format when you need it precise, and the Explain API Flow resource is where you first work out what an endpoint actually does before you document it. None of them reads your repo, calls your endpoint, or verifies a response — they structure the writing; the facts and the checking are yours.

It helps to tell this apart from its neighbors. Explaining code helps you understand an implementation for yourself; reviewing an API design judges whether the contract is well-shaped before you build it; a README introduces a whole project to a new user. This is narrower and consumer-facing: given an endpoint that already exists, produce the accurate reference someone integrates against — request, response, errors, and limits — from the facts you supply. And it is emphatically not an OpenAPI generator: it writes prose humans read, not a machine schema, and if any asset were framed as producing one it would be wrong to say so.

The reason to get this right is that documentation is trusted more than code. A developer integrating against your API reads the docs, not the handler, and builds on whatever the docs claim — so a confidently wrong line costs every consumer who follows it, and costs you the support tickets when they hit the reality the docs hid. A draft built from real facts, honest about its unknowns, and checked against the running endpoint is a promise you can keep. Writing that draft takes the model a minute; the part that decides the outcome takes you — running the examples, checking the codes, resolving the flags, and standing behind a reference every consumer will trust.

Tools for this guide

Each generates the prompt described above — you run it in your own AI assistant.

Ready-made resources

Reusable prompts and templates for the exact steps in this guide.

Take it further

When this task is one step inside a larger workflow or build.

FAQ

Does NewPrompt read my repository, call my API, or check that the docs are correct?

No. NewPrompt builds a documentation prompt in your browser — it doesn't connect to your source control, repository, or API gateway, call a running endpoint, run your code, or verify a single response. You paste your own code, routes, request/response examples, and auth details into your own AI tool and run the prompt there; the draft comes back to you. Checking that the examples run, the status codes are right, and the auth is real happens in your own environment, against your own API — NewPrompt structures the writing, it doesn't touch the system you're documenting.

Why does the AI invent parameters, status codes, or an auth flow that aren't real?

Because a code snippet doesn't contain everything a consumer needs, and where it's silent, the model fills the gap with what's most common rather than admitting the gap. So it documents a generic 200 instead of your real 201, assumes a bearer token because that's typical, or writes an example missing a required field. The fix is two rules in the prompt: document only what your supplied material supports, and flag anything it doesn't with "not documented — confirm." That turns the guessing into visible checklist items. It doesn't remove your verification step — the draft is only as accurate as the facts you give it, and you confirm the rest against the real endpoint.

Can it generate an OpenAPI / Swagger spec from my code?

No — this produces human-readable documentation, not a machine-readable schema. The prompt structures prose a developer reads: overview, authentication, endpoints, parameters, examples, errors, and limits. An OpenAPI or Swagger file is a different artifact with different tooling, and NewPrompt doesn't read your code or emit a spec. If you need a precise response format defined, that's a separate structured-output job; the documentation here is the readable reference, written from the facts you provide and verified by you against the running API.

How is this different from explaining the code or reviewing an API design?

They answer different questions. Explaining code helps you understand an implementation for your own sake — what a function does and why. Reviewing an API design judges whether a contract is well-shaped before you commit to building it. This one assumes the endpoint already exists and produces the consumer-facing reference someone integrates against: the request fields, a real response, the errors, and the limits — accurate to what you supply and verified against the live API. You'd explain code to learn it, review a design to improve it, and document the API so others can use it.