Was ist OpenAPI?

OpenAPI ist ein Standard zur Beschreibung von Programmierschnittstellen – Application Programming Interfaces (API). Die OpenAPI-Spezifikation definiert ein offenes und herstellerneutrales Beschreibungsformat für API-Dienste. Insbesondere lassen sich mithilfe von OpenAPI REST-konforme APIs beschreiben, entwickeln, testen und dokumentieren.

Die heutige OpenAPI-Spezifikation ging aus dem Vorgängerprojekt Swagger hervor. Die Entwicklungsfirma SmartBear stellte die existierende Swagger-Spezifikation unter eine offene Lizenz und übergab die Pflege und Weiterentwicklung an die OpenAPI-Initiative. Mitglieder der OpenAPI-Initiative sind neben SmartBear Branchengrößen wie Google, IBM und Microsoft; gefördert wird das Projekt auch von der Linux Foundation.

Die kostenlose IONOS API

Aktualisieren Sie Domain-, DNS-, SSL-Einstellungen und mehr mit der IONOS API.

DNS-Management
SSL-Verwaltung
API-Dokumentation

OpenAPI im Überblick

Ein Punkt, der für Verwirrung sorgen kann, ist die Unterscheidung zwischen OpenAPI und Swagger. Bei OpenAPI handelt es sich um eine Spezifikation, d. h. eine abstrakte Beschreibung, die nicht an eine spezifische technische Implementation gebunden ist. Bis zur Version 2.0 hieß diese Spezifikation noch Swagger und wurde dann in OpenAPI-Spezifikation umbenannt. Jedoch existieren die von der ursprünglichen Entwicklungsfirma SmartBear bereitgestellten Tools unter dem Namen Swagger weiter.

Mit OpenAPI lässt sich eine API auf einheitliche Weise beschreiben. Man spricht dabei von der „API-Definition“. Diese wird in einem maschinenlesbaren Format erzeugt. Insbesondere kommen dabei die beiden Sprachen YAML und JSON zum Einsatz.

Hinweis

Neben der API-Definition hört man manchmal auch den Ausdruck „API-Spezifikation“. Dabei handelt es sich um eine rein für den menschlichen Betrachter erstellte, abstrakte Beschreibung einer API.

Technisch unterscheiden sich YAML und JSON nur geringfügig, so dass es möglich ist, eine bestehende API-Definition automatisiert von einer Sprache in die andere zu konvertieren. Jedoch weist YAML eine klarere Struktur auf und ist für den Menschen einfacher zu lesen. Hier ein Beispiel desselben OpenAPI-Server-Objekts, dargestellt in YAML und JSON:

# YAML
servers:
- url: https://development.example.com/v1
    description: Development server
- url: https://staging.example.com/v1
    description: Staging server
- url: https://api.example.com/v1
    description: Production server
// JSON
{
    "servers": [
        {
            "url": "https://development.example.com/v1",
            "description": "Development server"
        },
        {
            "url": "https://staging.example.com/v1",
            "description": "Staging server"
        },
        {
            "url": "https://api.example.com/v1",
            "description": "Production server"
        }
    ]
}

Die OpenAPI-Spezifikation definiert eine Reihe von Eigenschaften, die sich für den Aufbau einer eigenen API nutzen lassen. Diese Eigenschaften sind als sogenannte Objekte (engl. „Objects“) zusammengefasst. In der aktuellen Version 3.0.3 legt OpenAPI u. a. die Struktur für die folgenden Objekte fest:

  • Info Object: Version, Name etc. der API
  • Contact Object: Kontaktinformation des API-Anbieters
  • License Object: Lizenz, unter der die API ihre Daten bereitstellt
  • Server Object: Hostnamen, URL-Struktur und Ports der Server, über die die API angesprochen wird
  • Components Object: gekapselte Komponenten, die sich innerhalb einer API-Definition mehrfach verwenden lassen
  • Paths Object: relative Pfade zu Endpunkten der API, die mit dem Server Object zusammen genutzt werden
  • Path Item Object: für einen spezifischen Pfad zulässige Operationen wie GET, PUT, POST, DELETE
  • Operation Object: legt u. a. die Parameter und die zu erwartenden Server-Responses für eine Operation fest

Was sind die Einsatzgebiete von OpenAPI?

