Erori + rate limits
Un singur plic de eroare pe toate endpoint-urile. Coduri de status HTTP standard + un string code structurat pentru potrivire programatică. Antete de rate limit pe fiecare răspuns, ca să vă puteți dozat ritmul înainte de a atinge un 429.
Plic de eroare
{
"detail": "Human-readable summary.",
"code": "billing.subscription_past_due",
"field_errors": {
"scheduled_for": ["Must be a future ISO 8601 timestamp."]
}
} detail— mereu prezent, sigur de afișat oamenilor (este tradus acolo unde locale-ul este disponibil).code— prezent pentru stări de eroare distinctibile. Stabil între versiunile API; potriviți pe acesta pentru logica de reîncercare.field_errors— prezent doar la eșecurile de validare 400. Hartă de nume-de-câmp → listă de mesaje.
Matricea codurilor de status
| Status | Clasă | Reîncercare? | Cauze comune |
|---|---|---|---|
| 400 | Validare | Nu | Câmp obligatoriu lipsă, format greșit, încălcare de regulă de business |
| 401 | Autentificare | Nu | Credențială lipsă / greșită / revocată |
| 402 | Facturare | Nu | Abonament restant, limita planului gratuit atinsă |
| 403 | Permisiune | Nu | Credențialei îi lipsește scope-ul, sau resursa este într-o altă organizație |
| 404 | Negăsit | Nu | Resursa nu există sau nu este vizibilă pentru credențialul dvs. |
| 409 | Conflict | Uneori | Reutilizare nepotrivită a Idempotency-Key, încălcare a mașinii de stări |
| 422 | Neprocesabil | Nu | Combinație invalidă semantic de câmpuri valide |
| 429 | Limitat ca rată | Da, cu backoff | Limită per credențial sau per organizație atinsă |
| 500 | Eroare de server | Da, cu backoff | Neașteptat — deschideți un tichet dacă persistă |
| 502 / 503 / 504 | Tranzitoriu | Da, cu backoff | Upstream / implementare / încărcare |
Coduri de eroare notabile
| Cod | Status | Ce înseamnă |
|---|---|---|
billing.subscription_past_due | 402 | Abonamentul Stripe al organizației are plata restantă. Îndrumați administratorul către /admin/billing. |
billing.free_plan_minutes_exhausted | 402 | Nivelul Gratuit / Pilot și-a folosit cele 5 inspecții. |
billing.signature_pack_exhausted | 402 | Creditele pachetului de semnături s-au epuizat; plătiți per semnătură sau cumpărați alt pachet. |
permission_denied | 403 | Credențialul nu are domeniul de acces necesar. Vedeți field_errors.required_scope. |
idempotency.key_mismatch | 409 | Aceeași cheie, corp diferit. Folosiți o cheie nouă. |
session.already_ended | 409 | Apelarea end pe o sesiune care nu este deschisă (de obicei sigur — end este idempotent, aceasta este pentru cazurile-limită). |
kyb.not_verified | 403 | Semnătură QES solicitată pe o organizație care nu a trecut verificarea KYB. |
rate_limited | 429 | Limită per credențial (60 rpm) sau per organizație (600 rpm) atinsă. |
Antete de limitare a ratei
Fiecare răspuns — de succes sau de eroare — poartă starea de limitare:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1716461235 X-RateLimit-Limit— limita care se aplică acestei cereri.X-RateLimit-Remaining— câte apeluri rămân în fereastra curentă.X-RateLimit-Reset— marca temporală Unix la careRemainingse resetează.
La un 429, Retry-After este de asemenea setat (în secunde) conform RFC 6585.
Domenii de limitare
| Domeniu | Limită | Fereastră |
|---|---|---|
| Per credențial | 60 | 1 minut |
| Per organizație (pe toate credențialele) | 600 | 1 minut |
Permite rafale în prima secundă a unui minut. Atingeți limita și cererile ulterioare din fereastră primesc 429.
Strategie de reîncercare
Backoff exponențial cu jitter pentru 429 / 5xx; nu reîncercați 4xx (cu excepția 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;
} SDK-urile implementează acest lucru intern pentru 429 + 5xx; dacă preferați să gestionați reîncercările manual, setați retries: 0 în opțiunile SDK-ului.
Corelarea erorilor
Fiecare răspuns poartă un antet X-Request-Id (UUID). Menționați-l în orice tichet de suport — putem extrage întreaga trasare a cererii doar din acest id.
Ce urmează
- Autentificare — rotația credențialelor dacă întâlniți erori 401
- Paginare + idempotență — tiparele care interacționează cu reîncercările