The OpenAPI Initiative announced OpenAPI 3.2 on September 23rd, 2025. Almost exactly a year later, on September 22nd, the Fastify project shipped fastify-swagger v9.9.0, and its release notes are a single line: OpenAPI 3.2.0 compatibility. It is a small release, but it is the kind I pay attention to, because a specification version only becomes real when the tools that generate contracts can produce it.
Most OpenAPI documents are not written by hand. They are generated from code, by a framework plugin like this one, every time an app starts or a build runs. So when a code-first framework learns a new version of the spec, a whole population of APIs can move with a one-line config change. When it does not, they cannot move at all.
What changed
The work came in through pull request #949 from Tony133, closing an issue that asked for 3.2 support in December. The pull request description is one of the clearer explanations I have read of what 3.2 means for a generator. OpenAPI 3.2 is additive over 3.1 and uses the same JSON Schema dialect, so most of it already worked: the version string passed straight through, and the new hierarchical tag fields (summary, parent and kind) came out unchanged. What was missing was narrower:
$selfwas being dropped. 3.2 adds a top-level$selfso a document can state its own URI, which matters for resolving references between documents. It is now passed through.- Custom HTTP methods had nowhere to go. Fastify lets you register methods like
PROPFIND. OpenAPI could never describe them, because the Path Item Object only had fixed fields for the standard methods. 3.2 addsadditionalOperations, and fastify-swagger now puts those routes there, keyed by the upper-case method name, when you target 3.2 or later. Older versions are unchanged, because they cannot describe those methods at all. QUERYis now tested. The new HTTP QUERY method, a safe, idempotent request that is allowed to carry a body, is a fixed field in 3.2. Fastify already supported it; now there are tests proving the generated document describes it correctly.- There are TypeScript types for 3.2. A new
OpenAPIV3_2namespace covers the document, tag, server and path item additions, and it works as both input and output of the plugin’s transform hook.
The README now explains how to pick the OpenAPI version, what gets passed through, and how custom methods are rendered. About 250 lines, most of them tests and types.
The honest part of the pull request
What I appreciated most were the notes at the bottom, because they describe the state of the ecosystem better than any survey would.
@apidevtools/swagger-parser, one of the most widely used OpenAPI parsers and validators in the JavaScript world, rejects openapi: 3.2.0. It supports up to 3.1.2. So the new tests assert on the structure of the generated document instead of validating it, and validation can be added once the parser catches up. The shared openapi-types package does not ship 3.2 types yet either, which is why Fastify built its own on top of the 3.1 ones. And several 3.2 additions that live in objects you write yourself, such as components.mediaTypes, the OAuth 2.0 device flow, in: querystring parameters and itemSchema for streaming, are passed through at runtime but not typed yet.
That is the real shape of a specification rollout. The spec ships. Then the generators, parsers, validators, type packages, editors and linters each have to catch up, on their own schedules, maintained by different people. A framework can produce a valid 3.2 document today that the most popular validator in its own ecosystem refuses to read. Two weeks ago I wrote about the same pattern in VS Code finally catching up with JSON Schema 2020-12. One tool at a time is how it happens.
Why this matters beyond Fastify
Two of the things 3.2 brings are directly useful for the agent work I keep writing about. QUERY gives complex, read-only searches a proper home instead of forcing them into a POST that looks like a write. An agent deciding whether a call is safe to retry is much better served by a method that says so. And $self makes a contract addressable, which matters when documents reference each other across a large estate and a machine has to resolve them without a human.
On my side, the contracts in the APIs.io catalog are standardized on 3.2.0, which means I am living with exactly the tooling gap this pull request describes. Every generator that learns 3.2 moves some providers closer to publishing it themselves, instead of me upgrading their contracts from the outside.
What I would do
- If you run Fastify, upgrade to 9.9.0, set
openapi: '3.2.0'in the plugin options, and look at what changes in your generated document. If you use custom HTTP methods or QUERY, this is the first time your contract can describe your whole API. - If you maintain a parser, validator or type package, this is your nudge. The generators are moving, and a validator that rejects the current version of the spec pushes people back to the old one.
- If you maintain another code-first framework, this pull request is a good template: pass through what already works, add what is structurally new, test it, and say plainly what the rest of the ecosystem is not ready for yet.
Thanks to Tony133 and the Fastify maintainers for doing this carefully and in public. A year after 3.2 shipped, this is what adoption actually looks like, one release note at a time.
