OpenAPI is JSON Schema with a REST wrapper
OpenAPI (formerly Swagger) is the de facto standard for describing REST APIs. At its core, the part that describes your request and response bodies is JSON Schema. If you know JSON Schema, you already know the hardest part of OpenAPI.
A single OpenAPI document — written in JSON or YAML — can drive interactive docs, server-side request validation, mock servers, and auto-generated client SDKs in dozens of languages. Write it once, reuse it everywhere.
The shape of a spec
openapi: 3.1.0
info:
title: Orders API
version: 1.0.0
paths:
/orders/{id}:
get:
summary: Get an order
parameters:
- name: id
in: path
required: true
schema: { type: string }
responses:
"200":
description: The order
content:
application/json:
schema: { $ref: "#/components/schemas/Order" }
components:
schemas:
Order:
type: object
properties:
id: { type: string }
total: { type: number }
status: { type: string, enum: [pending, shipped, delivered] }
required: [id, total, status]The Order schema is ordinary JSON Schema. OpenAPI 3.1 aligns fully with JSON Schema 2020-12, so features like $ref, oneOf, and pattern work as expected.
Reuse with components and $ref
Define each model once under components/schemas and reference it with $ref everywhere it appears. This keeps a large API consistent and DRY:
schema:
type: array
items:
$ref: "#/components/schemas/Order"What a good spec gives you
| Output | How |
|---|---|
| Interactive docs | Swagger UI / Redoc render the spec |
| Request validation | Middleware validates bodies against the schema |
| Typed clients | Generators emit TypeScript/Go/Python SDKs |
| Mock servers | Tools serve example responses from the spec |
| Contract tests | Verify the real API matches the spec |
Writing specs that scale
- Model bodies as reusable schemas. Never inline the same object twice.
- Use `example` and `examples`. Concrete samples make docs usable and feed mock servers.
- Describe enums and formats. They become validation rules and clearer docs.
- Version deliberately. Bump
info.versionand avoid breaking changes within a major version. - Validate the spec itself. A malformed spec breaks every downstream tool — lint it in CI.
Design-first vs code-first
- Design-first: write the OpenAPI spec before coding. The spec is the contract; teams build against it in parallel. Best for public or multi-team APIs.
- Code-first: generate the spec from annotations in your code. Faster for small internal APIs but risks the spec drifting from reality.
Either way, keep the spec in version control and treat changes to it as API changes.