Generell wird OpenAPI eingesetzt, um REST-APIs auf einheitliche Weise zu beschreiben. Da diese Beschreibung, also die API-Definition, in einem maschinenlesbaren Format vorliegt, lassen sich daraus automatisiert verschiedene virtuelle Artefakte erzeugen. Dazu gehören insbesondere:

  • Erzeugung von API-Dokumentation: Aus der maschinenlesbaren API-Definition wird automatisiert eine HTML-basierte Dokumentation erzeugt. Diese dient als Nachschlagewerk für Entwickler, die auf die Dienste der API zugreifen. Ändert sich die API-Definition, wird die Dokumentation neu erzeugt, so dass beide im Einklang bleiben.
  • Erzeugung von Anbindungen in verschiedenen Programmiersprachen: Mittels geeigneter Tools kann aus der API-Definition eine passende klientenseitige Software-Bibliothek in einer unterstützten Programmiersprache erzeugt werden. Somit wird Programmierern unterschiedlichster Couleur der Zugriff auf die API ermöglicht. Die Software-Bibliothek wird ganz normal eingebunden; Zugriffe auf die API-Dienste erfolgen dann z. B. über Funktionsaufrufe innerhalb der gewohnten Programmierumgebung.
  • Erzeugung von Testfällen: Jede Komponente einer Software muss Tests unterzogen werden, um die Funktionalität sicherzustellen. Insbesondere muss eine Software-Komponente bei jeder Änderung des zugrundeliegenden Codes erneut getestet werden. Aus der API-Definition lassen sich diese Testfälle automatisiert erzeugen, so dass die Funktionalität der Software-Komponenten durchgehend überprüft werden kann.

Der Vollständigkeit halber sei hier angemerkt, dass sich nicht jede beliebige API mittels OpenAPI abbilden lässt. REST-APIs werden jedoch explizit unterstützt.

Was sind die Vorteile von OpenAPI?

Generell liegt der Vorteil von OpenAPI darin, bei der Entwicklung und fortlaufenden Pflege einer API deren Implementation, Dokumentation und Tests in Einklang zu halten. Ferner erlaubt die Nutzung der OpenAPI-Spezifikation eine bessere Koordination der API-Entwicklung zwischen Backend und Frontend. Auf beiden Seiten können aus der API-Definition Code-Komponenten erzeugt werden, so dass Backend- und Frontend-Teams entwickeln und testen können, ohne auf die jeweils andere Seite warten zu müssen.

Neben diesen generellen Vorteilen wird OpenAPI insbesondere als standardisierte Basis für die Entwicklung von REST-APIs eingesetzt. Dies ist attraktiv, da es nicht trivial ist, eine REST-konforme API von Hand zu entwickeln. Jedoch haben REST-APIs einige Vorteile. So läuft REST über HTTP/S und die Ports dafür sind in jeder Firewall offen.

Ferner bietet die Nutzung von OpenAPI die folgenden Vorteile:

  • HTTP-APIs unabhängig von einer spezifischen Programmiersprache definieren
  • Server-Code für eine in OpenAPI definierte API generieren
  • Klientenseitige Bibliotheken für eine OpenAPI-konforme API in mehr als 40 Programmiersprachen generieren
  • Eine OpenAPI-Definition mit geeigneten Tools verarbeiten
  • Interaktive API-Dokumentation erstellen
  • Menschen und Maschinen ermöglichen, die Kapazitäten eines Services zu entdecken und zu verstehen, ohne dafür Einsicht in den Quelltext oder zusätzliche Dokumentation nehmen zu müssen.
  • Auf API-Services mit minimalem Implementationsaufwand zugreifen

Welche OpenAPI-Versionen gibt es und wie unterscheiden sich diese?

Zum Zeitpunkt der Artikelerstellung ist die OpenAPI-Version 3.0.3 aktuell. Hier ein kurzer Überblick der vorhergehenden Versionen:

Version Name Status
1.0, August 2011 Swagger-Spezifikation nicht mehr in Benutzung
2.0, September 2014 Swagger-Spezifikation → OpenAPI-Spezifikation weiterhin unterstützt
3.0, Juli 2017 OpenAPI-Spezifikation weiterhin unterstützt

Neuer Name des Root-Objekts

Mit dem Erscheinen der Version 3.0 wurde das OpenAPI-Objekt eingeführt, das das vormals benutzte Swagger-Objekt ersetzt:

