Skip to main content
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

Erfolgreiche Antworten enthalten nie ein error-Objekt. Verzweige zuerst auf den HTTP-Status, dann auf error.code.

Error-Codes


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.
Wie du damit umgehst. Prüfe den Header Authorization: Bearer samsa_sk_…. Wenn der Key widerrufen oder abgelaufen wurde, erstelle einen neuen. Wiederhole nicht — das Ergebnis wird sich nicht ändern.

missing_scope

HTTP 403. Der Key ist gültig, aber ihm fehlt der Scope, den der Endpoint erfordert. param ist "scope" und die Message nennt den fehlenden 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. Hat die Organisation mindestens ein aktives Team, gibt die API stattdessen die team-bezogenen Codes insufficient_team_credits oder insufficient_unallocated_credits zurück — mit zwei Ausnahmen. Eine vom Team-Budgeting ausgenommene System-Organisation bleibt auch mit aktiven Teams im org-Regime und behält diesen generischen Code. Und ein operativer Fehler in der Abbuchung selbst (etwa eine gestörte Saldo-Abfrage) fällt unabhängig vom Budget-Regime auf diesen generischen Code zurück. Ein schlichtes insufficient_credits in einem Team-Setup kann also vorübergehend sein; versuche es erneut, bevor du es als erschöpften Stand behandelst.
Wie du damit umgehst. Zeigt ein anschließendes GET /credits ein available, das die Kosten abdeckt, hast du möglicherweise den operativen Fallback getroffen — wiederhole einmal. Dieser Read ist allerdings eine Momentaufnahme: auch eine Zustandsänderung seit der Ablehnung (ein Top-up, eine Erstattung, ein geändertes Budget oder ein Periodenwechsel) kann das erklären, ein echter Engpass ist also nicht ausgeschlossen. Andernfalls 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.
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 der Stand, den der Key ausgeben kann — der kleinere Wert aus dem verbleibenden Plan-Pool der Organisation und dem verbleibenden Team-Budget, plus Top-ups —, unter den Kosten der Aktion liegt. Genau das ist das available, das GET /credits meldet.
Der Code nennt das Budget-Regime, nicht den erschöpften Stand. Ein Key, der einem Team mit Budget zugewiesen ist, erhält diesen Code auch dann, wenn der Plan-Pool der Organisation und nicht das Team-Budget aufgebraucht war — das Team kann also noch Spielraum ausweisen. Vergleiche plan_credits mit scope.remaining unter GET /credits, um zu sehen, was begrenzt.
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 der Stand, den der Key ausgeben kann — der kleinere Wert aus dem verbleibenden Plan-Pool der Organisation und dem Spielraum dieses nicht zugewiesenen Pools, plus der von Budgets ausgenommenen Top-ups —, unter den Kosten der Aktion liegt; derselbe Vorbehalt dazu, welcher Stand erschöpft war, gilt wie oben. Organisationen ohne aktives Team sehen die beiden team-bezogenen Codes nie — sie erhalten stattdessen das einfache insufficient_credits.
So siehst du es kommen. GET /credits meldet available — was der aufrufende Key gerade ausgeben kann — und einen scope-Block, der sein Budget-Regime nennt. Ein Job, dessen estimated_credits in available passen, wird mit keinem dieser drei Codes abgelehnt, solange sich der Credit- und Budget-/Team-Zustand zwischendurch nicht ändert — abgesehen vom operativen Fallback: eine gestörte Abbuchung kann auch dann das generische insufficient_credits liefern, also wiederhole zuerst.
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.
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.
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.

svg_acceptance_required

HTTP 422. Nur POST /images/vectorizations liefert diesen Code. SVG ist ein dokumentierter EU-AI-Act-Art.-50(2)-Scope-out: Ein SVG kann kein C2PA-Manifest und kein eingebettetes Wasserzeichen tragen, deshalb werden Vektorausgaben unsigniert ausgeliefert. svg_acceptance muss daher der literale Boolean true sein — ein fehlender, false oder anderer Wert wird mit diesem eigenen Code abgelehnt, nie mit dem generischen validation_error. Die Zustimmung ist Offenlegung / Audit-Nachweis, kein Compliance-Verzicht. Es wird nichts berechnet und kein Job erstellt.
Wie du damit umgehst. Sende die Anfrage erneut mit "svg_acceptance": true, sobald deine Integration den Hinweis auf die unsignierte Ausgabe denjenigen anzeigt, die mit dem Ergebnis arbeiten.

svg_phase1_scope_out_required

HTTP 403. Ebenfalls nur für die Vektorisierung und verschieden von missing_scope — mit dem Scope des Keys ist alles in Ordnung. Die Auslieferung erfordert zusätzlich eine aktuelle, serverseitig verifizierte ToS/AUP-Zustimmung; das Request-Flag svg_acceptance wird nie als dieser Fakt gewertet. Beim Absenden wird eine fehlende oder veraltete Zustimmung abgelehnt, bevor etwas berechnet wird. Die Prüfung läuft bei der Auslieferung erneut: Ein bereits angenommener Job kann also von GET /images/vectorizations/{id} oder bei der Webhook-Auslieferung noch abgelehnt werden, wenn die Zustimmung zwischenzeitlich abläuft — eine Ablehnung bei der Auslieferung kostet nichts zusätzlich, erstattet aber auch nicht die Credits, die der abgeschlossene Job bereits verbraucht hat.
Wie du damit umgehst. Akzeptiere die aktuellen ToS/AUP in der Samsa-App und versuch es erneut. Bei einem Job, der erst bei der Auslieferung abgelehnt wurde, frag seinen GET-Status neu ab — der Webhook wird nicht automatisch erneut gesendet. Das Akzeptieren ist Offenlegung, kein Verzicht.

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.
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.
Wie du damit umgehst. Warte, bis laufende Jobs einen terminalen Status erreichen (frage ihren GET-Endpoint ab oder nutze einen Webhook), 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.
Wie du damit umgehst. Wiederhole mit Backoff — 500er sind oft transient. Wenn es anhält, kontaktiere 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 kontaktierst — das ist der schnellste Weg für uns, genau herauszufinden, was passiert ist.
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.