🧭OpenAPI in der Praxis

Was man beim Schreiben und Pflegen einer API-Beschreibung beachten sollte – und wofür OpenAPI nicht gedacht ist.

🏷️Versionierung und Breaking Changes

info.version ist die Version der Beschreibung; die API-Version steht oft zusätzlich in der URL (/v1) oder in einem Header. Wichtiger als das Schema der Versionsnummer ist, Breaking Changes zu erkennen.
ÄnderungBreaking?Warum
Neues optionales Feld in einer Antwort✅ neinClients ignorieren unbekannte Felder (sollten sie jedenfalls).
Neuer optionaler Query-Parameter✅ neinAlte Anfragen bleiben gültig.
Neuer Endpunkt / neue Operation✅ neinBestehende Aufrufe ändern sich nicht.
Feld in der Antwort entfernen oder umbenennen💥 jaClients, die es lesen, brechen.
Optionales Request-Feld wird required💥 jaAlte Anfragen werden mit 400 abgelehnt.
Typ ändern (integer → string)💥 jaDeserialisierung und generierte Typen brechen.
Neuer Wert in einem Antwort-enum💥 jaUmstritten: streng typisierte Clients (switch ohne default) scheitern – vorher ankündigen.
Pfad oder operationId ändern💥 jaURLs und generierte Funktionsnamen ändern sich.
✅ Veraltetes ankündigen statt löschen
deprecated: true gibt es an Operationen, Parametern und Schemas (3.2 auch an Security Schemes). Generatoren machen daraus@deprecated-Hinweise; der HTTP-Header Sunset (RFC 8594) nennt das Abschaltdatum.
💡 Breaking Changes automatisch finden
Diff-Werkzeuge wie oasdiff vergleichen zwei Versionen der Beschreibung und schlagen in der CI Alarm, bevor ein Client bricht.

✅Best Practices

  • 🧩 Alles Wiederkehrende nach components: Fehlerantworten, Paging-Parameter, gemeinsame Schemas.
  • 🏷️ Sprechende, eindeutige operationIds im camelCase (listBooks, createOrder) – daraus werden Funktionsnamen.
  • 📝 summary kurz, description ausführlich; jedes Feld mit Beschreibung und Beispiel.
  • 🚦 Alle relevanten Statuscodes dokumentieren, Fehler einheitlich (Problem Details, RFC 9457).
  • 🔒 Security global setzen und öffentliche Operationen gezielt mit security: [] freigeben – sicherer als umgekehrt.
  • 🧪 In der CI prüfen: Lint (Spectral/Redocly), Beispiele gegen Schemas, Breaking-Change-Diff, Vertragstests.
  • 📂 Große Beschreibungen aufteilen (externe $ref) und für die Auslieferung bündeln.
Paginierung – ein wiederverwendbares Muster
components:
  parameters:
    Limit:
      name: limit
      in: query
      schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
    Cursor:
      name: cursor
      in: query
      schema: { type: string }
  schemas:
    BookPage:
      type: object
      required: [items]
      properties:
        items:
          type: array
          items: { $ref: '#/components/schemas/Book' }
        nextCursor:
          type: [string, 'null']   # null = letzte Seite

🐞Häufige Fehler

❗ openapi: 3.1 ohne Anführungszeichen

YAML liest eine Zahl. Immer als Text: openapi: 3.1.1 (Patch-Version angeben) bzw. version: '1.0'.

❗ Pfadparameter nicht deklariert

{id} im Pfad braucht einen Parameter name: id, in: path, required: true.

❗ nullable in 3.1

Wird als unbekanntes Schlüsselwort ignoriert. Richtig: type: [string, 'null'].

❗ $ref mit Geschwistern in 3.0

description/example neben $ref werden ignoriert – Workaround allOf: [ { $ref: … } ].

❗ Beispiele passen nicht zum Schema

Mock-Server liefern dann ungültige Daten. Beispiele in der CI gegen das Schema prüfen.

❗ Statuscodes als Zahl

Unquotiert liest YAML 200 als Zahl. Die Spezifikation verlangt Anführungszeichen ('200') für die Kompatibilität zwischen JSON und YAML – viele Parser sind nur tolerant.

❗ Keine Fehlerantworten beschrieben

Nur 200 dokumentiert → Clients wissen nicht, wie 400/401/404 aussehen. Einheitlich z. B. mit Problem Details (RFC 9457).

❗ Geheimnisse in Beispielen

Echte Tokens, Hosts oder E-Mail-Adressen haben in einer veröffentlichten Spezifikation nichts verloren – example.org und Platzhalter verwenden.

Viele davon findet der Validator im Editor – laden Sie dort das Beispiel „🐞 Mit Fehlern“.

🧭Abgrenzung: OpenAPI, AsyncAPI, GraphQL, JSON:API, MCP

StandardBeschreibtFormatTypischer Einsatz
OpenAPISynchrone HTTP-APIs (Request → Response), meist REST-artigYAML/JSON, JSON SchemaÖffentliche und interne Web-APIs, SDK-Generierung
AsyncAPIEreignisgetriebene APIs: Kanäle und Nachrichten über Kafka, MQTT, AMQP, WebSocket …YAML/JSON, an OpenAPI angelehntMessaging, Event-Streaming, IoT
GraphQLEine Abfragesprache mit einem Endpunkt; der Client wählt die FelderSDL (Schema Definition Language), IntrospectionFrontends mit vielen unterschiedlichen Datenbedarfen
JSON:APIKonvention für das Format von JSON-Antworten (data, relationships, included, Paginierung)Medientyp application/vnd.api+jsonErgänzt OpenAPI: legt fest, WIE die Nutzdaten aussehen
MCPModel Context Protocol: KI-Assistenten rufen Werkzeuge, Ressourcen und Prompts eines Servers auf (JSON-RPC 2.0)JSON-RPC, Werkzeug-Eingaben als JSON SchemaLLM-Integrationen; aus einer OpenAPI-Datei lassen sich MCP-Werkzeuge ableiten
             synchron (Anfrage → Antwort)          asynchron (Ereignisse)
           ┌─────────────────────────────┐        ┌──────────────────────┐
 Vertrag   │ OpenAPI      GraphQL (SDL)  │        │ AsyncAPI             │
           └─────────────────────────────┘        └──────────────────────┘
 Nutzdaten   JSON:API legt das Format der JSON-Dokumente fest (passt zu OpenAPI)
 KI          MCP: Werkzeuge für LLMs – deren Eingaben sind ebenfalls JSON Schema