> ## Documentation Index
> Fetch the complete documentation index at: https://docs.samsa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Fehler

> Das Error-Envelope der Samsa API, jeder Error-Code und wie du mit jedem umgehst.

Jeder Fehler, den die Samsa API zurückgibt — für jeden Endpoint, bei jedem Status
— verwendet ein einheitliches JSON-**Envelope**. Parse den maschinenlesbaren
`code`, nicht die menschliche `message` (Messages können sich ändern; Codes sind
stabil).

## Das Error-Envelope

```json theme={null}
{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "The provided API key is invalid, expired, or revoked.",
    "request_id": "req_8f14e45fceea167a"
  }
}
```

| Feld               | Beschreibung                                                                                                                               |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `error.type`       | Grobe Kategorie, z. B. `authentication_error`, `credit_error`, `rate_limit_error`.                                                         |
| `error.code`       | Stabiler, spezifischer Code, auf den du verzweigst (die Tabelle unten).                                                                    |
| `error.message`    | Menschenlesbare Erklärung. Für Anzeige und Logs — nicht parsen.                                                                            |
| `error.request_id` | Korrelations-id für diese Anfrage, auch als `X-Request-ID`-Response-Header zurückgegeben. **Nenne sie, wenn du den Support kontaktierst.** |
| `error.param`      | Bei Validierungs- und Scope-Fehlern vorhanden — nennt das betreffende Feld oder `"scope"`.                                                 |

<Note>
  Erfolgreiche Antworten enthalten nie ein `error`-Objekt. Verzweige zuerst auf den
  HTTP-Status, dann auf `error.code`.
</Note>

## Error-Codes

| HTTP | `code`                             | `type`                  | Bedeutung                                                                                                                                     |
| ---- | ---------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| 401  | `invalid_api_key`                  | `authentication_error`  | Fehlender, fehlerhafter, unbekannter, abgelaufener oder widerrufener Key.                                                                     |
| 403  | `missing_scope`                    | `permission_error`      | Gültiger Key, dem der Scope des Endpoints fehlt.                                                                                              |
| 402  | `insufficient_credits`             | `credit_error`          | Der Credit-Pool der Organisation liegt unter den Kosten der Aktion.                                                                           |
| 402  | `subscription_inactive`            | `credit_error`          | Kein nutzbares Organisations-Abonnement.                                                                                                      |
| 402  | `insufficient_team_credits`        | `credit_error`          | Das verbleibende Monatsbudget des Teams des API-Keys (plus Top-ups) liegt unter den Kosten der Aktion.                                        |
| 402  | `insufficient_unallocated_credits` | `credit_error`          | Der nicht zugewiesene Pool der Organisation (plus Top-ups) liegt unter den Kosten der Aktion — der Key ist keinem Team mit Budget zugewiesen. |
| 404  | `not_found`                        | `invalid_request_error` | Unbekannte id oder eine Ressource, die einer anderen Organisation gehört.                                                                     |
| 422  | `validation_error`                 | `invalid_request_error` | Request-Body oder Parameter haben die Validierung nicht bestanden.                                                                            |
| 429  | `rate_limited`                     | `rate_limit_error`      | Request-Rate-Fenster pro Key überschritten.                                                                                                   |
| 429  | `too_many_active_jobs`             | `rate_limit_error`      | Concurrency-Cap für gleichzeitige Jobs der Organisation erreicht.                                                                             |
| 500  | `internal_error`                   | `api_error`             | Unerwarteter Serverfehler.                                                                                                                    |

***

### `invalid_api_key`

**HTTP 401.** Der `Authorization`-Header fehlt oder ist fehlerhaft, oder der Key
ist unbekannt, abgelaufen oder widerrufen — oder der Key-Ersteller ist kein
Mitglied der Organisation mehr. Abgelaufene und unbekannte Keys sind absichtlich
nicht unterscheidbar.

```json theme={null}
{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "The provided API key is invalid, expired, or revoked.",
    "request_id": "req_8f14e45fceea167a"
  }
}
```

