Client
Needs a URL, inputs, authentication, and possible outputs.
One Bookstore API · one evolving contract
Start with one GET. Add inputs, payloads, failures, reuse, and security
only when the HTTP promise needs them. By the end, the same small example is ready for
teams and tools—not just a documentation page.
The durable idea: OpenAPI describes the messages an HTTP API may receive and send. It is a shared contract for people and tools; the actual requests and responses still travel at runtime.
Chapter 1 · Mental model
The server implementation and the OpenAPI description are two representations of the same public behavior. Neither replaces the other.
Needs a URL, inputs, authentication, and possible outputs.
Names and constrains the request and response shapes.
Must make its runtime behavior conform to the published promise.
Chapter 2 · Document anatomy
A description starts with identity and location, then moves through endpoints to operations, messages, and reusable pieces.
/books/{bookId}
openapi ≠ info.version
openapi: 3.1.0 selects specification behavior.
info.version: 1.0.0 versions this API description.
The same description can be JSON. Request and response bodies may use JSON, XML, images, files, or other media types.
An endpoint is a path such as /books/{bookId}. An operation is a
method on it, such as GET. One path can hold several operations.
Chapter 3 · First operation
Our first contract says where the Bookstore API lives, names one operation, and promises one successful response.
openapi: 3.1.0
info:
title: Bookstore API
version: 1.0.0
servers:
- url: https://api.bookstore.test
paths:
/books/{bookId}:
get:
operationId: getBook
summary: Get one book
parameters:
- name: bookId
in: path
required: true
schema: { type: string }
responses:
'200':
description: Book found
Chapter 4 · Inputs
The first call needed a required path value. Now add an optional query value—and keep both distinct from a request body.
# under /books/{bookId} → get
parameters:
- name: bookId # already present
in: path
required: true
schema: { type: string }
- name: include
in: query
required: false
schema:
type: array
items: { enum: [reviews, availability] }
style: form
explode: false
Chapter 5 · Request bodies
Creating a book sends a structured representation. requestBody describes
its media type and schema.
/books:
post:
operationId: createBook
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [title, author]
properties:
title: { type: string, minLength: 1 }
author: { type: string, minLength: 1 }
responses:
'201':
description: Book created
Path IDs, filters, pagination cursors, locale headers.
?limit=20&cursor=abc
An object, document, upload, or other payload with a media type.
{ "title": "The Left Hand of Darkness" }
Types, required fields, ranges, formats, composition, and more.
type: string · minLength: 1
Chapter 6 · Response branches
An operation produces one branch per call. Document each status, its headers, media type, and body independently.
responses:
'201':
description: Book created
headers:
Location: { schema: { type: string, format: uri-reference } }
content:
application/json:
schema: { type: object } # Book shape for now
'400':
description: Invalid request
content:
application/problem+json:
schema: { type: object } # Problem shape
'500':
description: Unexpected failure
The body is a Book. Location points at the new resource.
HTTP/1.1 201 Created
Location: /books/bk_124
Content-Type: application/json
{ "id": "bk_124", "title": "The Dispossessed" }
A stable Problem envelope describes validation failure without pretending it is a Book.
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
{ "type": "…/validation", "title": "Invalid request",
"status": 400 }
It can reuse the same envelope shape, while type, status, and
recovery semantics remain distinct.
HTTP/1.1 500 Internal Server Error
Content-Type: application/problem+json
{ "type": "…/internal", "title": "Unexpected failure",
"status": 500 }
Chapter 7 · Reuse with $ref
Inline shapes teach the first call clearly. Once Book and Problem repeat, move them to
components and point to them.
components:
schemas:
Book:
type: object
required: [id, title, author]
properties:
id: { type: string }
title: { type: string }
author: { type: string }
Problem:
type: object
required: [type, title, status]
# A use site becomes small:
schema:
$ref: '#/components/schemas/Book'
$ref → Book
One named wire contract
$ref → Book
Best default. It evolves with one API and resolves without a network.
#/components/schemas/Book
Useful for a larger service description split across owned files.
./models.yaml#/Book
Use for deliberately shared semantics. Pin an immutable release.
…/common/2.3.0.yaml#/Problem
Chapter 8 · Security
A security scheme defines how credentials travel. A security requirement says which operations need that scheme.
components:
securitySchemes:
BookstoreKey:
type: apiKey
in: header
name: X-API-Key
security:
- BookstoreKey: []
# Optional override on a public operation:
get:
security: []
Client reads BookstoreKey.
X-API-Key: … travels with the request.
Server verifies the credential.
Server decides whether this action is allowed.
Chapter 9 · Ownership + scale
As servers multiply, operation ownership should remain legible. A registry can centralise validation and distribution without becoming one giant hand-edited source file.
Keep components local. One team releases paths and schemas together.
Paths follow runtime ownership. Share only stable wire vocabulary.
Index immutable releases and fan them out to tools. Do not erase local ownership.
Chapter 10 · Contract workflow
A correct file can still drift from production. The reliable loop connects design, implementation, compatibility, and publication.
Review names, messages, and failure semantics before implementation hardens them.
Lint the description and resolve every local or external reference.
Diff against the last published release; classify removals and tighter constraints.
Exercise the running server against examples, schemas, statuses, and headers.
Record exact inputs, versions, and digests. Never silently replace a release.
Build docs, SDKs, mocks, and gateway configuration from the published artifact.
Chapter 11 · Design checklist
If an early answer is fuzzy, later schema detail will only make the ambiguity more expensive.
Name one clear operation with a stable operationId.
Resolve server URL + path template + HTTP method.
Place each value in path, query, header, cookie, or body.
State media types and parameter serialization where defaults are insufficient.
Model success, expected client errors, and server failures separately.
Name common semantics in components; keep coincidental similarity local.
Define the security mechanism and apply the correct requirement.
Assign ownership, diff releases, test conformance, and publish immutably.
Chapter 12 · Concept atlas
The core example covers most daily work. These adjacent features solve specific problems; open them when the use case demands one.
A schema constrains a family of valid values. An example is one concrete value for docs, tests, or mocks. An example does not add validation rules.
A callback is an out-of-band request tied to a parent operation and runtime
expression. Top-level webhooks describe incoming requests initiated
independently of another API call.
A Link Object describes how values from one response can become inputs to another operation. It expresses navigability; it does not execute the next request.
JSON Schema composition keywords such as oneOf express alternatives. A
discriminator can help select a schema using a payload field, but it should
clarify—not substitute for—valid schemas.
Model cursor or page inputs as query parameters and the page envelope as a response schema. Document ordering stability and cursor lifetime in prose; shapes alone cannot express them.
deprecated: true warns consumers away from an operation. It does not
remove it or define a retirement date. Pair it with migration guidance and a
compatibility policy.
Fields beginning with x- carry tool- or organisation-specific metadata.
Use them deliberately and document which consumer owns their meaning.
Bundling collects referenced resources into one distributable document while retaining references. Dereferencing replaces references with targets and can become large or encounter cycles. Choose for the consumer.
Chapter 13 · Sources
Examples use widely supported OpenAPI 3.1 syntax. OpenAPI 3.2.0 is the latest published specification as of this artifact’s August 2026 revision.