skip to content

Your team moves an OpenAPI 3.0 document to 3.1 — what changes at the document level?

level: seniorimportance: should knowfreq 34%

answer

  1. Endpoint map stops being mandatory
  2. A new root for pushed requests
  3. Dialect declared once at the top
  4. Schema Objects rejoin the JSON Schema world
  5. The cost is downstream, not syntactic

basics

~20 s

OpenAPI 3.1 adds the root keys webhooks and jsonSchemaDialect, makes paths optional so a document may describe only webhooks or components, adds a pathItems bucket to components, adds info.summary and an SPDX license.identifier, and aligns Schema Objects with JSON Schema 2020-12.

solid answer

~40 s

Bump `openapi` to `3.1.0` and four document-level things change. `paths` is no longer required: a valid 3.1 file may carry only `webhooks`, or act as a shared `components` library. `webhooks` is a new root map describing out-of-band requests the API *sends*, keyed by an event name — a cleaner story than 3.0's operation-attached `callbacks`. `jsonSchemaDialect` declares the default schema dialect for the document, because 3.1 realigns Schema Objects with JSON Schema 2020-12 rather than the older draft subset. Smaller additions: `components.pathItems`, `info.summary`, and `license.identifier` carrying an SPDX id in place of `license.url`. The real migration cost is rarely syntax — it is tooling: generators, gateways and validators adopted 3.1 unevenly, so verify your whole chain before committing the bump.

code

yaml · 23 lines
yaml
openapi: 3.1.0
info:
  title: Billing API
  summary: Invoicing and payment events
  version: "2026.04"
  license:
    name: Apache 2.0
    identifier: Apache-2.0
webhooks:
  invoicePaid:
    post:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Invoice'
      responses:
        '200':
          description: Consumer acknowledged the event
components:
  schemas:
    Invoice:
      type: object

go deeper

for a junior

Know that OpenAPI 3.1 exists, that it is closer to standard JSON Schema than 3.0, and that documents declare their version in the openapi field.

for a middle

Explain the new root keys and the relaxed requirements — webhooks, jsonSchemaDialect, optional paths — and what document shapes they make legal.

for a senior

Lead with the migration risk rather than the syntax: inventory every tool and consumer that parses the document, because 3.1 support is uneven and a broken SDK pipeline surfaces late.

for a principal

Own the rollout decision across teams — when the estate moves, whether shared component libraries move first, and how you avoid a split-version corpus that nobody's tooling can consume uniformly.

## What the bump is really about OpenAPI 3.1 was a compatibility release aimed at one long-standing complaint: 3.0's Schema Object was a *subset-plus-extensions* of an old JSON Schema draft, so schemas were not interchangeable with the wider JSON Schema ecosystem. 3.1 realigns on JSON Schema 2020-12. Around that central change sit a handful of document-level additions. ## paths becomes optional In 3.0, `paths` was a required root key — even if it was an empty object. In 3.1 a valid document must contain at least one of `paths`, `webhooks` or `components`. Two document shapes become legal that were not before: - **A webhook-only document** describing an API that only *pushes* to consumers. - **A components-only library** — a file of shared schemas, responses and parameters that other documents `$ref` into, with no endpoints of its own. Teams that previously faked this with an empty `paths: {}` can now express it honestly. ## webhooks `webhooks` is a root map from a name you choose (the event name, e.g. `invoicePaid`) to a Path Item Object. Each describes a request the *API provider* will send to a URL the consumer registered out of band. Because the value is a Path Item, it carries ordinary operation objects with a `requestBody` and `responses` — the responses being what the provider expects the consumer's endpoint to return. This differs from 3.0's `callbacks`, which still exist: a callback is attached to a specific operation and its URL is derived from a runtime expression over that operation's request. Callbacks model "this request triggers that call back"; `webhooks` models "subscribers registered elsewhere receive these". ## jsonSchemaDialect A root string naming the default JSON Schema dialect (a `$schema` URI) that Schema Objects in this document use when they do not declare their own. It exists because 3.1 schemas *are* JSON Schema documents and may carry `$schema` individually. Most documents can leave it out and accept the 2020-12 default; you set it when you deliberately author against another dialect and your tooling honours it. ## components.pathItems 3.1 adds a `pathItems` bucket to `components`, so a whole path item — its parameters and all its operations — can be defined once and referenced from `paths` or from `webhooks`. It is what makes webhook reuse practical. ## info additions `info.summary` gives a short one-line description alongside the longer `description`. `license` gains `identifier`, holding an SPDX license expression such as `Apache-2.0`; it is mutually exclusive with `license.url`, so a document may declare one or the other, never both. ## Operation-level relaxation `responses` is no longer REQUIRED on an Operation Object in 3.1. That is a validity relaxation, not an invitation: an operation with no documented responses is a worse contract, and most house style guides lint for at least one success response regardless of what the spec permits. ## The Schema Object realignment, at document level The schema keyword changes themselves are their own subject, but two document-level consequences are worth knowing when you plan a migration. First, `$ref` in 3.1 Schema Objects may sit alongside sibling keywords, because that is JSON Schema 2020-12 behaviour — in 3.0 siblings of `$ref` were ignored, which is why 3.0 documents are full of single-element `allOf` wrappers that exist purely to attach a description or a nullability flag. Second, 3.1 schemas can be lifted into and out of plain JSON Schema tooling, which changes what validation libraries you can use. ## What actually costs you The syntax migration is small and largely mechanical. The risk is downstream. Code generators, API gateways, mock servers, documentation renderers, contract-test tools and linters each adopted 3.1 at their own pace, and some still parse only 3.0. Before bumping the `openapi` string, inventory every consumer of the document — including consumers outside your team — and confirm each one parses 3.1. A spec that no longer generates SDKs is a worse outcome than a spec on an older version. The pragmatic sequencing is: confirm tooling, bump the version string, run the linter, fix schema-level fallout, and only then start using 3.1-only features such as `webhooks` — because the moment you do, rolling back is no longer a one-line change.

  • How do 3.1's webhooks differ from 3.0's callbacks?
    A callback hangs off a specific operation and its URL comes from a runtime expression over that operation's request — "this call triggers that callback". `webhooks` is a root-level map of events the provider sends to subscribers who registered out of band, with no triggering operation. Callbacks still exist in 3.1.
  • What makes a components-only OpenAPI 3.1 document useful?
    It is a shared library of schemas, responses and parameters that several API documents `$ref` into, keeping one definition of a common type across teams. In 3.0 it needed a dummy empty `paths` object to be valid; in 3.1 it is legal as written.
  • Would you bump a widely consumed document to 3.1 today?
    Only after inventorying the toolchain — generators, gateway, mock server, docs renderer, linter and any external consumer — since 3.1 support is uneven. The version string is one line; a chain that silently stops generating SDKs is the real cost, and it surfaces late.

saying these in an interview costs you the question

  • Says 3.1 is only a schema-keyword change
  • Thinks webhooks replaced callbacks entirely
  • Assumes every tool parses 3.1 already
  • Believes paths is still mandatory in 3.1
  • Sets both license.url and license.identifier

context