Open an OpenAPI spec and the version line is the first thing you see. If that line shows openapi: "3.0.3" or openapi: "3.1.0", one question has been on the table since September 2025: what does OpenAPI 3.2 bring, and is the jump worth it?
Three of the new features tend to stand out in day-to-day work because they fix real pain points. Hierarchical tags make documentation navigation possible without vendor extensions, the QUERY method decouples complex filters from the URL, and streaming APIs finally get first-class support. The rest is smaller, but useful in specific spots.
OpenAPI 3.2.0 has been available since September 2025 and stays fully backward-compatible with 3.0 and 3.1. Three additions solve concrete day-to-day pain points. Hierarchical tags replace vendor extensions like x-tagGroups, the QUERY method makes GET-with-body an idempotent operation, and streaming picks up first-class support through Server-Sent Events. On top of that, the OAuth 2.0 device flow gets a proper home, XML modeling sharpens up, and multipart definitions get cleaner.
What OpenAPI 3.2 brings
OpenAPI 3.2.0 was released on September 18, 2025. The specification stays strictly backward-compatible with 3.0 and 3.1. Existing specs keep validating without changes, and existing tooling doesn’t need to migrate. The 3.2-specific constructs are opt-in and only show up where teams actively use them.
Seven areas pick up additions or clarifications. Hierarchical tags make documentation navigation possible without vendor extensions. The QUERY method turns GET-with-body into an official, idempotent operation. Streaming and Server-Sent Events become first-class to model. The OAuth 2.0 device authorization flow can be described officially. XML modeling covers attributes, nested, and mixed content more precisely. Multipart definitions that combine file uploads with structured metadata get cleaner. Finally, several older constructs and OAuth flows are marked as deprecated. The table below sorts the most important changes by practical impact.
| Feature | Practical impact |
|---|---|
| Hierarchical tags | Microservice domains can be structured without x-tagGroups or x-displayName. Tag navigation becomes tool-portable. |
| QUERY method | Complex filter bodies are idempotent and cacheable, without a POST workaround. Search and reporting APIs get an HTTP verb that actually fits. |
| Streaming and SSE | Tooling can generate and validate Server-Sent Events instead of treating them as a special case. Maintaining a parallel AsyncAPI spec falls away. |
| OAuth device flow | CLI tools, IoT devices, and smart TVs without a browser can be described officially. |
| XML improvements | Attributes, nested, and mixed content can be modeled without vendor extensions. |
| Multipart clarification | File uploads with JSON metadata in the same request can be expressed cleanly. |
| Deprecation markers | Existing specs can be maintained without forcing a 3.2 jump immediately. |
From a migration perspective, 3.2 is a light jump. Teams already on 3.1 can flip the version line in the spec file to openapi: "3.2.0" and the spec keeps validating. New constructs are then introduced selectively, wherever a concrete use case calls for them. A big-bang migration across the entire API portfolio is neither necessary nor smart.
Hierarchical tags make doc navigation possible without vendor extensions
Tags in OpenAPI have always been used to group operations. Up to 3.1, they sit as a flat list at the top level. Anyone trying to organize an API with thirty endpoints across five domains had to fall back on vendor extensions like x-tagGroups (Redoc) or x-displayName (from various tool vendors).
The result was tool-specific and not portable. A spec that looked nicely structured in Redoc collapsed back to a flat list in Swagger UI. Teams that wanted to switch documentation generators had to remodel the tag structure every time.
In 3.2, hierarchical tags are part of the standard. Tag objects now carry the fields parent, summary, and kind. Nested navigation can be derived from those fields, and the structure stays portable across renderers.
tags:
- name: Payments
- name: Cards
- name: Transfers
x-tagGroups:
- name: Banking
tags:
- Payments
- Cards
- Transfers
# With OpenAPI 3.2
tags:
- name: Banking
summary: "Banking domain"
kind: nav
- name: Payments
parent: Banking
summary: "Payment processing"
- name: Cards
parent: Banking
summary: "Card operations"
- name: Transfers
parent: Banking
summary: "Transfers"
The practical effect is concrete. A team documenting an API for a banking platform can now group domains like Payments, Cards, and Transfers under a shared Banking node. The navigation shows up consistently in Swagger UI, Redoc, and Scalar without any tool-specific configuration.
There is no migration pressure for existing specs. Teams that want to keep using vendor extensions can do so, since 3.2 still accepts them. Teams that switch to the 3.2-native pattern gain portability and can phase out the vendor extensions step by step.
The QUERY method brings GET with a body as an idempotent operation
In the HTTP specification, GET requests are designed for read access: idempotent and cacheable. As soon as filter logic gets complex, the pattern runs into its limits. Long URLs with dozens of query parameters are awkward, and many servers cap URL length at 8 KB or less.
The obvious workaround so far has been POST with a JSON body. That works technically, but it signals the wrong semantics. POST stands for non-idempotent write operations, isn’t cacheable, and fits poorly with pure read access that happens to use complex filters.
OpenAPI 3.2 officially supports the QUERY method. QUERY is an ongoing HTTP standardization effort at the IETF, and it combines the semantics of GET (idempotent, safe, cacheable) with the option to send a request body alongside the request.
/customers:
query:
summary: Customer search with complex filters
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
filters:
type: array
items:
$ref: '#/components/schemas/Filter'
sort:
type: array
items:
type: string
responses:
'200':
description: Matching customers
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerList'
The method matters for search APIs, reporting endpoints, and GraphQL-style filter structures, where the filter logic no longer fits into query parameters. A team describing a search API with twenty optional filters and three sort criteria can now express the model cleanly.
Tooling support, however, is still limited. Most HTTP clients, browser implementations, and API gateways don’t support QUERY consistently yet. Teams using the method in their spec today mostly treat it as documentation and fall back on POST with an idempotency header at runtime until tooling catches up.
The HTTP standardization itself is still moving. QUERY is active as an IETF draft under draft-ietf-httpbis-safe-method-w-body and is expected to be ratified as an RFC in 2026 or 2027. So OpenAPI 3.2 gets out ahead of a standardization effort that hasn’t wrapped up in the HTTP stack itself yet. For teams with existing POST-based search APIs, a gradual spec adjustment makes sense once the client libraries in their own stack pick up QUERY.
Streaming and Server-Sent Events as first-class
Streaming APIs have been hard to express in OpenAPI so far. Server-Sent Events, long polling, and chunked-transfer endpoints could be described technically, but tooling had no real handle on generating code from them or validating the spec. In practice, SSE endpoints were either declared as regular GET endpoints with text/event-stream or factored out of the main spec entirely.
In 3.2, streaming patterns are officially on the table. Server-Sent Events can be modeled cleanly through the text/event-stream content type, and the streaming nature of an endpoint becomes machine-readable for tooling. The spec now distinguishes between one-off responses and continuous event streams. In practice, you’ll often still see a vendor extension like x-stream: true tacked on while generators are still catching up to the official streaming field.
/events:
get:
summary: Event stream over Server-Sent Events
responses:
'200':
description: Continuous event stream with order updates
content:
text/event-stream:
schema:
$ref: '#/components/schemas/OrderEvent'
x-stream: true
Tooling implementations like OpenAPI Generator and Spectral are working on support for the streaming markers. Until then, the concrete benefit is limited to documentation and validation, which for many teams is already where most of the value sits.
Before 3.2, we kept streaming APIs in a separate AsyncAPI specification that ran in parallel to the OpenAPI spec. The dual maintenance overhead fell away as soon as 3.2 went into production and SSE endpoints could be described directly inside the OpenAPI document. Spec consumers no longer had to keep two different tools in their head, depending on whether they wanted to call a synchronous endpoint or a streaming one.
The line between OpenAPI and AsyncAPI still holds. AsyncAPI covers complex event-driven architectures with pub/sub patterns, channel definitions, and message brokers. OpenAPI 3.2 with streaming support covers synchronous and semi-synchronous HTTP-based streaming patterns, where a server continuously sends data to a client.
Typical use cases for streaming in OpenAPI 3.2 include live order updates in e-commerce platforms, telemetry streams from IoT devices, progress updates for long-running backend tasks, and live notifications in banking or logistics applications. Teams that cover one of these patterns and have so far relied on workarounds end up with noticeably cleaner specs under 3.2.
Other changes that tend to fly under the radar
The smaller additions in 3.2 attract less attention, but they help specific use cases that were hard to describe in 3.1.
- OAuth 2.0 device authorization flow. The flow defined in RFC 8628 is now officially available as a flow variant in the spec. It covers CLI tools, IoT devices, and smart TVs without a browser, where a code is entered on a console while the actual authentication happens on a second device. Before 3.2, the flow had to be modeled through vendor extensions or as a generic custom flow.
- XML modeling. Attributes, nested elements, and mixed content can be described without workarounds. For legacy stacks in insurance, healthcare, or logistics that still maintain XML-based interfaces, this is a genuine improvement. Teams that keep XML around as a legacy format for SAP integrations or EDI connections end up with cleaner spec descriptions.
- Multipart definitions. Combining file uploads with structured JSON metadata in the same request can be expressed more cleanly. Anyone describing an endpoint for image uploads with description metadata, or document uploads with classification JSON, no longer needs explanatory comments in the spec to make the intent clear.
- Deprecation markers. Several older constructs are marked as deprecated. The
nullable: truemodeling from 3.0 is officially superseded by the JSON-Schema-aligned variant from 3.1, several OAuth flow variants are considered legacy, and theconsumesandproducesconventions carried over from 2.0 are conclusively dropped. The deprecation markers concern style, not validity. Existing specs stay valid, but linters will increasingly flag warnings.
When the jump from 3.1 to 3.2 is worth it
The call for or against 3.2 is unusually clear compared to previous version jumps. 3.2 is backward-compatible with 3.1, and the migration effort stays minimal. It comes down to which features you actually need.
- Streaming or Server-Sent Events in your use case. The jump is worth it. Tooling generation and validation for SSE endpoints become possible, instead of maintaining workarounds.
- Hierarchical doc navigation wanted. The jump is worth it. Vendor extensions like
x-tagGroupscan be removed, and the spec becomes tool-portable. - Complex filter endpoints (search, GraphQL-style filters). The jump is worth it. QUERY decouples the filter body from query-parameter limits more cleanly than POST with an idempotency header.
- None of the three drivers apply. No acute migration pressure. 3.1 stays valid; the jump can wait until a use case actually shows up.
Tooling status is the second factor when sizing up the jump. OpenAPI Generator, Spectral, and the major doc renderers like Swagger UI, Redoc, and Scalar have rolled out 3.2 support to varying degrees. Teams that auto-generate from the spec should check 3.2 support in their own stack first, before flipping production specs.
On the migration side, the jump from 3.1 to 3.2 is pure schema adjustment. Existing tags structures, path definitions, and component schemas stay valid. 3.2 constructs are added, not replaced, and tooling that doesn’t understand 3.2 silently ignores the new fields. Validating the spec with a 3.1 linter gives you warnings at worst for unknown fields, not errors.
For anyone still unsure what actually separates OpenAPI from Swagger as a term, there’s a breakdown in OpenAPI vs Swagger.
How api-portal.io supports OpenAPI 3.2
In api-portal.io, OpenAPI 3.2 is supported side by side with 3.0 and 3.1. On spec import, 3.2 constructs like hierarchical tags, QUERY operations, and streaming markers are picked up directly and rendered in the documentation UI. The API Linter checks 3.2-specific patterns against the same style guide that already applies to 3.0 and 3.1.
The API Explorer supports rendering multiple API formats.