Start / Cheat Sheets

Cheat Sheet

API-Design und HTTP — Cheat Sheet

Stand: · Moderne API-Entwicklung mit REST, OpenAPI und Contract Testing

RESTHTTPAPI-DesignAPI-Security

Der Spickzettel zum Seminar Moderne API-Entwicklung mit REST, OpenAPI und Contract Testing, erster Teil: der Entwurf selbst — was eine Ressource ist, welche Methode was zusagt, wie ein Fehler aussieht und wo eine API angegriffen wird. Vertrag, Schema und Contract Testing stehen auf dem zweiten Blatt, Vertrag und Contract Testing. Maßgeblich sind die RFCs selbst — 9110 für HTTP-Semantik, 9111 für Caching, 9457 für Fehler; hier steht die Auswahl, die im Alltag zählt. Das Blatt hält Entscheidungen fest, den Entwurf bringt es nicht bei.

Reichweite einer API

ReichweiteConsumerÄnderungLebensdauer
internnamentlich bekanntim Team abstimmbarMonate
Partnervertraglich gebundenmit VorlaufJahre
öffentlichunbekanntnur additivoffen

Die Reichweite entscheidet, wie teuer ein Fehlentwurf wird — nicht die Technik dahinter. Sie hängt an den Consumern, nicht an der Netzwerkzone: Ein Dienst im eigenen Cluster ist nicht deshalb intern, weil er dort läuft.

Zugesagt sind in jedem Fall: welche Ressourcen es unter welchen Adressen gibt, welche Felder eine Antwort mindestens enthält, wie Fehler aussehen — und wie lange die heutige Fassung gilt.

Modul: APIs als Produkt und Vertrag verstehen

Ressourcen und Seitenaufteilung

Ressourcen sind Substantive, Zustandsübergänge brauchen kein Verb im Pfad:

GET  /abos/{aboId}
GET  /abos/{aboId}/lieferungen
GET  /lieferfenster?woche=2026-W38
POST /bestellungen
GET  /bestellungen/{bestellId}

Was ein eigenes Leben hat, wird eigene Ressource statt Subressource; mehr als zwei, drei Ebenen Verschachtelung macht Adressen unbrauchbar.

MerkmalOffsetCursor
Aufrufseite und groessecursor aus der Antwort
Stabil bei Änderungennein, Einträge springenja
Sprung auf Seite 40möglichnicht vorgesehen
Aufwand in der Datenbankwächst mit dem Offsetbleibt gleich

Offset ist bequem für Oberflächen mit Seitenzahlen, Cursor belastbar für große Datenmengen. Die nächste Seite gehört in eine Link-Relation nach RFC 8288:

Link: </bestellungen?cursor=b4f1>; rel="next",
      </bestellungen>; rel="first"

Die Standardsortierung festlegen — sonst wechselt sie mit dem Ausführungsplan.

Modul: Ressourcen und Endpunkte modellieren

Methoden und Statuscodes

Methodesicheridempotentcachebar
GETjajaja
HEADjajaja
POSTneinneinnur explizit
PUTneinjanein
PATCHneinneinnein
DELETEneinjanein

PATCH steht nicht in RFC 9110, sondern in RFC 5789 — und ist weder sicher noch idempotent. DELETE dagegen muss idempotent sein: Der zweite Aufruf ist kein Fehler.

Die Statuscodes, die im Alltag den Unterschied machen:

CodeBedeutung
201 / 202 / 204angelegt / angenommen, noch nicht erledigt / kein Inhalt
400Syntax kaputt
401 / 403nicht angemeldet / angemeldet und trotzdem nicht erlaubt
409Konflikt mit dem aktuellen Zustand
412 / 428Vorbedingung verletzt / Vorbedingung gefordert
415 / 406gesendeter Rumpf abgelehnt / nichts Passendes lieferbar
422formal korrekt, fachlich unmöglich
429zu viele Anfragen

Lange Vorgänge: 202 bestätigt die Annahme und verweist auf eine Statusressource, 303 See Other führt nach Abschluss auf das Ergebnis.

Modul: HTTP-Semantik korrekt einsetzen

ETags und optimistische Nebenläufigkeit

GET /touren/71 -> 200 OK
ETag: "v7"
PUT /touren/71
If-Match: "v7"     -> 204 No Content
PUT /touren/71
If-Match: "v7"     -> 412 Precondition Failed

Ohne If-Match gewinnt der zweite Schreiber, und die Änderung des ersten verschwindet unbemerkt. Ein starker Validator ändert sich bei jeder Änderung der Repräsentation, ein schwacher darf gleich bleiben, wenn nur Unwesentliches sich ändert: If-Match vergleicht stark, If-None-Match darf schwach vergleichen. Caching regelt RFC 9111, nicht 9110.

Ein ETag aus einem Zeitstempel ist innerhalb einer Sekunde blind; eines über die ganze Collection ändert sich ständig.

