LIVE · AUDIT-KJEDE · EU-VERTET
SYSTEM · 99,99 % OPPETID
v 1.0 ↗ LAGET I EU

Feil + hastighetsgrenser

Én feilkonvolutt på tvers av alle endepunkter. Standard HTTP-statuskoder + en strukturert code-streng for programmatisk matching. Hastighetsgrense-hoder på hvert svar, så du kan finne farten din før du treffer en 429.

Feilkonvolutt

{
  "detail": "Human-readable summary.",
  "code": "billing.subscription_past_due",
  "field_errors": {
    "scheduled_for": ["Must be a future ISO 8601 timestamp."]
  }
}
  • detail — alltid til stede, trygg å vise til mennesker (den er oversatt der lokaliteten er tilgjengelig).
  • code — til stede for skillbare feiltilstander. Stabil på tvers av API-versjoner; match på denne for retry-logikk.
  • field_errors — til stede kun ved 400-valideringsfeil. Kart av feltnavn → liste av meldinger.

Statuskodematrise

StatusKlasseRetry?Vanlige årsaker
400ValideringNeiManglende påkrevd felt, feil format, brudd på forretningsregel
401AutentiseringNeiManglende / feil / tilbakekalt legitimasjon
402FaktureringNeiAbonnement forfalt, gratisplanens grense nådd
403TillatelseNeiLegitimasjonen mangler scope, eller ressursen er i en annen organisasjon
404Ikke funnetNeiRessursen finnes ikke, eller er ikke synlig for legitimasjonen din
409KonfliktNoen gangerIdempotency-Key-gjenbruk med avvik, brudd på tilstandsmaskin
422Ikke prosesserbarNeiSemantisk ugyldig kombinasjon av gyldige felt
429HastighetsbegrensetJa, med backoffPer-legitimasjon- eller per-organisasjon-struping nådd
500ServerfeilJa, med backoffUventet — opprett en sak hvis vedvarende
502 / 503 / 504ForbigåendeJa, med backoffOppstrøms / deploy / last

Bemerkelsesverdige feilkoder

CodeStatusHva det betyr
billing.subscription_past_due402Organisasjonens Stripe-abonnement er forfalt. Henvis admin til /admin/billing.
billing.free_plan_minutes_exhausted402Free-/Pilot-nivået har brukt sine 5 inspeksjoner.
billing.signature_pack_exhausted402Signaturpakkens kreditter er brukt opp; betal per signatur eller kjøp en ny pakke.
permission_denied403Legitimasjonen mangler scope. Se field_errors.required_scope.
idempotency.key_mismatch409Samme nøkkel, ulik body. Bruk en ny nøkkel.
session.already_ended409Kaller end på en ikke-åpen økt (vanligvis trygt — end er idempotent, dette er for grensetilfellene).
kyb.not_verified403QES-signatur forespurt på en organisasjon som ikke har klarert KYB.
rate_limited429Per-legitimasjon (60 rpm) eller per-organisasjon (600 rpm) struping nådd.

Hastighetsgrense-hoder

Hvert svar — suksess eller feil — bærer strupetilstanden:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1716461235
  • X-RateLimit-Limit — grensen som gjelder for denne forespørselen.
  • X-RateLimit-Remaining — hvor mange kall som gjenstår i det gjeldende vinduet.
  • X-RateLimit-Reset — Unix-tidsstempel der Remaining nullstilles.

Ved en 429 settes også Retry-After (i sekunder) per RFC 6585.

Strupe-scopes

ScopeGrenseVindu
Per legitimasjon601 minutt
Per organisasjon (på tvers av all legitimasjon)6001 minutt

Kan burste det første sekundet av et minutt. Treff grensen, og videre forespørsler innenfor vinduet gir 429.

Retry-strategi

Eksponentiell backoff med jitter for 429 / 5xx; ikke retry 4xx (annet enn 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-ene implementerer dette internt på 429 + 5xx; hvis du heller vil håndtere retries selv, sett retries: 0 i SDK-alternativene.

Feilkorrelasjon

Hvert svar bærer et X-Request-Id-hode (UUID). Oppgi dette i enhver supportsak — vi kan hente hele forespørselssporet fra denne id-en alene.

Hva er neste steg