Developers
Åbn Levano

Guide 5 af 9

På denne side

Fejl og rate limits

Alle fejl er JSON og har mindst et message. Nogle har mere.

json
{ "message": "Unauthenticated." }

Statuskoderne

Kode Betyder Hvad du gør
200 OK
401 Nøglen mangler, er ukendt, spærret eller udløbet Stop. Genforsøg hjælper ikke
403 Nøglen mangler et scope, eller abonnementet er udløbet Stop. Se nedenfor
404 Ressourcen findes ikke i din organisation, eller modulet er slået fra Stop. Se nedenfor
409 Kaldet strider mod en tilstand, ikke mod et felt Stop. Ret tilstanden først
422 Ugyldige parametre Ret input
429 For mange kald Vent, og genforsøg efter Retry-After
5xx Fejl hos os Genforsøg med eksponentiel backoff

Kun 429 og 5xx er værd at genforsøge automatisk. Alt andet er en fejl i kaldet, og et blindt genforsøg gør det bare til den samme fejl igen, hurtigere.

403 fortæller hvilket scope der mangler

json
{
  "message": "Insufficient scope.",
  "required_scope": "invoices:read"
}

required_scope er der så din log kan sige "nøglen mangler invoices:read" i stedet for "adgang nægtet". Værdien er altid et navn fra scope-kataloget, aldrig fri tekst.

Den anden 403 er et udløbet abonnement. Den har intet required_scope, men et code:

json
{
  "message": "The organisation has no active subscription.",
  "code": "subscription_inactive"
}

Den rammer kun skrivninger. GET bliver ved med at virke, så en virksomhed altid kan hente sine egne data ud. Se Autentificering og scopes.

404 er også svaret på "findes i en anden organisation"

Det her overrasker de fleste, og det er med vilje.

Slår du et id op der findes, men hører til en anden organisation, får du 404, ikke 403. Der er intet i svaret der skelner de to tilfælde fra hinanden.

Grunden er at 403 ville være en oplysning. "Du må ikke se den her" bekræfter at rækken eksisterer, og med et endpoint der svarer forskelligt på "findes ikke" og "findes, men ikke hos dig" kan man afprøve id'er indtil man har kortlagt en anden organisations sager. Det hedder et enumeration-hul, og den eneste sikre rettelse er at de to tilfælde ser ens ud.

Så i din fejlhåndtering: 404 betyder "ikke her". Læs det ikke som "slettet", og skriv ikke en oprydning der sletter lokale rækker på et enkelt 404.

409 betyder at noget skal gøres først

409 er ikke et ugyldigt felt. Det er et kald der er rigtigt skrevet, men forkert placeret i rækkefølgen, og de svar bærer et stabilt code du kan forgrene på.

json
{
  "message": "A flow that is out for signature cannot be deleted. Cancel it first, which revokes the signers' links, then delete it.",
  "code": "flow_must_be_cancelled_first"
}

To steder giver det i dag:

Kode Sker når Gør
flow_must_be_cancelled_first DELETE på et underskriftsflow der er ude til underskrift Annullér flowet først. Det er annulleringen der spærrer underskrivernes links
flow_must_be_draft Underskriverlisten ændres efter at flowet er sendt Send en påmindelse eller byt en e-mail i stedet, eller annullér og start forfra

Se Underskrifter. En Idempotency-Key genbrugt med en anden body giver også 409, og det er den samme slags fejl: kaldet strider mod noget der allerede er sket.

Et blindt genforsøg hjælper ingen af delene. Ret tilstanden, og kald så igen.

422 samler feltfejlene

json
{
  "message": "The given data was invalid.",
  "errors": {
    "per_page": ["The per page must be an integer."]
  }
}

errors er et objekt med et feltnavn per nøgle og en liste af beskeder. Feltnavnene er dem fra forespørgslen, så du kan sætte dem direkte på din egen formular.

Nogle 422-svar bærer også et code ved siden af errors, når det der er galt er en tilstand frem for et felt. Det gælder hele underskriftsfladen, hvor flow_incomplete, flow_invalid_state og deres søskende fortæller præcis hvad der stod i vejen. Underskrifter har hele listen.

Rate limits

Grænsen tælles pr. nøgle, ikke pr. IP. Standard er 120 kald i minuttet. Flere servere bag samme nøgle deler altså puljen, og to nøgler fra samme maskine gør ikke.

Hvert autentificeret svar bærer status med:

Header Indhold
X-RateLimit-Limit Kald tilladt i vinduet
X-RateLimit-Remaining Kald tilbage i det nuværende vindue
X-RateLimit-Reset Unix-tidsstempel for hvornår vinduet nulstilles

Rammer du loftet, får du 429 og en Retry-After i sekunder.

python
import time, requests

def call(url, headers, attempt=1):
    response = requests.get(url, headers=headers, timeout=30)

    if response.status_code == 429 and attempt <= 5:
        time.sleep(int(response.headers.get("Retry-After", 5)))
        return call(url, headers, attempt + 1)

    response.raise_for_status()
    return response.json()

Læs Retry-After frem for at gætte. Et fast sleep(1) i en løkke er den sikreste måde at holde sig selv i 429 resten af minuttet.

Vil du ikke ramme loftet i første omgang: hent større sider frem for flere. per_page=100 henter det samme som fire kald med per_page=25, for ét kald af budgettet.

Det uautentificerede endpoint /api/v1/openapi.json har sin egen, lavere grænse, fordi den ikke kan tælles pr. nøgle.

Hvad du ikke får i en fejl

Fejl indeholder ikke stack traces, interne id'er eller besked om hvilken organisation en ressource ellers ligger i. Kan du ikke se hvad der gik galt af message alene, så skriv til os med tidspunkt, endpoint og navnet på nøglen. Vi kan slå kaldet op i vores egne logs. Nøglens hemmelighed skal du ikke sende med.

Søg i dokumentationen

Søg på titel eller emne. Brug Tab til at vælge et resultat.