OpenAPI 3.1 has been stable since 2021 and is now the default for new specs. If you're on 3.0, the upgrade is mostly painless — but the JSON Schema alignment makes downstream tooling (SDK generators, validators, docs sites) noticeably happier. Here's the short version of what changed and how to upgrade.
The five real differences
1. JSON Schema 2020-12 alignment
This is the headline change. OpenAPI 3.0 had its own dialect of JSON Schema — close to draft-04 but with quirks. OpenAPI 3.1 aligns with JSON Schema 2020-12, the modern standard.
Concrete result: validators, codegen, and docs tools can use off-the-shelf JSON Schema libraries instead of OpenAPI-specific shims. Bugs in edge cases (recursive schemas, $ref resolution, etc.) tend to be fixed faster because the surface area is shared with the JSON Schema community.
2. null is a real type
In 3.0:
properties:
phone:
type: string
nullable: true
In 3.1:
properties:
phone:
type: [string, "null"]
The 3.1 form composes correctly with oneOf / anyOf / allOf. The 3.0 nullable: true was a known awkward special case that didn't compose well.
3. Webhooks at the top level
In 3.0, you could model webhooks using callbacks: on a request, but only if there was a request that triggered them. There was no clean way to model "we send your endpoint a webhook every time X happens."
In 3.1:
webhooks:
messageReceived:
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/InboundMessage'
responses:
"200":
description: Acknowledged.
Webhooks live at the same level as paths: and components:. Generators that understand webhooks can produce typed webhook handlers; docs sites get a real "Webhooks" section instead of stuffing them under "Advanced."
4. Examples follow JSON Schema rules
OpenAPI 3.0 had its own example / examples system that was almost but not quite consistent with JSON Schema. 3.1 unifies them. The practical consequence: docs sites can render examples more reliably because they're working with one model.
5. exclusiveMinimum / exclusiveMaximum are numbers, not booleans
In 3.0:
minimum: 1
exclusiveMinimum: true
In 3.1 (and modern JSON Schema):
exclusiveMinimum: 1
Less likely to bite you in practice but worth knowing if you have validators that round-trip specs.
What doesn't change
- Path templating syntax (
/messages/{message_id}). - The shape of
components.schemasand$ref. tags,operationId,servers:,security:/securitySchemes:.- The HTTP method verbs and status code response model.
If your spec doesn't touch nullable, webhook-shaped endpoints, or quirky example handling, the upgrade is essentially a YAML header change.
How to upgrade
Step 1: change the version line
openapi: 3.0.3 # before
openapi: 3.1.0 # after
Step 2: rewrite nullable: true
For every nullable: true, change type: string to type: [string, "null"]. A regex replacement gets you 90% of the way there; spot-check anything unusual.
Step 3: pull webhooks up
If you have webhooks modeled under callbacks:, lift them to a top-level webhooks: block. The shape inside (request body schema, response schema) stays the same.
Step 4: re-validate
Run your validator (Spectral, Stoplight, openapi-cli, or Bloom's report). The validator will flag anything you missed.
Step 5: regenerate
Generate your SDKs against the new spec. Bloom's compatibility report (what's in one) tells you whether the regenerated SDK has any breaking changes vs the 3.0 version. In most cases the diff is zero — the wire format is identical, only the spec representation changed.
Tooling support today
In 2026, all of the major tooling supports 3.1:
- Bloom — first-class.
- OpenAPI Generator — yes, with a flag.
- Spectral / Stoplight — yes.
- Mintlify / ReadMe / Fern — yes.
- Redocly — yes (their reference implementation).
- Swagger UI / Swagger Editor — yes, since 2022.
Old tools that have not been updated since 2021 may still be 3.0-only. If you encounter one, that's a signal about the tool's maintenance level.
What to do this week
- If you're on 2.0, plan a direct jump to 3.1 instead of 2.0 → 3.0 → 3.1. The intermediate stop adds work without lasting value.
- If you're on 3.0 with a clean spec, the upgrade is half a day. Schedule it during a regular maintenance window.
- If you're on 3.0 with a messy spec, the upgrade is worth doing alongside a cleanup pass — see the OpenAPI best practices post for what "clean" looks like.
If you want a 3.1 spec generated against existing code or migrated from a 3.0 file, start a free Bloom report — the generation pipeline reads either version and the migration report flags the practical differences.