River
Y CombinatorBacked by Y Combinator

Writing & MediaFree

OpenAPI Spec Documentation Gap Workup

River reads your OpenAPI document and lists every field the specification leaves optional that yours never filled, with what a reader still has to ask.

Start here

Generate a reference site from an OpenAPI document and you get exactly what the document holds, formatted. That is the appeal and it is also the whole problem. A renderer has no opinion about whether a reader could act on the result, because rendering is not its job. So the finished reference set ships carrying the same blanks the document carried. The writer who assembled it is then the one asked why the docs never say what happens when a call fails.

The reason those blanks are permitted sits in the specification itself. From version 3.1 onward the Operation Object has no required field at all, twelve fields and not one of them obligatory. A response needed only a description until 3.2 made that optional too, and covering known errors is worded as an expectation rather than a rule. So a document can satisfy the OpenAPI Initiative's own schema while naming no error, no example and no description.

Stripe publishes its API description openly and it is a strong document by most measures, 419 paths and 594 operations with all but five described. That same document passes the specification's schema with zero errors. Every one of its 594 operations declares no 4xx and no 5xx. All 1,402 of its parameters carry no example, and all 594 of its request bodies carry no description. Conforming and answerable are separate questions and only one has a validator.

The rule that would have caught it ships switched off

A linter is the obvious next move and it closes less of this than expected. Ten of these gaps can be counted mechanically on any document. Take a file both common linters call clean, remove one field at a time, and read what each tool newly says. A missing operation description, a missing summary and a missing 4xx each produce a finding. The remaining seven produce nothing from either tool, including every operation that never says what a failure looks like.

Part of that is a rule that exists and is not turned on. Spectral ships 56 rules in its OpenAPI ruleset, 45 enabled by default and 11 not, and the parameter description rule is one of the eleven. Volume is not the constraint either. A default run over Stripe returns 600 findings, 594 of which report that an operation has no tags, and none of which mention the 1,188 responses that carry no example.

Formats are the subtle one. A schema can name any format it likes, because the specification treats it as a non-validating annotation and support for even a registered name is explicitly optional. A value outside the registry of 53 names is therefore legal and means nothing to any tool. Stripe carries two such values, currency and unix-time, 679 times between them, and what either one actually means lives in whatever prose happens to sit beside it rather than in the format itself.

How it works

  1. Paste the document

    The whole OpenAPI file as YAML or JSON, at whatever version it declares in its header.

  2. Check the obligations

    Each absent field is read against whether that version of the specification ever required it.

  3. Count the whole file

    Every operation, not a sample, so each gap arrives with the number of endpoints it affects.

  4. Route each question

    What only engineering can answer separates from what the document already implies you can write.

What you get

  • One row per operation, parameter and response, naming the field that is not there
  • What the specification says about that field, with the version and section it says it in
  • The question a reader would have to ask, written so an engineer can answer it directly
  • Split into what only engineering knows and what you can already draft yourself
  • Every format value in the document checked against the registry the specification points at
  • Which gaps your own linter already reports, so you do not file them twice

Common questions

My spec passes validation. Doesn't that mean it is complete?

It means it conforms, which is a different test, and only that one has a tool. From version 3.1 the Operation Object has twelve fields and no required ones, so a document naming one endpoint, one parameter and one empty response description validates with zero errors. Conformance is a question about shape. Whether someone could integrate against it is a question about content.

Doesn't a linter already find this?

Three of the ten gaps, on a default run. Removing an operation's description, its summary or its 4xx each produces a finding from one of the two common tools. Removing a parameter's description or example, a response's example or schema, a request body's description, or every 5xx in the file produces nothing at all from either one.

I cannot change the spec myself. Is this still worth running?

That is the case it is built for. The output is not a patch, it is a set of questions with the specification's own wording attached to each one, which is what makes them answerable rather than arguable. Anything the document already implies you can draft as endpoint prose yourself, and the rest becomes an SME question set for whoever owns the file.

Is this an audit of our documentation?

No, and the difference decides what you do next. A documentation audit compares published pages against how the product behaves now and finds text that has gone stale. This reads the document those pages are generated from and finds fields that were never filled in. Nothing here drifted out of date. It was absent from the first commit.

Which gaps does it put first?

The endpoints you name, then the rest in an order the output states rather than assumes. Operations with no error response at all come before those missing an example. A caller who cannot handle a failure is blocked, while a caller without an example is only slowed. Nothing external defines that order, so the output names what it sorted by instead of implying a standard.

Our spec is generated from annotations in the code.

Then the gaps are in the annotations and the list tells you which ones. It reads the document rather than your source, so it names the operation and the field instead of the file and the line. If the harder problem is that nobody can explain the system at all, start with the codebase and come back to the spec.

We do not have an OpenAPI document yet.

Then this is the wrong end to start from. Describe the endpoints you have and generate the document first, then bring it back. A gap list only means something against a document that declares a version, because which absences are permitted depends entirely on the version you are writing to.

OpenAPI Spec Documentation Gap Workup

Fill in the form and your workspace opens with the work already underway.