Reference

OpenAPI 3.1 vs 3.0: what's new and what to use in 2026

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.schemas and $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.