Model a polymorphic response with a discriminator
Describe a response that comes in several shapes so a generator emits a tagged union rather than a bag of optional fields, using oneOf with a discriminator.
How-to › Section 5
Authoring, linting, modelling and versioning the description that SDKs, docs and agent surfaces are generated from, including letting a coding agent draft or repair it.
23 guides in 7 topics. Every guide compares its approaches and shows the output its commands printed.
Writing OpenAPI 3.1 that tools can use: operationIds (snake_case, unique, verb plus noun, chosen to generate clean SDK method names), tags, components and $ref reuse, discriminators, nullable versus unions, examples, security schemes, servers, webhooks and callbacks, uploads, bundling and splitting, Swagger 2 to 3.1 migration, design-first versus code-first (FastAPI, NestJS Swagger, springdoc, swag, zod-openapi, Huma, tsoa).
Describe a response that comes in several shapes so a generator emits a tagged union rather than a bag of optional fields, using oneOf with a discriminator.
Give every operation one declared, described tag in reading order, audit the list in CI, and measure what a tag rename moves in a tag-driven generator and in sdkgen.
Keep OpenAPI 3.1 as the source of truth and build a 3.0 copy for older generators, with a guard that fails when the conversion loses or mangles anything.
Move every repeated schema, parameter, and response under components and reference it with $ref, so generators emit one named type instead of a copy per use.
Set style and explode on each array and object query parameter, serialize from the document in the client, and validate requests with a Prism mock.
Break a multi-thousand-line description into per-resource files, then produce the single bundled document most generators expect, without losing component names.
Name every operation with a unique lowercase verb-plus-noun id, audit the ids in CI, rename the bad ones with an overlay, and diff the methods two generators make.
The spec as an output of AI, not only an input: drafting an OpenAPI description with Claude Code, Cursor or Copilot from route handlers, from HAR captures, from prose docs or a Postman collection; filling missing schemas and examples; repairing a spec that a generator rejects; validating the result with Spectral, Schemathesis and a mock server; keeping the agent-written spec in sync with code in CI.
List every response with no schema or example with two Spectral rules, hand the gaps and fixtures to a coding agent, and validate every example after every batch.
Run Spectral on every OpenAPI edit a coding agent makes, through a Claude Code hook or a Cursor or Copilot instruction, so the agent fixes errors before moving on.
Convert a Postman v2.1 export for a baseline, give a coding agent the gaps and saved examples, and check for invented required fields and a lossless round trip.
Style rules and governance: Spectral rulesets and custom functions, Redocly lint, Stoplight style guides, vacuum, CI gates, checks that generated SDKs will be usable (every operation has an id, every response has a schema), conventions across many services.
Run one naming ruleset in every repository, then compare terms across specs, because no per-document linter sees that billing says customer and CRM says client.
Make Spectral a required check that fails on errors and annotates warnings, and lint the whole document so an edit to a shared component cannot merge unseen.
Run aontu vet over every environment overlay in CI, so two files that disagree fail in seconds with both lines named, and refuse a release that rests on defaults.
Designing the resource model before or beside the spec: resource naming, id formats, sub-resources versus links, non-CRUD actions such as cancel or approve, filtering and sorting, field selection, relationships, deciding when an endpoint is an entity operation and when it is a standalone action.
Add a fields parameter that returns a subset on request and the full object otherwise, refuse unknown names with an RFC 9457 problem, and check the mock agrees.
Apply one test to every proposed endpoint, tabulate the verdicts, and catch the PATCH that refunds a card and sends an email while looking like a safe update.
Triage requested queries into filters and searches, measure how long the search index trails a write, and keep an SDK list method off the search endpoint.
One filter and sort grammar for every list endpoint: a shared parser, a field declaration per resource, OpenAPI parameter components, and a CI check for drift.
List every resource, its key, parent, operations, and actions in one table before the first path, then compile the table and check that every path matches a row.
Turning endpoints into entities, attributes and operations: classification heuristics (which path is a list, load, create, update or remove), handling endpoints that map to no entity (direct and prepare escape hatches), flows, inconsistent specs, diffing two models from successive spec versions, publishing the model as JSON beside OpenAPI, and verifying that SDK, CLI and MCP server were generated from the same model version.
Extract a model from each spec version, diff the two model files, and read the result beside what oasdiff and openapi-diff report about the same release.
Put the entity model extracted from the spec beside the one your team drew, give each disagreement a row and a decision, and fail the build when one has neither.
When OpenAPI is the wrong tool: TypeSpec, Smithy, AsyncAPI, GraphQL SDL, protobuf, Arazzo workflows, JSON Schema alone, and converting legacy RAML and API Blueprint.
Publish standalone JSON Schema 2020-12 files, bundle them offline, generate TypeScript and Python types, and wrap them in an OpenAPI 3.1 shell when a tool insists.
Versioning strategies (path, header, date-based as Stripe does), additive change rules, breaking-change detection in CI (oasdiff, openapi-diff, Optic, and aontu breaking and subsume as one option for model files), Sunset and Deprecation headers, deprecation calendars, compatibility tests, and tying SDK versions to API versions (the sdkgen api-versioning design note as one approach beside Stainless and Speakeasy).
Fail a pull request whose OpenAPI change would break existing clients: bundle both sides with one tool, run oasdiff, and post its verdict as a comment.
Send the API version you were built against on every request, and refuse a response that came back under a different one.
Retries, timeouts, pagination and auth are the same problems in every client. Voxgig generates them from your OpenAPI description, in 23 languages, from one model.
Since 2018, Richard Rodger has talked with developer advocates, event organizers, and the people who build developer-facing companies about the specifics of the work.