# <= 2.0
"swagger": "2.0"
# >= 3.0
"OpenAPI": "3.0.0"

Mehrere Hosts/Server

Ab OpenAPI-Version 3.0 kann eine API über mehr als nur einen Server angesprochen werden. Ferner ist es möglich, Teile der Server-URL variabel zu definieren. Hier ein Beispiel:

"servers": [
        {
            "url": "https://{username}.example.com:{port}/{basePath}",
            "description": "The production API server",
            "variables": {
                "username": {
                    "default": "demo",
                    "description": "this value is assigned by the service provider, in this example `example.com`"
                },
                "port": {
                    "enum": [
                        "8443",
                        "443"
                    ],
                    "default": "8443"
                },
                "basePath": {
                    "default": "v2"
                }
            }
        }
    ]

Neue Komponenten- und Referenz-Objekte

Bei den in OpenAPI-Version 3.0 hinzugekommenen Komponenten- und Referenz-Objekten handelt es sich um eine der größeren Neuerungen. Das Komponenten-Objekt erlaubt die Definition mehrerer, innerhalb der API-Definition wiederverwendbarer Objekte. Diese sogenannten Komponenten werden innerhalb der API-Definition mithilfe des speziellen Konstrukts $ref eingebunden.

Mittels der Komponenten und Referenzen ist es möglich, eine API-Definition aus mehreren, wiederbenutzbaren Teilen aufzubauen. Dies erleichtert die Lesbarkeit und verringert die Größe des gesamten Dokuments. Nachfolgend ein Beispiel aus der offiziellen GitHub-API-Definition:

  1. Schema eines GitHub-Code-Repositorys, als Komponenten-Objekt definiert
  2. Lizenz-Definition, über eine extern definierte Komponente referenziert
