← Back to docs

Recipe / API Design

OpenAPI design patterns

A well-shaped OpenAPI spec is the contract that lets SDKs, gateways, mock servers, and customer integrations move in lockstep. This recipe walks through three patterns Meridian uses across the 250-deployment gateway so endpoints stay predictable as we scale providers.

1. Version your contract, not your URL

Pin openapi: 3.1.0 at the top and let info.version carry the date stamp. Avoid /v2/ path prefixes unless the wire format actually broke. Consumers regenerate SDKs from the spec hash, so a minor field add is invisible to them.

2. Name operations, reuse schemas

Every path-method pair needs an explicit operationId in camelCase. That string becomes the method name in every generated SDK. Pull request and response bodies into components/schemas the moment two operations share even one field.

3. Document streaming as a content negotiation

Server-sent events do not fit cleanly into OpenAPI's response object, so model the streaming case as a separate content-type under the same 200 response. Set stream: true in the request schema and document the SSE frame layout in the description block.

openapi.yaml
openapi: 3.1.0
info:
  title: Meridian Inference API
  version: 2026.06.27
  description: Unified gateway for 250+ LLM deployments
servers:
  - url: https://llm.getnimbus.net/v1
paths:
  /chat/completions:
    post:
      operationId: createChatCompletion
      summary: Create a chat completion
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatRequest'
      responses:
        '200':
          description: Streamed or buffered completion
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatResponse'
components:
  schemas:
    ChatRequest:
      type: object
      required: [model, messages]
      properties:
        model:
          type: string
          example: azure/model-router
        messages:
          type: array
          items:
            $ref: '#/components/schemas/Message'
        stream:
          type: boolean
          default: false