The Key Building Blocks Explained
OpenAPI 3.1 is the industry standard for REST API documentation, yet many teams only use a fraction of its capabilities. This guide explains all the essential building blocks: from Info and Paths through Components and Schemas to Security and Callbacks, with complete practical YAML examples.
Table of Contents
- 1. OpenAPI 3.1 vs. 3.0: what changed
- 2. Info, Servers and the Root Object
- 3. Paths and Operations: the core of the API
- 4. Parameters: path, query, header and cookie
- 5. Schemas with JSON Schema 2020-12
- 6. Components: reuse without duplicates
- 7. Security schemes: Bearer, OAuth2 and API key
- 8. OpenAPI 3.0 vs. 3.1 side by side
- 9. Summary
- 10. FAQ
1. OpenAPI 3.1 vs. 3.0: what changed
OpenAPI 3.1 was released in February 2021 and brought the most significant change since version 2.0: full compatibility with JSON Schema 2020-12. In OpenAPI 3.0, the schema object was a customized subset of JSON Schema Draft 7 with proprietary extensions such as nullable. These deviations caused tooling issues and semantic contradictions. OpenAPI 3.1 replaces that subset with full JSON Schema 2020-12 compatibility: type can now be an array (type: [string, null] instead of nullable: true), $ref may be combined with other keywords, and every JSON Schema keyword is valid.
The second important change concerns webhooks: OpenAPI 3.1 has a new top-level field webhooks that documents callbacks an API provider sends to its consumers. In 3.0, webhooks had to be buried inside callbacks within operations. The new field makes asynchronous notifications a first-class citizen of the API specification. The third notable change: info.license now supports an identifier field following the SPDX standard instead of only a URL.
In practice, migrating from 3.0 to 3.1 mainly means: replacing every nullable: true with type: [string, null] or oneOf: [{type: string}, {type: 'null'}], adjusting exclusiveMinimum/exclusiveMaximum (in 3.1 these are now numbers instead of booleans, as defined in JSON Schema 2020-12), and setting the openapi version to 3.1.0. Tooling support for 3.1 has been widely available since 2023, Swagger UI, Redoc, Stoplight and most code generators fully support 3.1.
2. Info, Servers and the Root Object
Every OpenAPI 3.1 specification starts with the root object, which defines the version, metadata and the available servers. The info object is required and must contain at least title and version. The version is the API version, not the OpenAPI specification version, a common mistake for newcomers. The servers array defines the base URLs of the API for different environments. Without servers, clients assume the server is relative to the location of the specification.
The externalDocs field lets you link to further documentation. Root-level tags define groups with descriptions that are then referenced in operations, which matters for a clean documentation structure. The info.contact object with name, email and URL is indispensable for public APIs. The info.termsOfService field links to the terms of use. All of these fields are relevant metadata for automatically generated documentation pages and developer portals.
# openapi.yaml - Root Object, complete OpenAPI 3.1 example
openapi: 3.1.0
info:
title: Mironsoft Commerce API
version: "2.0.0"
description: |
REST API for the Mironsoft Commerce stack.
Supported authentication: Bearer JWT, OAuth 2.0 (Authorization Code).
contact:
name: Mironsoft API Support
email: api@mironsoft.de
url: https://mironsoft.de/support
license:
name: Proprietary
identifier: LicenseRef-Proprietary
servers:
- url: https://api.mironsoft.de/v2
description: Production
- url: https://api-staging.mironsoft.de/v2
description: Staging
- url: http://localhost:8080/v2
description: Local Development
tags:
- name: orders
description: Create, read and manage orders
externalDocs:
description: Order lifecycle documentation
url: https://docs.mironsoft.de/orders
- name: products
description: Product catalog and inventory
- name: auth
description: Authentication and token management
externalDocs:
description: Full Mironsoft Developer Docs
url: https://docs.mironsoft.de
3. Paths and Operations: the core of the API
The paths object is the centerpiece of any OpenAPI specification. Each key is a URL path template, each value a Path Item Object that defines the HTTP methods and their operations. An operation requires at least a responses object, but should also include operationId, summary, description and tags. The operationId is especially important: code generators use it as the function name, so it must be unique, descriptive and follow a consistent convention, e.g. getOrderById, createOrder, updateOrderStatus.
Path templates use curly braces for path parameters: /orders/{orderId}. Every parameter defined in curly braces must be declared in the parameters array of the operation (or the path item) with in: path. Path parameters are always required: true, the specification mandates this. Parameters defined at the path item level apply to all operations of that path and can be overridden in individual operations. This pattern is useful for auth parameters that apply to all methods of an endpoint.
# Paths and Operations - complete example for /orders/{orderId}
paths:
/orders:
post:
operationId: createOrder
summary: Create a new order
tags: [orders]
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
examples:
standard_order:
$ref: '#/components/examples/StandardOrder'
responses:
'201':
description: Order created successfully
headers:
Location:
description: URL of the new resource
schema:
type: string
format: uri
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/Unauthorized'
/orders/{orderId}:
parameters:
- name: orderId
in: path
required: true
schema:
type: string
format: uuid
description: Unique order ID (UUID v4)
get:
operationId: getOrderById
summary: Retrieve an order
tags: [orders]
security:
- BearerAuth: []
responses:
'200':
description: Order found
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'404':
$ref: '#/components/responses/NotFound'
4. Parameters: path, query, header and cookie
OpenAPI distinguishes four kinds of parameters via the in field: path, query, header and cookie. Path parameters are part of the URL path and always required. Query parameters appear after the ? and are typically optional, used for filtering, sorting and pagination. Header parameters document custom HTTP headers (standard headers such as Authorization are defined via security). Cookie parameters document values transmitted via cookies.
Every parameter has a schema object that defines the data type and validation rules. For query parameters with complex data structures, the style field matters: form (default), spaceDelimited, pipeDelimited or deepObject control how arrays and objects are serialized. The explode: true field (default for form) produces a separate parameter per array element (?tag=a&tag=b), while explode: false combines them (?tag=a,b). These details are decisive for compatibility with automatically generated client code.
5. Schemas with JSON Schema 2020-12
In OpenAPI 3.1, schemas are complete JSON Schema 2020-12 objects. That means full access to every JSON Schema keyword: type as an array, if/then/else for conditional validation, $defs for local definitions, unevaluatedProperties for strict schemas and prefixItems for typed tuple arrays. The most important practical change compared to OpenAPI 3.0: nullable: true no longer exists. Instead, use type: [string, "null"] or a oneOf with a null type.
Well-designed schemas make use of description, example (or examples), default, minimum/maximum, minLength/maxLength, pattern and enum where it makes sense. These fields are not just for documentation, they drive validation in mock servers, code generation in client SDKs and validation logic in server-side middleware layers. A schema without descriptions and examples is technically correct but largely useless for consumers.
# Schemas with JSON Schema 2020-12 - OpenAPI 3.1 example
components:
schemas:
Order:
type: object
required: [id, status, items, total, createdAt]
description: Complete order representation
properties:
id:
type: string
format: uuid
description: Unique order ID
examples: ["550e8400-e29b-41d4-a716-446655440000"]
readOnly: true
status:
type: string
enum: [pending, confirmed, shipped, delivered, cancelled]
description: Current status of the order
items:
type: array
minItems: 1
items:
$ref: '#/components/schemas/OrderItem'
total:
type: object
required: [amount, currency]
properties:
amount:
type: number
format: decimal
minimum: 0
exclusiveMinimum: true
description: Total amount in the given currency
currency:
type: string
pattern: '^[A-Z]{3}$'
description: ISO 4217 currency code
examples: ["EUR", "USD"]
note:
type: ["string", "null"]
maxLength: 500
description: Optional order note (null when not set)
createdAt:
type: string
format: date-time
readOnly: true
additionalProperties: false
6. Components: reuse without duplicates
The components object is the library system of OpenAPI. It holds reusable definitions that can be referenced with $ref. Available sections: schemas, responses, parameters, examples, requestBodies, headers, securitySchemes, links, callbacks and, new in 3.1, pathItems. Consistent use of components is the single most important factor for a maintainable OpenAPI specification. Anyone defining schemas inline inside operations creates duplicates that need adjusting in many places whenever something changes.
For shared error responses, a standardized error schema pays off. An RFC 9457 Problem Details compatible error structure with type, title, status, detail and instance is defined in components/schemas and referenced by every error response in components/responses. That way, all 4xx and 5xx responses automatically share a consistent format that can be updated in a single change.
7. Security schemes: Bearer, OAuth2 and API key
OpenAPI 3.1 supports four security scheme types: http (for Basic and Bearer), apiKey, oauth2 and openIdConnect. Security schemes are defined in components/securitySchemes and can then be applied at the root level as a default or targeted at the operation level. An empty array security: [] on an operation overrides the global security and marks the endpoint as publicly accessible.
OAuth 2.0 in OpenAPI is particularly involved: the oauth2 scheme contains separate configurations for each flow (authorizationCode, clientCredentials, implicit, password) with authorization URL, token URL and scope definitions. Scopes are listed in the operation's security array as a string array. Scope definitions must be complete and descriptive, Swagger UI generates the OAuth consent UI in the interactive documentation from them.
# Security Schemes - Bearer JWT + OAuth 2.0 in OpenAPI 3.1
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
JWT bearer token. Obtain via POST /auth/token.
Header: Authorization: Bearer <token>
OAuth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth.mironsoft.de/oauth/authorize
tokenUrl: https://auth.mironsoft.de/oauth/token
refreshUrl: https://auth.mironsoft.de/oauth/token/refresh
scopes:
orders:read: Read orders
orders:write: Create and update orders
products:read: Read product catalog
admin: Administrative access to all resources
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
description: API key for server-to-server communication
# Global security - applies to all operations
security:
- BearerAuth: []
# Public endpoint - overrides global security
paths:
/products:
get:
operationId: listProducts
security: [] # Public endpoint, no auth required
summary: List products publicly
tags: [products]
responses:
'200':
description: Product list
8. OpenAPI 3.0 vs. 3.1 side by side
Moving from OpenAPI 3.0 to 3.1 is, for most APIs, not a breaking change at the API level, but it does require adjustments to the specification file. The table below shows the most important differences and migration steps for teams updating an existing 3.0 specification.
| Feature | OpenAPI 3.0 | OpenAPI 3.1 | Migration |
|---|---|---|---|
| Nullable fields | nullable: true |
type: [string, "null"] |
Search & replace, adjust the type |
| JSON Schema version | Subset of Draft 7 | Full 2020-12 | All new keywords available |
| Webhooks | Nested in callbacks |
Top-level webhooks |
Move to its own section |
| $ref with siblings | Not allowed | Fully supported | No allOf wrapper needed anymore |
| exclusiveMin/Max | Boolean | Numeric value | Provide the value directly |
9. Summary
OpenAPI 3.1 is a thoroughly designed standard that can describe every aspect of a REST API, from simple CRUD endpoints to complex OAuth flows and asynchronous webhooks. The key building blocks: the root object with Info and Servers, the Paths object with operations and operationId, the parameters system with its four types, JSON Schema 2020-12 for schemas, Components for reuse and security schemes for authentication. Teams that apply all of these building blocks consistently get a specification that supports code generation, mock servers, validation and interactive documentation without rework.
The biggest lever for new teams: name operationId consistently and descriptively, centralize all error responses in components/responses, and always define schemas in components/schemas, never inline. These three decisions prevent the most common maintenance problems and make the specification maximally usable for code generators.
OpenAPI 3.1 Building Blocks: The Essentials at a Glance
Root & Paths
info, servers, tags at the root level. Paths with path items and operations. Name operationId uniquely and descriptively, it becomes the function name in SDKs.
Schemas (JSON Schema 2020-12)
type as an array for nullable fields. if/then/else for conditional validation. additionalProperties: false for strict schemas. Always add description and examples.
Components
Define schemas, responses, parameters, examples and requestBodies centrally. $ref for reuse. No inline schemas in operations for maintainable specs.
Security
BearerAuth for JWT, OAuth2 for the authorization code flow, ApiKey for server-to-server. Global security at the root level, security: [] for public endpoints.
Mironsoft
OpenAPI design, API documentation and code generation
Need a professional OpenAPI specification?
We build complete OpenAPI 3.1 specifications for REST APIs, from schema architecture through security configuration to generated client SDKs and mock servers.
Schema design
JSON Schema 2020-12 schemas for every API object
API review
Check existing specs against OpenAPI 3.1 quality standards
Code generation
Generate client SDKs and server stubs from the spec