# Fehler-Codes

<Lead>
Fehler der Plattform-API sind maschinenlesbar: ein stabiler `code` für deine Fehlerbehandlung, eine `message` für Menschen. Diese Seite beschreibt die Envelope und die Status-Codes, auf die sich Integrationen einstellen sollten.
</Lead>

<BetaNotice>
Das hier beschriebene Format ist der Planungsstand für die öffentliche REST-API. Webhook-Zustellungen (heute produktiv) haben kein Fehler-Envelope: Dort zählt allein der HTTP-Status deiner Antwort, siehe [Webhooks](/api/webhooks).
</BetaNotice>

## Fehler-Envelope

Jede Fehlerantwort trägt denselben JSON-Aufbau:

<ResponseExample status={400} contentType="application/json">
{`{
  "error": {
    "code": "validation_failed",
    "message": "The request body is invalid.",
    "details": [
      { "path": "email", "message": "Invalid email address." }
    ]
  }
}`}
</ResponseExample>

- `code` ist stabil und für programmatische Auswertung gedacht. Verlasse dich auf `code`, nie auf den Wortlaut von `message`.
- `details` ist optional und enthält bei Validierungsfehlern die betroffenen Felder.

## HTTP-Status-Codes

| Status | Code (typisch) | Bedeutung | Wiederholen? |
|---|---|---|---|
| 400 | `validation_failed` | Anfrage fehlerhaft (Body, Parameter) | Nein, erst korrigieren |
| 401 | `unauthorized` | Kein oder ungültiger API-Key | Nein |
| 403 | `forbidden` | Key gültig, Aktion nicht erlaubt (Scope/Rechte) | Nein |
| 404 | `not_found` | Ressource existiert nicht oder gehört einem anderen Workspace | Nein |
| 409 | `conflict` | Zustand kollidiert (z.B. doppelter eindeutiger Wert) | Nach Prüfung |
| 429 | `rate_limited` | Zu viele Anfragen | Ja, nach `Retry-After` |
| 500 | `internal_error` | Unerwarteter Fehler auf Plattform-Seite | Ja, mit Backoff |
| 503 | `unavailable` | Vorübergehend nicht verfügbar (Wartung, Überlast) | Ja, mit Backoff |

<Info title="404 statt 403 bei fremden Daten">
Ressourcen anderer Workspaces beantworten wir mit 404, nicht mit 403. So lässt sich nicht per API erraten, welche IDs existieren.
</Info>

## Umgang mit Fehlern

<Checklist>
  <ChecklistItem>Auf `code` verzweigen, `message` nur loggen oder anzeigen.</ChecklistItem>
  <ChecklistItem>5xx und 429 mit exponentiellem Backoff wiederholen, 4xx (außer 429) nicht.</ChecklistItem>
  <ChecklistItem>Schreiboperationen idempotent gestalten, damit ein wiederholter Request nach Timeout keine Duplikate erzeugt.</ChecklistItem>
  <ChecklistItem>Bei anhaltenden 5xx die Status-Seite prüfen (status.reosa.de), bevor du eskalierst.</ChecklistItem>
</Checklist>
