Skip to content

OpenAPI 3.1 Reference: Schemas, Components, Webhooks, SDK Generation & Tooling

OpenAPI 3.1 is the standard for documenting HTTP APIs. It’s the spec that powers Swagger UI, Redoc, SDK generators, and mock servers. Getting the spec right means your docs, client libraries, and validation all work from the same source of truth.

1. Document Structure & Info

openapi.yaml skeleton — info, servers, tags, and security schemes
openapi: "3.1.0"
info:
  title: Orders API
  version: "2.0.0"
  description: |
    REST API for order management.
    [Changelog](https://example.com/changelog)
  contact:
    name: Platform Team
    email: platform@example.com
  license:
    name: MIT
    identifier: MIT

servers:
  - url: https://api.example.com/v2
    description: Production
  - url: https://api.staging.example.com/v2
    description: Staging
  - url: http://localhost:8000
    description: Local development

tags:
  - name: orders
    description: Order lifecycle management
  - name: users
    description: User accounts

# Security schemes (define once, apply globally or per-endpoint):
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    apiKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key

# Apply globally (can be overridden to {} on public endpoints):
security:
  - bearerAuth: []

2. Paths, Parameters & Request Bodies

Define endpoints, path/query/header parameters, and JSON request bodies
paths:
  /orders:
    get:
      summary: List orders
      operationId: listOrders           # unique ID — used by SDK generators
      tags: [orders]
      parameters:
        - name: status
          in: query                      # path | query | header | cookie
          required: false
          schema:
            type: string
            enum: [pending, processing, completed, cancelled]
          description: Filter by order status
        - name: page
          in: query
          schema:
            type: integer
            minimum: 1
            default: 1
        - 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/OrderList"

    post:
      summary: Create order
      operationId: createOrder
      tags: [orders]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateOrderRequest"
            example:
              customerId: "cust_123"
              items:
                - productId: "prod_456"
                  quantity: 2
      responses:
        "201":
          description: Order created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Order"
        "422":
          $ref: "#/components/responses/ValidationError"

  /orders/{orderId}:
    parameters:
      - name: orderId
        in: path
        required: true
        schema:
          type: string
          pattern: "^ord_[a-z0-9]{12}$"
    get:
      summary: Get order by ID
      operationId: getOrder
      tags: [orders]
      responses:
        "200":
          description: Order details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Order"
        "404":
          $ref: "#/components/responses/NotFound"

3. Schemas & Components

Reusable schemas with $ref, composition (allOf/oneOf/anyOf), and discriminators
components:
  schemas:
    Order:
      type: object
      required: [id, customerId, status, total, createdAt]
      properties:
        id:
          type: string
          readOnly: true                # excluded from request schemas
          example: ord_a1b2c3d4e5f6
        customerId:
          type: string
        status:
          type: string
          enum: [pending, processing, completed, cancelled]
        total:
          type: number
          format: float
          minimum: 0
        items:
          type: array
          items:
            $ref: "#/components/schemas/OrderItem"
        createdAt:
          type: string
          format: date-time
          readOnly: true

    OrderItem:
      type: object
      required: [productId, quantity, unitPrice]
      properties:
        productId:
          type: string
        quantity:
          type: integer
          minimum: 1
        unitPrice:
          type: number

    # Composition with discriminator (polymorphism):
    PaymentMethod:
      oneOf:
        - $ref: "#/components/schemas/CreditCard"
        - $ref: "#/components/schemas/BankTransfer"
        - $ref: "#/components/schemas/Crypto"
      discriminator:
        propertyName: type              # field that tells the parser which schema
        mapping:
          credit_card: "#/components/schemas/CreditCard"
          bank_transfer: "#/components/schemas/BankTransfer"
          crypto: "#/components/schemas/Crypto"

    # allOf (extend/merge schemas):
    AdminUser:
      allOf:
        - $ref: "#/components/schemas/User"    # inherit all User fields
        - type: object
          properties:
            permissions:
              type: array
              items:
                type: string

  # Reusable responses:
  responses:
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    ValidationError:
      description: Request validation failed
      content:
        application/json:
          schema:
            type: object
            properties:
              errors:
                type: array
                items:
                  type: object
                  properties:
                    field: {type: string}
                    message: {type: string}

4. Tooling — Validation, Docs & SDK Generation

Lint the spec, serve Swagger UI locally, generate TypeScript/Python clients
# Validate the spec (catches $ref errors, missing schemas, etc.):
npx @redocly/cli lint openapi.yaml      # best validator — checks rules + $refs
npx swagger-codegen validate openapi.yaml

# Redocly lint rules (.redocly.yaml):
extends: [recommended]
rules:
  operation-operationId: error          # require operationId on every endpoint
  tag-description: warn
  no-unused-components: warn

# Serve Swagger UI locally (zero install via Docker):
docker run --rm -p 8080:8080   -v $(pwd)/openapi.yaml:/tmp/spec.yaml   -e SWAGGER_JSON=/tmp/spec.yaml   swaggerapi/swagger-ui

# Serve Redoc (cleaner UI):
npx @redocly/cli preview-docs openapi.yaml

# Generate TypeScript fetch client:
npx openapi-typescript openapi.yaml --output src/types/api.ts
# or full SDK:
docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate   -i /local/openapi.yaml   -g typescript-fetch   -o /local/generated/

# Generate Python client:
docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate   -i /local/openapi.yaml   -g python   -o /local/generated-python/

# Mock server (for frontend dev before backend is ready):
npx @stoplight/prism-cli mock openapi.yaml --port 4010
# curl http://localhost:4010/orders  → returns example data from spec

5. Webhooks, Links & OpenAPI 3.1 Features

Document webhooks, response links, and OpenAPI 3.1 JSON Schema alignment
# OpenAPI 3.1 key changes from 3.0:
# - Full JSON Schema 2020-12 compatibility (type: [string, null] instead of nullable: true)
# - webhooks: top-level key for documenting outbound webhooks
# - schema.$schema field supported

# Webhooks (document what you SEND, not receive):
webhooks:
  orderCompleted:
    post:
      summary: Order completed notification
      description: Sent when an order transitions to 'completed' status
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required: [event, data, timestamp]
              properties:
                event: {type: string, example: order.completed}
                data:
                  $ref: "#/components/schemas/Order"
                timestamp:
                  type: string
                  format: date-time
      responses:
        "200":
          description: Webhook received successfully

# Links (connect response fields to other operations):
paths:
  /orders:
    post:
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Order"
          links:
            GetOrderById:
              operationId: getOrder
              parameters:
                orderId: "$response.body#/id"   # use the id from the response

# Nullable types (3.1 syntax vs 3.0):
# OpenAPI 3.0:  {type: string, nullable: true}
# OpenAPI 3.1:  {type: [string, "null"]}

# Or use oneOf for complex nullable schemas:
schema:
  oneOf:
    - $ref: "#/components/schemas/User"
    - type: "null"

Track OpenAPI, Swagger, and API tooling releases.
ReleaseRun monitors developer tooling and 13+ technologies.

Related: FastAPI Reference | NGINX Ingress Controller Reference | TypeScript EOL Tracker

🔍 Free tool: npm Package Health Checker — check openapi-types, swagger-ui-express, and related packages for known CVEs and active maintenance.

Founded

2023 in London, UK

Contact

hello@releaserun.com