Fouten + rate limits
Eén error-envelope over elk endpoint. Standaard HTTP-statuscodes + een gestructureerde code-string voor programmatische matching. Rate-limit-headers op elke response zodat u uw tempo kunt bepalen voordat u een 429 raakt.
Error-envelope
{
"detail": "Human-readable summary.",
"code": "billing.subscription_past_due",
"field_errors": {
"scheduled_for": ["Must be a future ISO 8601 timestamp."]
}
} detail— altijd aanwezig, veilig om aan mensen te tonen (wordt vertaald waar de locale beschikbaar is).code— aanwezig voor onderscheidbare foutstatussen. Stabiel over API-versies; match hierop voor retry-logica.field_errors— alleen aanwezig bij 400-validatiefouten. Map van veldnaam → lijst met berichten.
Statuscode-matrix
| Status | Klasse | Opnieuw proberen? | Veelvoorkomende oorzaken |
|---|---|---|---|
| 400 | Validatie | Nee | Ontbrekend verplicht veld, verkeerd formaat, schending van bedrijfsregel |
| 401 | Auth | Nee | Ontbrekende / foute / ingetrokken credential |
| 402 | Facturering | Nee | Abonnement achterstallig, gratis-planlimiet bereikt |
| 403 | Rechten | Nee | Credential mist scope, of resource zit in een andere org |
| 404 | Niet gevonden | Nee | Resource bestaat niet, of is niet zichtbaar voor uw credential |
| 409 | Conflict | Soms | Idempotency-Key-hergebruik komt niet overeen, schending van state machine |
| 422 | Onverwerkbaar | Nee | Semantisch ongeldige combinatie van geldige velden |
| 429 | Snelheidslimiet | Ja, met backoff | Per-credential- of per-org-throttle bereikt |
| 500 | Serverfout | Ja, met backoff | Onverwacht — open een ticket als het aanhoudt |
| 502 / 503 / 504 | Tijdelijk | Ja, met backoff | Upstream / deploy / belasting |
Opvallende foutcodes
| Code | Status | Wat het betekent |
|---|---|---|
billing.subscription_past_due | 402 | Stripe-abonnement van de org is achterstallig. Verwijs de beheerder naar /admin/billing. |
billing.free_plan_minutes_exhausted | 402 | Gratis / Pilot-niveau heeft zijn 5 inspecties gebruikt. |
billing.signature_pack_exhausted | 402 | Handtekeningpakket-credits opgebruikt; pay-per-sig of koop een nieuw pakket. |
permission_denied | 403 | Credential mist de scope. Zie field_errors.required_scope. |
idempotency.key_mismatch | 409 | Dezelfde sleutel, andere body. Gebruik een nieuwe sleutel. |
session.already_ended | 409 | end aanroepen op een niet-open sessie (meestal veilig — end is idempotent, dit is voor de randgevallen). |
kyb.not_verified | 403 | QES-handtekening aangevraagd op een org die KYB niet heeft doorlopen. |
rate_limited | 429 | Per-credential- (60 rpm) of per-org- (600 rpm) throttle bereikt. |
Rate-limit-headers
Elke response — succes of fout — draagt de throttle-status:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1716461235 X-RateLimit-Limit— de limiet die op dit verzoek van toepassing is.X-RateLimit-Remaining— hoeveel calls resteren in het huidige venster.X-RateLimit-Reset— Unix-timestamp waaropRemainingreset.
Bij een 429 wordt ook Retry-After gezet (in seconden) volgens RFC 6585.
Throttle-scopes
| Scope | Limiet | Venster |
|---|---|---|
| Per credential | 60 | 1 minuut |
| Per org (over alle credentials) | 600 | 1 minuut |
Burstbaar in de eerste seconde van een minuut. Bereik de limiet en verdere verzoeken binnen het venster geven 429.
Retry-strategie
Exponentiële backoff met jitter voor 429 / 5xx; retry geen 4xx (behalve 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;
} De SDK's implementeren dit intern bij 429 + 5xx; wilt u retries liever zelf afhandelen, zet dan retries: 0 in de SDK-opties.
Foutcorrelatie
Elke response draagt een X-Request-Id-header (UUID). Vermeld deze in elk supportticket — we kunnen alleen op basis van dat id de volledige request-trace ophalen.
Wat nu
- Authenticatie — credential-rotatie als u 401's ziet
- Paginering + idempotentie — de patronen die met retries samenwerken