Modul: HTTP-Semantik korrekt einsetzen

Fehler nach RFC 9457

ElementInhaltBeständigkeit
typeURI als Kennung des Problemtypsfest, ist der Schlüssel
statusHTTP-Statuscode, nur zur Bequemlichkeitwie die Antwort
titlekurze Zusammenfassung für Menschenändert sich nicht
detailErklärung dieses Vorfallsje Vorfall
instanceURI dieses einen Vorfallsje Vorfall

Consumer unterscheiden Fehler am type, nie am title — der darf übersetzt werden.

{
  "type": "/probleme/kontingent",
  "title": "Das Lieferfenster ist ausgebucht.",
  "status": 409,
  "detail": "Für den 18.09.2026 sind 0 Kisten frei.",
  "instance": "/bestellungen/9f2c",
  "naechstesFenster": "2026-09-25T08:00:00+02:00"
}

Medientyp ist application/problem+json, der type darf eine relative Referenz sein, Erweiterungsfelder sind erlaubt — unbekannte muss ein Consumer ignorieren. Nicht das Richtige sind Problem Details, wenn der Statuscode allein alles sagt oder die Branche ein etabliertes Fehlerformat hat.

Modul: Requests, Responses und Fehler robust gestalten

Repräsentationen

{
  "bestellId": "9f2c",
  "aboId": "a-4471",
  "lieferfenster": "2026-09-18T08:00:00+02:00",
  "kistenGroesse": "mittel",
  "betrag": { "wert": "24.90", "waehrung": "EUR" },
  "status": "bestaetigt"
}

Vier Entscheidungen, die man einmal trifft und überall durchhält: Beträge als Zeichenkette mit Währung, damit die Rundung nicht vom Consumer abhängt; Zeitstempel mit Zone; Aufzählungswerte unübersetzt; und ein optionales Feld entweder immer weg oder immer null — nicht mal so, mal so.

Den Idempotenzschlüssel liefert der Aufrufer, nicht der Server — sonst löst er nichts. Wiederholungen brauchen eine Wartezeit, sonst verstärken sie die Überlast.

Modul: Requests, Responses und Fehler robust gestalten

OWASP API Security Top 10 (2023)

Nr.Risiko
API1Broken Object Level Authorization
API2Broken Authentication
API3Broken Object Property Level Authorization
API4Unrestricted Resource Consumption
API5Broken Function Level Authorization
API6Unrestricted Access to Sensitive Business Flows
API7Server Side Request Forgery
API8Security Misconfiguration
API9Improper Inventory Management
API10Unsafe Consumption of APIs

API9 ist ein Vertragsthema: Nicht dokumentierte Endpunkte werden nicht geprüft und nicht abgeschaltet, alte Versionen laufen weiter, weil niemand ihren Betrieb bemerkt. Der Vertrag ist das Inventar — wenn er vollständig ist.

Berechtigung hat drei Ebenen, und alle drei werden serverseitig geprüft:

EbeneFrage
FunktionDarf diese Rolle diese Operation überhaupt aufrufen?
ObjektGehört dieses konkrete Objekt zu diesem Aufrufer?
EigenschaftDarf dieser Aufrufer genau dieses Feld lesen oder schreiben?

Die Eigenschaftsebene ist die, die am häufigsten fehlt — das Schema muss die erlaubten Felder abschließend nennen, sonst entscheidet der Aufrufer:

POST /bestellungen
{
  "aboId": "a-4471",
  "kistenGroesse": "gross",
  "rabattSatz": 90
}

Modul: API-Sicherheit in Vertrag und Design

Typische Fallen

  • Alles antwortet mit 200 und einem Statusfeld im Rumpf — der Consumer muss dann jede Antwort auspacken, um Erfolg von Fehler zu unterscheiden.
  • 500 für fachliche Ablehnungen. Weckt nachts die Bereitschaft für einen Fall, der genau so vorgesehen war.
  • POST zum Lesen verhindert jede Zwischenspeicherung.
  • Der Server liefert ETags, prüft If-Match aber nie. Sieht korrekt aus und schützt nichts.
  • Antworten pauschal als nicht cachebar markiert, aus Angst vor Zwischenspeichern.
  • Jeder Endpunkt erfindet sein eigenes Fehlerformat — und detail wird zum Feld, das der Consumer parsen muss.
  • Stacktraces in detail verraten Interna nach außen.
  • Die URI trägt die Tabellenstruktur nach außen und friert sie ein.
  • Die Seitengröße ist frei wählbar, und ein Aufruf holt die gesamte Datenbank.
  • Die Objektprüfung fehlt, weil die ID schwer zu erraten scheint.
  • Ein Endpunkt gilt als sicher, weil er im internen Netz liegt.
  • 404 statt 403 gewählt, aber die Antwortzeit verrät die Existenz weiterhin.

Zum Seminar Moderne API-Entwicklung mit REST, OpenAPI und Contract Testing