Fehler + Rate-Limits
Ein Fehler-Envelope über jeden Endpoint hinweg. Standard-HTTP-Statuscodes + ein strukturierter code-String für programmatisches Matching. Rate-Limit-Header auf jeder Response, damit Sie sich einteilen können, bevor Sie auf einen 429 treffen.
Fehler-Envelope
{
"detail": "Human-readable summary.",
"code": "billing.subscription_past_due",
"field_errors": {
"scheduled_for": ["Must be a future ISO 8601 timestamp."]
}
} detail— immer vorhanden, sicher für Menschen anzuzeigen (es ist übersetzt, wo die Locale verfügbar ist).code— vorhanden bei unterscheidbaren Fehlerzuständen. Stabil über API-Versionen; matchen Sie darauf für die Retry-Logik.field_errors— nur bei 400-Validierungsfehlern vorhanden. Map von Feldname → Liste von Meldungen.
Statuscode-Matrix
| Status | Klasse | Retry? | Häufige Ursachen |
|---|---|---|---|
| 400 | Validierung | Nein | Fehlendes Pflichtfeld, falsches Format, Geschäftsregel-Verletzung |
| 401 | Auth | Nein | Fehlendes / falsches / widerrufenes Credential |
| 402 | Abrechnung | Nein | Abonnement überfällig, Free-Plan-Limit erreicht |
| 403 | Berechtigung | Nein | Dem Credential fehlt der Scope, oder die Ressource ist in einer anderen Org |
| 404 | Nicht gefunden | Nein | Ressource existiert nicht oder ist für Ihr Credential nicht sichtbar |
| 409 | Konflikt | Manchmal | Idempotency-Key-Wiederverwendung passt nicht, State-Machine-Verletzung |
| 422 | Unverarbeitbar | Nein | Semantisch ungültige Kombination gültiger Felder |
| 429 | Rate-limitiert | Ja, mit Backoff | Per-Credential- oder Per-Org-Throttle erreicht |
| 500 | Serverfehler | Ja, mit Backoff | Unerwartet — öffnen Sie ein Ticket, falls es anhält |
| 502 / 503 / 504 | Transient | Ja, mit Backoff | Upstream / Deploy / Last |
Bemerkenswerte Fehlercodes
| Code | Status | Was es bedeutet |
|---|---|---|
billing.subscription_past_due | 402 | Das Stripe-Abonnement der Org ist überfällig. Leiten Sie den Admin zu /admin/billing. |
billing.free_plan_minutes_exhausted | 402 | Die Free- / Pilot-Stufe hat ihre 5 Inspektionen aufgebraucht. |
billing.signature_pack_exhausted | 402 | Signatur-Paket-Guthaben aufgebraucht; Pay-per-Sig oder ein weiteres Paket kaufen. |
permission_denied | 403 | Dem Credential fehlt der Scope. Siehe field_errors.required_scope. |
idempotency.key_mismatch | 409 | Gleicher Key, anderer Body. Nutzen Sie einen frischen Key. |
session.already_ended | 409 | Aufruf von end auf einer nicht-offenen Sitzung (meist unbedenklich — end ist idempotent, dies ist für die Randfälle). |
kyb.not_verified | 403 | QES-Signatur auf einer Org angefordert, die KYB nicht bestanden hat. |
rate_limited | 429 | Per-Credential- (60 rpm) oder Per-Org- (600 rpm) Throttle erreicht. |
Rate-Limit-Header
Jede Response — Erfolg oder Fehler — trägt den Throttle-Zustand:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1716461235 X-RateLimit-Limit— das Limit, das für diesen Request gilt.X-RateLimit-Remaining— wie viele Calls im aktuellen Fenster verbleiben.X-RateLimit-Reset— Unix-Zeitstempel, zu demRemainingzurückgesetzt wird.
Bei einem 429 wird zusätzlich Retry-After gesetzt (in Sekunden) gemäß RFC 6585.
Throttle-Scopes
| Scope | Limit | Fenster |
|---|---|---|
| Pro Credential | 60 | 1 Minute |
| Pro Org (über alle Credentials) | 600 | 1 Minute |
Burstable für die erste Sekunde einer Minute. Erreichen Sie das Limit, geben weitere Requests innerhalb des Fensters 429 zurück.
Retry-Strategie
Exponentielles Backoff mit Jitter für 429 / 5xx; wiederholen Sie 4xx nicht (außer 408, 425, 429):
async function withRetry<T>(fn: () => Promise<T>, max = 5): Promise<T> {
let lastErr: unknown;
for (let i = 0; i < max; i++) {
try {
return await fn();
} catch (err: any) {
const status = err?.status;
if (status >= 400 && status < 500 && ![408, 425, 429].includes(status)) {
throw err; // not retryable
}
const base = status === 429 ? (err.retryAfterMs ?? 1000) : 250 * 2 ** i;
const jitter = Math.random() * base * 0.2;
await new Promise((r) => setTimeout(r, base + jitter));
lastErr = err;
}
}
throw lastErr;
} Die SDKs implementieren dies intern bei 429 + 5xx; wenn Sie Retries lieber selbst behandeln, setzen Sie retries: 0 in den SDK-Optionen.
Fehler-Korrelation
Jede Response trägt einen X-Request-Id-Header (UUID). Nennen Sie diesen in jedem Support-Ticket — wir können allein aus dieser ID den vollständigen Request-Trace ziehen.
Was als Nächstes kommt
- Authentifizierung — Credential-Rotation, falls Sie 401er sehen
- Paginierung + Idempotenz — die Muster, die mit Retries interagieren