OpenAPI Specification
A machine-readable, language-agnostic standard for describing RESTful APIs — OpenAPI 3.1 document structure, JSON Schema alignment, tooling ecosystem (Swagger UI, Redoc, code generators), API-first design workflow, and contract testing with Schemathesis and Dredd.
What it is
OpenAPI (formerly Swagger) is a vendor-neutral specification for describing HTTP APIs in a structured YAML or JSON document. An OpenAPI document captures the full interface contract: available endpoints, HTTP methods, request parameters and bodies, response schemas, authentication schemes, and metadata. OpenAPI 3.1 (released 2021) aligns fully with JSON Schema Draft 2020-12, eliminating the previous subset incompatibilities of OAS 3.0.
The specification is maintained by the OpenAPI Initiative (a Linux Foundation project) and has become the de facto standard for documenting REST APIs, enabling an ecosystem of tools for documentation, mocking, SDK generation, and contract testing.
Why it exists
Without a formal contract, the only documentation of an API is its implementation — subject to change, often stale prose, and requiring consumers to reverse-engineer behaviour. OpenAPI creates a single source of truth: documentation, mocks, generated SDKs, and contract tests can all derive from the same document. This accelerates parallel development (frontend and backend teams can work against a mock before the real implementation is ready) and catches breaking changes before they reach production.
Document structure
openapi: "3.1.0"
info:
title: Orders API
version: "2.1.0"
description: Manage customer orders.
contact:
name: Platform Team
email: platform@example.com
servers:
- url: https://api.example.com/v2
description: Production
- url: https://api.staging.example.com/v2
description: Staging
security:
- bearerAuth: [] # Default security for all paths
paths:
/orders:
get:
operationId: listOrders
summary: List orders for the authenticated user
tags: [Orders]
parameters:
- name: status
in: query
schema:
type: string
enum: [pending, confirmed, shipped, delivered]
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
"200":
description: Paginated list of orders
content:
application/json:
schema:
$ref: "#/components/schemas/OrderPage"
"401":
$ref: "#/components/responses/Unauthorized"
/orders/{orderId}:
get:
operationId: getOrder
tags: [Orders]
parameters:
- name: orderId
in: path
required: true
schema:
type: string
format: uuid
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/Order"
"404":
$ref: "#/components/responses/NotFound"
components:
schemas:
Order:
type: object
required: [id, status, total, createdAt]
properties:
id:
type: string
format: uuid
readOnly: true
status:
type: string
enum: [pending, confirmed, shipped, delivered, cancelled]
total:
type: number
format: decimal
minimum: 0
createdAt:
type: string
format: date-time
readOnly: true
items:
type: array
items:
$ref: "#/components/schemas/OrderItem"
OrderPage:
type: object
required: [data, pagination]
properties:
data:
type: array
items:
$ref: "#/components/schemas/Order"
pagination:
$ref: "#/components/schemas/Pagination"
Pagination:
type: object
properties:
nextCursor:
type: string
nullable: true
hasMore:
type: boolean
responses:
Unauthorized:
description: Authentication is required
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
NotFound:
description: Resource not found
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
API-first design workflow
In API-first development, the OpenAPI document is authored before implementation begins. The workflow is:
- Design — write the OpenAPI document collaboratively (Stoplight Studio, Swagger Editor); review in a PR.
- Mock — stand up a mock server from the spec (Prism, Stoplight Prism, WireMock with contract). Frontend teams develop against the mock immediately.
- Implement — generate server stubs or use the spec to drive TDD. The spec is the contract, not the implementation.
- Validate — run contract tests against the real implementation to verify it matches the spec.
- Publish — serve Swagger UI or Redoc documentation from the live spec. Lint the spec in CI with Spectral.
Tooling ecosystem
- Swagger UI / Redoc — render interactive HTML documentation from an OpenAPI document. Swagger UI lets users try endpoints inline; Redoc produces a three-panel reference layout.
- Prism — a mock server that generates example responses from the spec; validates requests against the schema in proxy mode.
- OpenAPI Generator / Kiota — generate typed client SDKs (TypeScript, Java, Python, Go, C#, and 50+ more) and server stubs from the spec.
- Spectral — a linter for OpenAPI documents; enforces API style guides (naming conventions, required fields, security schemes); integrates into CI.
- Schemathesis — property-based contract testing tool that generates hundreds of test cases from the OpenAPI spec and fuzzes the live API for edge cases, schema violations, and server errors.
- Dredd — transaction-level contract testing; runs requests from the spec against the real server and asserts responses match the documented schemas.
Pros and cons
Pros
- Single source of truth for documentation, mocks, SDKs, and contract tests.
- Enables parallel frontend/backend development via mock servers before implementation.
- Generated SDKs eliminate hand-written client code and keep types in sync with the server.
- Spectral linting enforces API design standards across teams automatically.
- OAS 3.1 full JSON Schema alignment removes the frustrating subset incompatibilities of 3.0.
Cons
- Code-first approaches often produce low-quality specs from framework annotations — verbose, missing descriptions, poor examples.
- Large OpenAPI documents become hard to maintain without a $ref decomposition strategy and tooling.
- OpenAPI doesn't capture behavioural semantics (ordering guarantees, rate limits, side effects) — only structural contracts.
- Generated SDKs may need manual customisation for retry logic, authentication, and pagination.
- Webhook and async API patterns are awkward in OpenAPI 3.1; AsyncAPI is a better fit for event-driven APIs.
Implementation notes
Prefer $ref decomposition
For any non-trivial API, keep schemas in components/schemas and reference them with $ref rather than inlining. Split large specs across files (paths/orders.yaml, schemas/order.yaml) and bundle them for distribution with redocly bundle or the Swagger CLI. This keeps individual files reviewable in PRs and avoids a single 5,000-line YAML file.
Write example objects
Every schema should include at least one example value. Prism uses examples to generate mock responses; Redoc and Swagger UI display them to developers. Use components/examples for named, reusable examples that can be referenced from multiple operations. Provide examples that cover the full object shape — not just required fields.
Schemathesis contract testing
Schemathesis is a property-based testing tool that reads the OpenAPI spec and automatically generates hundreds of test cases by varying parameter values, header values, and request bodies. It checks that responses match the documented status codes and schemas, and that the server never returns a 500. Run it as part of CI against a staging environment. Schemathesis catches bugs that hand-written test cases miss (missing null handling, unexpected enum values, invalid content types).
Documenting security requirements
Define security schemes in components/securitySchemes and apply them globally (top-level security field) with per-operation overrides for public endpoints. Document required OAuth2 scopes per operation using the scopes field in the security requirement. This allows API gateway tooling to auto-configure scope enforcement from the spec.
Decision checklist
- Is the OpenAPI spec authored before implementation (API-first), not extracted after?
- Does every operation have a unique
operationId? - Are all schemas in
components/schemaswith$refreferences? - Does every schema have at least one
example? - Is Spectral linting running in CI against the spec?
- Are Schemathesis or Dredd contract tests running against staging on every PR?
- Are security schemes and required scopes documented per endpoint?
- Are error responses documented with
application/problem+json(RFC 9457)?
Related patterns
- REST API Design — OpenAPI is the standard contract format for REST APIs.
- API Versioning — document versioning strategy in the
info.versionandserversfields. - Contract Testing — Schemathesis and Dredd use OpenAPI documents as the contract source.
- API Authorization — document OAuth2 scopes and security schemes in the OpenAPI spec.
Further reading
- OpenAPI Specification 3.1 — spec.openapis.org/oas/v3.1.0
- Swagger Editor — editor.swagger.io
- Spectral OpenAPI Linting — stoplight.io/open-source/spectral
- Schemathesis documentation — schemathesis.readthedocs.io
- AsyncAPI (for event-driven APIs) — asyncapi.com