"components": {
    "schemas": {
        // Repository-Schema
        "repository": {
            "title": "Repository",
            "description": "A git repository",
            "type": "object",
            "properties": {
                "id": {
                    "description": "Unique identifier of the repository",
                    "example": 42,
                    "type": "integer"
                },
                "node_id": {
                    "type": "string",
                    "example": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5"
                },
                "name": {
                    "description": "The name of the repository.",
                    "type": "string",
                    "example": "Team Environment"
                },
                "full_name": {
                    "type": "string",
                    "example": "octocat/Hello-World"
                },
                // Lizenz-Definition
                "license": {
                    "nullable": true,
                    "allOf": [
                        {
                            // Referenz auf extern definierte Komponente
                            "$ref": "#/components/schemas/license-simple"
                        }
                    ]
                },

OpenAPI im Einsatz: Zwei Beispiele

Die OpenAPI-Spezifikation und die damit verbundenen Tools, insbesondere von Swagger, werden auf breiter Basis zur Erstellung diverser APIs verwendet. Wir stellen hier zwei Beispiele vor:

GitHub v3 REST API

Der beliebte Git-Service GitHub nutzt OpenAPI, um die seine „GitHub v3 REST API“ zu beschreiben. Die API-Definition liegt auf GitHub als Repository vor. Mit ihrer Hilfe kann ein Nutzer genau erschließen, welche Services über die GitHub-API angesprochen werden können und wie genau die dabei zum Zuge kommenden Aufrufe strukturiert sein müssen. Ferner kann ein jeder die API nutzen, um mittels geeigneter Tools dafür passenden Code zu erzeugen.

Laut GitHub dient die API-Definition dazu, die REST API zu beschreiben, zu erzeugen, zu konsumieren und zu visualisieren. Zum Zeitpunkt der Artikelerstellung liegt die API-Definition nicht vollständig vor. So fehlen noch einige Header-Felder, die in Zukunft hinzugefügt werden. Ferner wird darauf hingewiesen, dass manche der möglichen API-Operationen über verschiedene Pfade ausgeführt werden können, wobei ggf. nur ein Pfad in der Spezifikation aufgeführt ist.

Aus Gründen der Kompatibilität bietet GitHub die API-Definition in verschiedenen Formaten an. Zum einen existiert eine als gebündelt („bundled“) bezeichnete Version. Diese enthält die mit OpenAPI 3.0 eingeführten Komponenten und darauf verweisende Referenzen. Als Gegenstück dazu wird eine als dereferenziert („dereferenced“) bezeichnete Version angeboten, in der die Referenzen allesamt aufgelöst sind. Aufgrund der dabei auftretenden Redundanz ist die dereferenzierte API-Definition um etwa den Faktor drei größer als die gebündelte. Viele Tools unterstützen noch keine Referenzen; für diese Fälle bietet sich die dereferenzierte API-Definition an.

Sie können sich die API-Definition selbst anschauen. Wir weisen darauf hin, dass die komplette Datei mehrere Megabyte groß ist. Für eine Textdatei handelt es sich dabei um eine unglaublich große Menge an Informationen. Auf GitHub kann eine derartig große Datei nicht direkt dargestellt werden. Sie können aber den folgenden Link nutzen, um sich die GitHub REST API im Browser anzuschauen. Hierbei handelt es sich um die deutlich kompaktere und besser lesbare YAML-Version: GitHub REST API (YAML).

Petstore-Beispiel-API von SwaggerHub

Als zweites verweisen wir auf eine Beispiel-API, die bei SwaggerHub erzeugt werden kann. SwaggerHub ist eine Onlineplattform für Design und Entwicklung von REST-APIs mit OpenAPI. Sie können sich dort ein kostenloses Nutzerkonto einrichten; zum Anmelden genügt aber auch ein bereits bestehendes Nutzerkonto bei GitHub.

Sobald Sie in SwaggerHub eingeloggt sind, können Sie eine neue API erstellen. Dabei gibt es die Möglichkeit, auf einem bestehenden Template aufzusetzen. Beispielsweise existiert ein API-Template für einen virtuellen „Petstore“, also einen Tierladen. Die mit dem Template erzeugte Petstore-API umfasst ein breites Spektrum an OpenAPI-Objekten. Dazu gehören u. a.:

  • Kontaktinformation, Nutzungsbedingungen, Lizenz etc.
  • Die API-Endpoints und die Operationen eines jeden Endpoints
  • Die erlaubten Eingabe- und Ausgabe-Parameter der Operationen
  • Sicherheitsvorgaben

Schaut man sich die Petstore-API an, kann man eine Menge darüber lernen, wie OpenAPI funktioniert. Ferner dient die Petstore-Definition als ein gutes Beispiel für den Aufbau einer REST-konformen API. Abschließend sei ein Code-Beispiel aus der Petstore-API gegeben. Wir analysieren den nachfolgenden Code-Abschnitt:

  1. Der Code definiert den API-Endpoint '/pet'.
  2. Mit einem HTTP-POST Request wird ein neues Tier dem Tierladen hinzugefügt.
  3. Nutzen Sie stattdessen das HTTP-Verb PUT am selben Endpoint, können Sie ein bereits vorhandenes Tier verändern.
  4. Für die Operationen sind verschiedene Server-Antworten definiert. Die dafür festgelegten HTTP-Statuscodes umfassen in diesem Beispiel den bekannten Statuscode 404 „Not Found“. Dieser wird im Fall der Petstore-API als „Pet not found“ stilisiert.
Hinweis

Bei den mit '$ref' beginnenden und mit „OpenAPI 3.0+ Component“ kommentierten Codezeilen handelt es sich um Referenzen zu individuell definierten OpenAPI-Komponenten.

# Petstore API Template #
# API Endpoint '/pet'
/pet:
    # HTTP-POST Request
    post:
        tags:
            - pet
        summary: Add a new pet to the store
        operationId: addPet
        # HTTP-Status codes
        responses:
            '405':
                description: Invalid input
        security:
            # Permissions
            - petstore_auth:
                - 'write:pets'
                - 'read:pets'
        requestBody:
            # OpenAPI 3.0+ Component
            $ref: '#/components/requestBodies/Pet'
    # HTTP-PUT Request
    put:
        tags:
            - pet
        summary: Update an existing pet
        operationId: updatePet
        # HTTP-Status codes
        responses:
            '400':
                description: Invalid ID supplied
            '404':
                description: Pet not found
            '405':
                description: Validation exception
        security:
            # Permissions
            - petstore_auth:
                - 'write:pets'
                - 'read:pets'
        requestBody:
            # OpenAPI 3.0+ Component
            $ref: '#/components/requestBodies/Pet'
Fazit

OpenAPI hat sich als offenes und herstellerneutrales Beschreibungsformat für API-Dienste etabliert. Es ist zu erwarten, dass OpenAPI innerhalb der absehbaren Zukunft als Standard für den Aufbau von REST-APIs breite Verwendung finden wird.