Die teuersten API-Fehler sind nicht die, die sofort crashen — es sind die, die zwei Jahre lang funktionieren und dann jede Änderung zur Operation am offenen Herzen machen. Eine API ist ein Versprechen an alle, die sie nutzen, und Versprechen lassen sich schwer zurücknehmen.
Ich habe in Kundenprojekten und eigenen Produkten beide Seiten erlebt: APIs entworfen, die ich später verfluchen durfte, und fremde APIs geerbt, deren Design-Entscheidungen mich Wochen gekostet haben. Hier sind die Fehler, die sich in der Wartung am bittersten rächen — und was du stattdessen machst.
Fehler 1: Keine Versionierungs-Strategie, weil “brauchen wir noch nicht”
Der Klassiker: Die API startet ohne Versionskonzept, weil es ja nur einen Client gibt — das eigene Frontend. Zwei Jahre später gibt es eine Mobile App, zwei Integrationspartner und ein Zapier-Setup eines wichtigen Kunden. Jetzt willst du ein Feld umbenennen und stellst fest: Du weißt nicht einmal, wer deine API alles nutzt.
Der Punkt ist nicht, dass du ab Tag eins /v1/ in die URL schreiben musst — obwohl das billig ist und nichts kostet. Der Punkt ist, dass du eine Antwort auf die Frage brauchst: “Wie ändere ich etwas, ohne bestehende Clients zu brechen?” Meine pragmatische Regel für kleine Teams:
- Additive Änderungen sind immer okay: neue Felder, neue Endpoints, neue optionale Parameter. Clients müssen so gebaut sein, dass sie unbekannte Felder ignorieren.
- Entfernen und Umbenennen ist ein Breaking Change — und passiert nur mit neuem Versionspfad oder mit dokumentierter Deprecation-Frist.
- Logge, welche Clients welche Endpoints nutzen (User-Agent, API-Key). Sonst diskutierst du Breaking Changes im Blindflug.
Fehler 2: Pagination “später nachrüsten”
GET /orders liefert alle Bestellungen. Bei 200 Datensätzen im ersten Jahr kein Problem. Bei 80.000 im dritten Jahr ist es ein Timeout — und jetzt kommt der bittere Teil: Pagination nachträglich einzuführen ist ein Breaking Change. Jeder Client, der bisher das komplette Array bekam, muss umgebaut werden. Aus einer Zehn-Minuten-Entscheidung am Anfang wird ein koordiniertes Migrations-Projekt.
Deshalb: Jeder Endpoint, der eine Liste zurückgibt, ist von Anfang an paginiert. Ohne Ausnahme, auch wenn die Tabelle heute zwölf Zeilen hat. Und wenn du schon dabei bist: Nimm Cursor-basierte Pagination statt offset/limit, wenn die Daten sich häufig ändern — Offset-Pagination überspringt oder dupliziert Einträge, sobald während des Blätterns Datensätze eingefügt werden. Für Admin-UIs mit Seitenzahlen ist Offset okay; für Feeds und Sync-Szenarien ist Cursor die robustere Wahl.
Wichtig ist auch das Antwortformat: Pack die Liste in ein Objekt ({ "data": [...], "nextCursor": "..." }) statt ein nacktes Array zurückzugeben. Ein nacktes Top-Level-Array kannst du nie wieder um Metadaten erweitern, ohne alles zu brechen.
Fehler 3: Fehlerformate nach Tageslaune
In gewachsenen APIs findest du oft drei Generationen von Fehler-Antworten: mal { "error": "..." }, mal { "message": "...", "code": 42 }, mal ein HTML-Fehler vom Proxy, den niemand abgefangen hat. Jeder Client baut sich daraus sein eigenes fragiles Parsing, und jede Fehlerbehandlung ist ein Ratespiel.
Leg vor dem ersten Endpoint ein einheitliches Fehlerformat fest und erzwinge es zentral über einen Error-Handler-Middleware — nicht per Konvention und Hoffnung. Sinnvoller Standard: ein maschinenlesbarer, stabiler code (z. B. validation_failed, insufficient_balance), eine menschenlesbare message und optional ein details-Objekt für Feld-Fehler. Wer sich an einem Standard orientieren will: RFC 9457 (Problem Details) ist genau dafür da.
Und nutze HTTP-Statuscodes ehrlich. Eine API, die bei jedem Fehler 200 OK mit { "success": false } liefert, sabotiert Monitoring, Caching, Retry-Logik und jedes Standard-Tooling gleichzeitig.
Fehler 4: Interne Datenmodelle 1:1 nach außen kippen
Der bequemste Weg zum Endpoint: ORM-Objekt serialisieren, zurückgeben, fertig. Damit ist dein Datenbankschema ab sofort öffentliche Schnittstelle. Jede Spalten-Umbenennung, jede Normalisierung, jeder Refactor schlägt direkt auf alle Clients durch — und du wirst Refactorings unterlassen, weil sie plötzlich Breaking Changes sind. Das interne Modell erstarrt, weil das externe nicht angefasst werden kann.
Die Lösung ist eine dünne, bewusste Mapping-Schicht: DTOs, Serializer, Response-Schemas — der Name ist egal. Entscheidend ist, dass jedes Feld in der API-Antwort eine bewusste Entscheidung war und nicht ein Nebeneffekt des Datenbankdesigns. Nebenbei verhinderst du damit die peinlichen Unfälle, bei denen password_hash oder interne Flags in der JSON-Antwort auftauchen.
Fehler 5: Nicht-idempotente Endpoints für kritische Aktionen
Netzwerke sind unzuverlässig. Wenn ein Client ein POST /payments abschickt und ein Timeout bekommt, weiß er nicht: Ist die Zahlung durchgegangen oder nicht? Er wird es erneut versuchen — und ohne Idempotenz-Konzept hast du jetzt eine Doppelbuchung. Das ist kein theoretisches Szenario; genau so entstehen die Support-Tickets, die richtig weh tun.
Für alles mit Geld oder unumkehrbaren Folgen: Idempotency-Keys. Der Client schickt einen eindeutigen Key mit, der Server speichert das Ergebnis und liefert bei Wiederholung dieselbe Antwort statt einer zweiten Ausführung. Stripe hat dieses Muster populär gemacht, und es kostet dich einen Nachmittag Implementierung — verglichen mit Wochen an Kulanz-Erstattungen ein Geschenk.
Fehler 6: Dokumentation als Nachgedanke
Eine API ohne Doku ist Wartungslast in Wartestellung: Jede Frage landet bei dir persönlich. Die gute Nachricht: Du musst keine Prosa schreiben. Ein gepflegtes OpenAPI-Schema — idealerweise aus dem Code generiert oder als Quelle der Wahrheit für Validierung genutzt — liefert Doku, Client-Generierung und Contract-Tests in einem. Wichtig ist nur, dass Schema und Realität nicht auseinanderlaufen; ein Schema, das lügt, ist schlimmer als keins.
Was davon brauchst du wirklich ab Tag eins?
Ehrliche Einordnung, damit das nicht in Overengineering kippt: Pagination, einheitliches Fehlerformat und die Mapping-Schicht kosten fast nichts, wenn du sie von Anfang an machst — die sind Pflicht. Idempotenz brauchst du erst, wenn Geld oder kritische Aktionen im Spiel sind. Ausgefeilte Versionierungs-Infrastruktur brauchst du erst mit externen Clients; bis dahin reicht die Disziplin, nur additiv zu ändern. Der gemeinsame Nenner aller Punkte: Denk bei jeder Design-Entscheidung an die Person, die in zwei Jahren etwas ändern muss. Meistens bist du das selbst.
Wenn du deine API-Design-Entscheidungen mal gegenchecken willst: Im Discord der Community zerlegen wir sowas gern gemeinsam — ehrliches Feedback inklusive.