**Wie du damit umgehst.** Prüfe den Header `Authorization: Bearer samsa_sk_…`.
Wenn der Key widerrufen oder abgelaufen wurde,
[erstelle einen neuen](/de/guides/authentication#einen-key-rotieren). Wiederhole
nicht — das Ergebnis wird sich nicht ändern.

### `missing_scope`

**HTTP 403.** Der Key ist gültig, aber ihm fehlt der
[Scope](/de/guides/authentication#scopes), den der Endpoint erfordert. `param` ist
`"scope"` und die Message nennt den fehlenden Scope.

```json theme={null}
{
  "error": {
    "type": "permission_error",
    "code": "missing_scope",
    "message": "The API key is missing the required scope: images.generate.",
    "request_id": "req_1c9a3b7d2e5f4a80",
    "param": "scope"
  }
}
```

**Wie du damit umgehst.** Ein Admin bearbeitet die Scopes des Keys (oder erstellt
einen neuen Key), um den genannten Scope zu gewähren. Wiederhole nicht, ohne den
Key zu ändern.

### `insufficient_credits`

**HTTP 402.** Der ausgebbare Credit-Pool der Organisation (Abonnement plus gültige
Top-ups) liegt unter den Kosten der Aktion. Siehe [Preise](/de/guides/pricing). Hat
die Organisation mindestens ein aktives Team, gibt die API stattdessen die
team-bezogenen Codes [`insufficient_team_credits`](#insufficient_team_credits) oder
[`insufficient_unallocated_credits`](#insufficient_unallocated_credits) zurück.

```json theme={null}
{
  "error": {
    "type": "credit_error",
    "code": "insufficient_credits",
    "message": "Insufficient credits available.",
    "request_id": "req_2d5f4a801c9a3b7d"
  }
}
```

**Wie du damit umgehst.** Lade auf oder upgrade den Plan der Organisation in der
App, dann wiederhole. Es wurde nichts berechnet und kein Job erstellt.

### `subscription_inactive`

**HTTP 402.** Die Organisation hat kein nutzbares Abonnement (keines aktiv, in
Kulanzfrist oder mit ausgebbaren Top-ups). Unterscheidet sich von
`insufficient_credits`, wo ein Abonnement existiert, der Pool aber zu niedrig ist.

```json theme={null}
{
  "error": {
    "type": "credit_error",
    "code": "subscription_inactive",
    "message": "No active subscription for this organization.",
    "request_id": "req_4a801c9a3b7d2d5f"
  }
}
```

**Wie du damit umgehst.** Reaktiviere die Abrechnung für die Organisation in der
App, dann wiederhole.

### `insufficient_team_credits`

**HTTP 402.** Organisationen können ihre monatlichen Abonnement-Credits in
**Budgets** pro Team aufteilen, und jeder API-Key kann einem Team zugewiesen werden.
Ein Key, der einem Team mit Budget zugewiesen ist, gibt aus dem monatlichen Bucket
dieses Teams aus; alles, was keinem Team-Budget zugewiesen ist, bildet den **nicht
zugewiesenen Pool** der Organisation. Gekaufte Top-up-Credits sind von Budgets
ausgenommen und bleiben verfügbar, um den Rest zu decken. Dieser Code tritt auf, wenn das
verbleibende Budget des Teams für die aktuelle Abrechnungsperiode plus Top-ups unter
den Kosten der Aktion liegt.

```json theme={null}
{
  "error": {
    "type": "credit_error",
    "code": "insufficient_team_credits",
    "message": "Insufficient team credits for team Marketing",
    "request_id": "req_6b7d2d5f4a801c9a"
  }
}
```

**Wie du damit umgehst.** Ein Organisations-Admin kann das monatliche Budget des
Teams erhöhen, den Key einem anderen Team zuweisen oder Top-up-Credits kaufen
(Top-ups sind nicht durch Team-Budgets begrenzt). Der Budget-Verbrauch setzt sich
außerdem mit der nächsten Abrechnungsperiode zurück. Es wurde nichts berechnet und kein Job
erstellt.

### `insufficient_unallocated_credits`

**HTTP 402.** Der Key ist keinem Team mit Budget zugewiesen (nicht zugewiesen, oder
sein Team hat kein Budget), daher gibt er aus dem nicht zugewiesenen Pool der
Organisation aus — den monatlichen Abonnement-Credits, die nach Abzug der Budgets
aller aktiven Teams übrig bleiben. Dieser Code tritt auf, wenn dieser Pool plus der von
Budgets ausgenommenen Top-ups unter den Kosten der Aktion liegt. Organisationen ohne
aktives Team sehen die beiden team-bezogenen Codes nie — sie erhalten stattdessen
das einfache [`insufficient_credits`](#insufficient_credits).

```json theme={null}
{
  "error": {
    "type": "credit_error",
    "code": "insufficient_unallocated_credits",
    "message": "Insufficient unallocated organization credits",
    "request_id": "req_0a3b7d2d5f4a801c"
  }
}
```

**Wie du damit umgehst.** Ein Organisations-Admin kann Team-Budgets senken, um nicht
zugewiesene Credits freizugeben, den Key einem Team mit verfügbarem Budget zuweisen,
den Plan upgraden oder Top-up-Credits kaufen. Es wurde nichts berechnet und kein Job
erstellt.

### `not_found`

**HTTP 404.** Die id ist unbekannt oder sie gehört einer anderen Organisation. Die
beiden Fälle sind per Design nicht unterscheidbar, sodass die Existenz nie über
Organisationen hinweg preisgegeben wird.

```json theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "not_found",
    "message": "The requested resource was not found.",
    "request_id": "req_7d2d5f4a801c9a3b"
  }
}
```

**Wie du damit umgehst.** Verifiziere die id und dass die Organisation des Keys die
Ressource besitzt. Wiederhole nicht.

### `validation_error`

**HTTP 422.** Der Request-Body oder ein Parameter hat die Validierung nicht
bestanden. `param` nennt das betreffende Feld; `message` erklärt die Einschränkung.

```json theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "validation_error",
    "message": "aspect_ratio must be one of: 1:1, 1:4, 1:8, 16:9, 2:3, 21:9, 3:2, 3:4, 4:1, 4:3, 4:5, 5:4, 8:1, 9:16.",
    "request_id": "req_3b7d2d5f4a801c9a",
    "param": "aspect_ratio"
  }
}
```

**Wie du damit umgehst.** Behebe die Anfrage gemäß `message` und `param`, dann
reiche sie erneut ein. Das ist ein Client-Fehler — dieselbe Anfrage zu wiederholen
schlägt identisch fehl.

### `rate_limited`

**HTTP 429.** Der Key hat sein Request-Rate-Fenster pro Key überschritten. Die
Antwort trägt die Header `Retry-After` und `X-RateLimit-*`. Siehe
[Rate Limits](/de/guides/rate-limits).

```json theme={null}
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limited",
    "message": "API rate limit exceeded. Slow down and retry after the rate-limit window resets.",
    "request_id": "req_5f4a801c9a3b7d2d"
  }
}
```

**Wie du damit umgehst.** Warte nach dem `Retry-After`-Intervall ab und wiederhole
dann. Verwende exponentielles Backoff bei wiederholten 429ern.

### `too_many_active_jobs`

**HTTP 429.** Die Organisation hat ihren Cap für gleichzeitige laufende Jobs
erreicht. Die Message enthält den aktuellen Stand und das Limit, und ein
`Retry-After`-Header ist gesetzt.

```json theme={null}
{
  "error": {
    "type": "rate_limit_error",
    "code": "too_many_active_jobs",
    "message": "Too many active jobs for this organization (5/5). Wait for in-flight jobs to finish before submitting more.",
    "request_id": "req_801c9a3b7d2d5f4a"
  }
}
```

**Wie du damit umgehst.** Warte, bis laufende Jobs einen terminalen Status
erreichen (frage ihren `GET`-Endpoint ab oder nutze einen
[Webhook](/de/guides/webhooks)), bevor du weitere einreichst, dann wiederhole nach
`Retry-After`.

### `internal_error`

**HTTP 500.** Ein unerwarteter Fehler auf Samsas Seite. Die Antwort verrät nie
interne Details — die `request_id` ist dein Ansatzpunkt für den Support.

```json theme={null}
{
  "error": {
    "type": "api_error",
    "code": "internal_error",
    "message": "An internal error occurred. Contact support with the request_id.",
    "request_id": "req_9a3b7d2d5f4a801c"
  }
}
```

**Wie du damit umgehst.** Wiederhole mit Backoff — 500er sind oft transient. Wenn
es anhält, kontaktiere [support@samsa.ai](mailto:support@samsa.ai) mit der
`request_id`.

## `request_id` für den Support nutzen

Jeder Fehler (und jeder Erfolg) trägt eine `request_id`, auch zurückgegeben als
`X-Request-ID`-Response-Header. Sie verbindet deinen clientseitigen Fehler, den
Response-Header und Samsas Server-Logs zu einer Anfrage. Logge sie und nenne sie,
wenn du [support@samsa.ai](mailto:support@samsa.ai) kontaktierst — das ist der
schnellste Weg für uns, genau herauszufinden, was passiert ist.

<Tip>
  Neue Error-Codes können mit der Zeit hinzukommen (zum Beispiel additive Codes pro
  Endpoint). Behandle einen unbekannten `code` wie seine HTTP-Statusklasse und
  verzweige immer auf `code`, statt den `message`-Text zu matchen.
</Tip>
