- 1 Section
- 10 Lessons
- unbegrenzt
- API-Entwicklung & REST vertieft10
- 1.1Was ist eine API? REST vs. SOAP vs. GraphQL
- 1.2HTTP-Methoden und Statuscodes vertieft
- 1.3RESTful API designen: Ressourcen und Endpunkte
- 1.4Authentifizierung in APIs: API-Key, Basic Auth
- 1.5JWT – JSON Web Tokens
- 1.6OAuth2 und OpenID Connect
- 1.7API-Versionierung
- 1.8Rate Limiting und Throttling
- 1.9API-Testing: Postman und curl
- 1.10Aufgaben API
RESTful API designen: Ressourcen und Endpunkte
Eine REST-API kann technisch korrekt sein und trotzdem schlecht zu benutzen. „Korrekt" heißt: gültige HTTP-Methoden und Statuscodes. „Gut zu benutzen" heißt: konsistent, vorhersehbar, selbsterklärend. Genau darum geht's in dieser Lektion: wie du eine API entwirfst, die andere Entwickler*innen sofort verstehen und gerne nutzen.
Wir schauen uns an, wie man Ressourcen identifiziert, wie man verschachtelte URLs strukturiert, wie Filterung und Pagination funktionieren, wie HATEOAS aussieht und wie Fehler einheitlich beantwortet werden. Am Ende hast du eine Checkliste, mit der du jede REST-API auf Designqualität prüfen kannst.
1) Vom Verb zum Substantiv – die Grundregel
Die wichtigste Regel beim REST-Design: URLs sind Substantive, HTTP-Methoden sind die Verben. Wer einmal verstanden hat, dass die URL nur die Ressource identifiziert und die Methode was damit passiert, hat die halbe Miete. Hier eine direkte Gegenüberstellung typischer Anfänger-Fehler und ihrer RESTful Lösung:
2) Plural oder Singular?
Eine häufige Designfrage: heißt es /product/42 oder /products/42? Beides ist verständlich, aber die Konvention sagt klar: Plural. Begründung: die URL /products bezeichnet die Sammlung („alle Produkte"), /products/42 ein Element daraus. Wer Singular nutzt, bekommt sofort den Konflikt: was bedeutet /product?
Die Konsequenz ist konsequenter Plural durchs ganze System: /users, /orders, /products, /categories. Auch wenn es nur ein einziges Element gibt, bleibt der Plural – das wirkt zwar manchmal seltsam (/companies/1 für die einzige Firma im System), aber es ist konsistent. Konsistenz schlägt Eleganz im API-Design fast immer.
3) Verschachtelte Ressourcen
Was tun, wenn Ressourcen zueinander gehören? Bestellungen gehören zu einem Kunden, Bewertungen zu einem Produkt. Die natürliche URL-Form spiegelt das wider:
GET /orders/42 ist oft praktischer als GET /users/7/orders/42, weil man die User-ID nicht kennen muss. Beide URLs gleichzeitig anzubieten ist okay – sie zeigen dieselbe Ressource aus verschiedenen Sichten.4) Query-Parameter für Filter, Sortierung, Suche
URLs identifizieren Ressourcen. Wenn du dagegen filtern, sortieren oder durchsuchen willst, sind Query-Parameter der richtige Ort. Sie kommen nach dem Fragezeichen und sind als Schlüssel-Wert-Paare strukturiert:
GET /products?category=Bücher&preis_min=10&preis_max=50Mehrere Filter werden mit
& verkettet. Server interpretiert die als „und"-Verknüpfung.GET /products?sort=preis – aufsteigend. ?sort=-preis – absteigend (Minus-Präfix). Auch mehrfach: ?sort=kategorie,-preis.GET /products?q=notizbuch – Volltextsuche. Häufig q= als Konvention, manchmal auch search= oder query=.GET /products/42?fields=name,preis – nur diese Felder zurückgeben. Spart Bandbreite. (Mit GraphQL verschwindet diese Notwendigkeit – der Client wählt immer Felder.)GET /products?page=2&size=20 – die zweite Seite mit 20 Einträgen. Oder offset-basiert: ?offset=20&limit=20. Mehr dazu unten.GET /orders/42?include=customer,items – verwandte Ressourcen mitliefern, um zusätzliche Aufrufe zu sparen.GET /products?category=Bücher&sort=-preis&page=2&size=20 heißt: alle Bücher, nach Preis absteigend, Seite 2, 20 pro Seite. Diese Kombinierbarkeit ist eine Stärke. Achtung bei Datentypen: alles in der URL ist ein String. Der Server muss parsen – „20" wird zur Zahl 20, „true" zum Boolean true. Bei booleschen Werten oft auch ohne expliziten Wert: ?active statt ?active=true.5) Pagination live: warum nicht alles auf einmal?
Eine API, die bei GET /products alle 50.000 Produkte zurückliefert, ist katastrophal. Die Antwort ist groß, dauert lang, frisst Bandbreite und Speicher auf dem Client. Lösung: Pagination – Aufteilen in handhabbare Seiten:
meta-Objekt mit Pagination-Infos – total, page, size, has_next. Oder Links nach HATEOAS-Stil: next, prev, first, last. So weiß der Client, wo er steht und was er als nächstes laden kann, ohne raten zu müssen.Zwei Pagination-Stile sind verbreitet:
- Offset-basiert:
?offset=40&limit=20. Intuitiv, aber bei großen Datenmengen langsam – die Datenbank muss 40 Einträge überspringen. - Cursor-basiert:
?after=eyJpZCI6NDJ9. Schneller bei Riesen-Datenmengen (Twitter, Facebook nutzen das), aber komplexer zu implementieren.
Für die meisten APIs reicht Offset-Pagination. Cursor wird relevant bei Live-Feeds oder wenn die Datenmenge in die Millionen geht.
6) Aktionen, die keine CRUD-Operationen sind
Was machst du, wenn eine Operation nicht in das CRUD-Schema passt? Beispiele: „Bestellung stornieren", „Mail versenden", „Bericht generieren", „Kennwort zurücksetzen". Diese Aktionen ändern Zustand, sind aber kein einfaches Erstellen, Lesen, Aktualisieren, Löschen.
Es gibt zwei pragmatische Ansätze:
- Als Zustandsänderung modellieren (REST-konform):
PATCH /orders/42mit Body{"status": "cancelled"}. Das ändert das Statusfeld – mehr nicht. Der Server prüft die Erlaubnis (kann diese Bestellung überhaupt storniert werden?) und führt aus. - Als Sub-Ressource modellieren (pragmatischer Stil):
POST /orders/42/cancellation. Eine Stornierung wird als eigene Ressource gesehen, die man „erzeugt". AuchPOST /users/7/password-resetist eine elegante Form.
Vermeide URLs wie POST /cancelOrder/42 – das ist der Verb-in-URL-Antipattern. Wenn eine Aktion partout nicht in eine Ressource passt, ist POST auf eine Sub-Ressource oft die sauberste Lösung.
7) API-Versionierung
APIs entwickeln sich weiter. Was passiert, wenn du eine bestehende API ändern musst, ohne alte Clients zu brechen? Die Antwort: Versionierung. Es gibt drei verbreitete Ansätze, die in L7 tiefer behandelt werden – hier die Übersicht:
/api/v1/products, /api/v2/products. Vorteil: einfach, sichtbar. Nachteil: URL ändert sich.Accept: application/vnd.api+json;version=2. Vorteil: URL bleibt stabil. Nachteil: versteckter, schwerer zu testen.?version=2. Vorteil: einfach. Nachteil: ungewöhnlich, kann mit anderen Parametern kollidieren.8) Konsistente Fehler-Antworten
Wenn etwas schief geht, soll die API klare Antworten geben. Schlecht: nur ein Statuscode ohne Erklärung. Gut: ein einheitliches Fehler-Format, das jeder Endpunkt nutzt. Ein bewährtes Schema (orientiert an RFC 7807 „Problem Details"):
Eine Fehler-Antwort sollte mindestens enthalten: einen Fehler-Code (maschinenlesbar, z.B. "EMAIL_INVALID"), eine Beschreibung für Menschen, und optional eine Detail-Liste für Feld-spezifische Validierungsfehler. Beispiel:
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"error": "VALIDATION_FAILED",
"message": "Eingabe-Validierung fehlgeschlagen",
"details": [
{ "field": "email", "code": "INVALID_FORMAT", "message": "Keine gültige E-Mail" },
{ "field": "alter", "code": "OUT_OF_RANGE", "message": "Alter muss > 0 sein" }
]
}
Wichtig: alle Endpunkte deiner API sollten dieses Schema benutzen. Konsistenz ist Trumpf – wer mal so, mal anders antwortet, zwingt Frontend-Entwickler zu Sonderfällen. Frontend-Code wie error.details.find(d => d.field === 'email') funktioniert nur, wenn der Server immer dasselbe Format liefert.
9) HATEOAS – das Web-Prinzip in REST
Ein Buchstabensalat-Wort, das in IHK-Klausuren manchmal auftaucht: HATEOAS – „Hypermedia As The Engine Of Application State". Die Idee: API-Antworten enthalten nicht nur Daten, sondern auch Links auf verwandte Ressourcen und mögliche nächste Aktionen. So entdeckt der Client die API dynamisch, ähnlich wie ein Mensch das Web durch Klick-Pfade erkundet.
In der Praxis sieht eine HATEOAS-Antwort so aus:
{
"id": 42,
"status": "neu",
"betrag": 99.90,
"_links": {
"self": { "href": "/orders/42" },
"customer": { "href": "/users/7" },
"items": { "href": "/orders/42/items" },
"cancel": { "href": "/orders/42/cancellation", "method": "POST" }
}
}
Vorteil: der Client muss die URL-Struktur nicht hardcoden – er folgt den Links. Wenn sich die URLs später ändern, bleibt der Client funktionsfähig. Nachteil: in der echten Welt wird HATEOAS selten konsequent umgesetzt. Die meisten APIs sind „REST minus HATEOAS". In Klausuren wichtig: HATEOAS = Hypermedia-Links in API-Antworten. Punkt.
10) Cheat-Karten für gute REST-APIs
Eine kompakte Checkliste, die du an jeder API durchgehen kannst:
/products, nicht /product./user-profiles, nicht /UserProfiles./getProduct./users/7/orders/42 okay, mehr wird unhandlich.?-Parametern. Nicht über URL-Struktur./api/v1/. Vertieft in L7.created_at oder createdAt, nicht beides.11) Reality-Check: kein API-Design ist perfekt
Selbst die populärsten APIs der Welt – GitHub, Stripe, Twilio – brechen manchmal ihre eigenen Regeln. GitHub hat GET /repos/{owner}/{repo} mit Owner als Pfad-Parameter, statt /users/{owner}/repos/{repo}. Stripe nutzt sehr viel POST, auch wo theoretisch PUT passen würde. Das ist okay – Konsistenz innerhalb einer API ist wichtiger als orthodoxe REST-Reinheit.
Wenn du Designer einer API bist: triff früh die wichtigsten Entscheidungen (URL-Stil, Versionierungs-Ansatz, Fehler-Schema, Pagination-Stil) und ziehe sie konsequent durch. Selbst pragmatische Entscheidungen sind besser als ein wilder Stilmix.
Zusammenfassung
Gutes REST-API-Design folgt klaren Konventionen. Grundregel: URL = Substantiv (was), HTTP-Methode = Verb (wie). Anti-Patterns wie /getProduct sind falsch. Plural: /products. Verschachtelte Ressourcen wie /users/7/orders/42 – max. 2-3 Ebenen, oft zusätzlich direkter Endpunkt. Query-Parameter für Filter, Sortierung (?sort=-preis), Suche, Pagination. Pagination: Listen immer paginieren, Offset-basiert (?page=2&size=20) ist Standard; Antwort mit Meta-Daten (total, has_next). Aktionen außerhalb CRUD als Zustandsänderung (PATCH) oder Sub-Ressource (POST /orders/42/cancellation). Versionierung: URL-Versionierung am häufigsten (vertieft in L7). Konsistente Fehler-Antworten mit Code + Message + optional Details (RFC 7807). HATEOAS: Hypermedia-Links in Antworten – klausurrelevant, in der Praxis selten umgesetzt. Pragmatische Wahrheit: Konsistenz innerhalb einer API schlägt REST-Reinheit. Vertiefung: L4 Auth, L8 Rate Limiting.
