Docs & Code Guide

Keep API docs in sync with code: one spec, everything else regenerates

The way to keep documentation in sync with the actual API is to stop maintaining documentation about the API and start maintaining one machine-readable spec that everything else renders from. Reference pages, SDKs, mock servers, and changelogs can all regenerate from an OpenAPI document; hand-written prose that restates endpoints cannot, and that prose is the part that is always wrong. Here is the workflow, the two CI gates that keep the spec honest, and where the architecture picture fits.

8 min readFor teams whose API reference lags the deployed API

See it as a diagram

Everything below, as a diagram you can edit. Describe yours and see it in seconds.

203/20003 credits left
Try:

No account needed · Editable canvas, not a picture

Spec-first or code-first, but never docs-first

There are two working versions of this loop. Spec-first: you write the OpenAPI document before the code, review API changes as spec diffs, and generate server stubs and SDKs from it. Code-first: annotations in the code produce the spec on every build, the way FastAPI derives it from route signatures, springdoc from Spring controllers, or drf-spectacular from Django serializers. Both are fine. What fails is docs-first, where a human describes endpoints in a wiki after the fact.

The choice matters less than the invariant it buys you: in both workflows the spec is generated or reviewed in the same pull request as the code, so it cannot silently lag. The wiki page describing the API has no such mechanism. It drifts the day after it is written, which is why the search phrase "api documentation out of date" exists at all.

Two CI gates: Spectral for quality, oasdiff for breakage

A spec that regenerates from code can still degrade: missing descriptions, undocumented error responses, breaking changes nobody announced. Two open-source tools gate this in CI. Spectral lints the spec against a ruleset, so you can fail a build that ships an operation without a description or a response without a schema. oasdiff compares the pull request spec against the base branch spec and classifies every change, and its breaking mode fails the build on removed endpoints, narrowed enums, or new required parameters.

Together they turn API docs review into a diff review. The reviewer no longer reads the whole reference looking for lies; they read a machine-produced changelog of what this PR does to the contract.

# .github/workflows/api-contract.yml
name: api-contract
on:
  pull_request:
    paths: ["openapi.yaml"]
jobs:
  contract:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - name: Lint the spec (descriptions, schemas, operationIds)
        run: npx @stoplight/spectral-cli lint openapi.yaml
      - name: Fail on breaking contract changes
        run: |
          git show origin/main:openapi.yaml > /tmp/base.yaml
          docker run --rm -v /tmp:/tmp -v "$PWD":/work -w /work \
            tufin/oasdiff breaking /tmp/base.yaml openapi.yaml --fail-on ERR

Render the reference from the spec, never write it by hand

The reference portal should be a renderer, not a copy. Redoc and Stoplight Elements render an OpenAPI document directly, so deploying the spec is deploying the docs. Swagger UI adds a try-it console on top of the same file. Hosted portals work the same way when you feed them the spec on every merge: ReadMe, for instance, syncs an OpenAPI file through its rdme CLI in CI, so the published reference is regenerated rather than edited.

Once the portal renders the spec, the only prose left to maintain by hand is the part machines cannot know: guides, auth walkthroughs, the reasons behind rate limits. That is a small enough surface to keep honest with ordinary review. Tools like Swimm exist for coupling that remaining prose to code if you need enforcement there too.

The spec cannot carry the landscape picture

One thing an OpenAPI document does not describe is how the API sits in the system: which services live behind the gateway, what each one owns, which third parties you call. That picture is usually a slide from two reorgs ago. It deserves the same regenerate-not-redraw treatment as the reference.

Datadef's AI import accepts an OpenAPI-style spec pasted as the prompt, so the first version of the landscape diagram comes from the contract you already maintain; the API architecture diagram generator is the fastest way in. From there the diagram is editable, and an AI agent connected to Datadef's MCP server (registry name io.datadef/mcp) can update it from what it reads in the repo, on request or as a CI step after merge. Datadef does not watch the repository by itself; the update is one agent call away, which is the honest version of automatic. The full loop is described in living diagram from OpenAPI.

Shared public, the diagram has a permanent image URL you can embed in the portal or the README, and an edit shows up in the embed within minutes.

Where the spec-first loop strains

Datadef diagrams the API landscape; it does not sync prose API references. If your reference pages are hand-written and drifting, the fix is the spec-rendering workflow above with tools like Redoc, ReadMe, or Stoplight, not a diagram tool. Datadef earns its place on the architecture view next to the reference, not in place of it.

The live embed also requires the project to be shared public. For a confidential internal API map, the embed URLs are not available, and a periodically re-exported image inside the private wiki is the honest fallback.

The one-sentence answer

Make the OpenAPI spec the only source of truth, gate it with Spectral and oasdiff in CI, render the reference from it, and regenerate the landscape diagram from the same spec instead of redrawing it.

FAQ

How can I keep documentation in sync with the actual API?

Maintain one OpenAPI spec as the source of truth and regenerate everything else from it. Either write the spec first and generate code from it, or generate the spec from code annotations on every build. Lint the spec with Spectral in CI, fail builds on breaking changes with oasdiff, and publish the reference through a portal that renders the spec directly, such as Redoc or Stoplight Elements. Hand-written endpoint prose is the part that drifts, so keep as little of it as possible.

Should I go spec-first or code-first with OpenAPI?

Both keep docs in sync, so pick by team habit. Spec-first means API changes are designed and reviewed as spec diffs before implementation, which suits public APIs with many consumers. Code-first means frameworks like FastAPI or springdoc generate the spec from the code on each build, which suits fast-moving internal APIs. The invariant that matters is that the spec changes in the same pull request as the code.

What do oasdiff and Spectral each do in CI?

Spectral lints an OpenAPI document against a ruleset: missing descriptions, missing response schemas, naming rules. oasdiff diffs two versions of the spec and classifies the changes; its breaking mode fails the build on removed endpoints, new required parameters, or narrowed types. Spectral keeps the spec complete, oasdiff keeps the contract stable.

Can Datadef keep my API reference documentation up to date?

No. Datadef generates and updates architecture and data diagrams; it does not sync prose API references. For reference pages, render them from your OpenAPI spec with a tool like Redoc, ReadMe, or Stoplight. Datadef covers the adjacent gap: the API landscape diagram, generated from a pasted spec and updated through its MCP server by an AI agent or a CI job.

How does an API architecture diagram stay in sync with the code?

By being regenerated from a real artifact instead of redrawn from memory. A Datadef diagram can be created from a pasted OpenAPI spec, and an AI agent connected to the Datadef MCP server can update it from the repository after a merge or on request. Nothing watches the repo automatically; the regeneration is one agent call or CI command. Embedded by URL in a public project, the updated diagram appears wherever it is embedded within minutes.