Fejl
Sursa bruger HTTP-statuskoder til at angive, om en anmodning lykkedes, og en stabil fejlkode til at angive, hvorfor den ikke gjorde. Alle fejlsvar har samme form:
{
"detail": "the cursor is malformed or was issued for different filters",
"error": {
"code": "api.cursor_invalid",
"message": "the cursor is malformed or was issued for different filters",
"details": {"parameter": "cursor"},
"request_id": "01JB7Q2M4X9V3K8T5N6P0R1S2A",
"doc_url": "https://developers.sursa.com/errors/api.cursor_invalid"
}
}
| Felt | Betydning |
|---|---|
error.code | Stabil kode i formen <area>.<reason>. Lad din kode forgrene sig efter den. |
error.message | En læsbar forklaring på engelsk. Den kan omformuleres når som helst; fortolk den ikke. |
error.details | Strukturerede oplysninger om fejlen, fx parameteren, en grænse eller hvornår du kan forsøge igen. Felterne afhænger af koden. |
error.request_id | Id’et for denne anmodning, det samme som i svarheaderen X-Request-Id. |
error.doc_url | Siden om denne kode på portalen. |
detail | Den tidligere form af fejlen, bevaret for eksisterende integrationer. Ny kode bør læse error. |
Hver kode har sin egen side under Fejlkoder med dens HTTP-status, felterne i details og de operationer, der
returnerer den. Siden for hver operation i API-referencen viser de koder, operationen kan returnere.
HTTP-statusser
| Status | Betydning |
|---|---|
200, 201, 202, 204 | Anmodningen lykkedes. 202 betyder, at den er modtaget og stadig behandles. |
400 | Anmodningen er forkert udformet: en forkert parameter, cursor, metadata eller Idempotency-Key. Ret anmodningen. |
401 | Ingen gyldig nøgle. Se Autentificering. |
402 | En grænse i organisationens prisplan er nået, fx antallet af kort eller lagerpladsen. |
403 | Nøglen er gyldig, men har ikke lov til dette: Der mangler en rolle, et scope eller en funktion i prisplanen. |
404 | Objektet findes ikke, eller nøglen har ikke lov til at se det. |
409 | Anmodningen er i konflikt med den aktuelle tilstand: et external_id, der allerede findes, en åben synkronisering, en anmodning med den samme Idempotency-Key, der stadig kører. |
410 | Objektet er udløbet, fx en upload efter 24 timer, eller ruten er udfaset. |
413 | Brødteksten eller filen er for stor. |
415 | Filtypen understøttes ikke, eller indholdet passer ikke til filnavnet. |
422 | Anmodningen er korrekt udformet, men ugyldig: et manglende felt eller en værdi uden for det tilladte interval. |
429 | For mange anmodninger, eller en kvote er brugt op. Se Hastighedsgrænser og kvoter. |
500, 502, 503, 504 | Et problem hos Sursa. Forsøg igen senere. |
Valideringsfejl
Ved 422 med koden validation.failed viser detail alle felter, der ikke bestod
valideringen, hver med sin placering:
{
"detail": [
{"loc": ["body", "title"], "msg": "String should have at least 1 character", "type": "string_too_short"}
],
"error": {"code": "validation.failed", "message": "request validation failed", "request_id": "01JB7…"}
}
Hvilke fejl du skal forsøge igen
| Fejl | Forsøge igen? |
|---|---|
| Netværksfejl eller timeout, intet svar | Ja, med den samme Idempotency-Key. |
429 | Ja, efter det antal sekunder, der står i Retry-After. |
500, 502, 503, 504 | Ja, med eksponentiel backoff: 1 s, 2 s, 4 s … op til et minut, med tilfældig jitter. |
409 api.idempotency_in_progress | Ja, efter Retry-After: Den første anmodning med denne nøgle kører stadig. |
Enhver anden 4xx | Nej. Den samme anmodning vil mislykkes igen; ret den først. |
Forsøg kun POST- og PATCH-anmodninger igen med en Idempotency-Key, så et nyt forsøg
efter et tabt svar ikke kan oprette et objekt mere. GET, PUT og DELETE kan trygt forsøges igen, som de er.
// Retries a request on network errors, 429 and 5xx. The same Idempotency-Key is sent on every attempt.
async function withRetries(send, attempts = 5) {
for (let attempt = 1; ; attempt++) {
let response;
try {
response = await send();
} catch (error) {
if (attempt >= attempts) throw error;
}
if (response && response.status !== 429 && response.status < 500) return response;
if (attempt >= attempts) return response;
const retryAfter = Number(response?.headers.get("Retry-After"));
const backoff = Math.min(60, 2 ** (attempt - 1)) * (0.8 + Math.random() * 0.4);
await new Promise((resolve) => setTimeout(resolve, 1000 * (retryAfter || backoff)));
}
}
const key = crypto.randomUUID();
const response = await withRetries(() =>
fetch("https://api.sursa.com/v1/cards/text", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SURSA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": key,
},
body: JSON.stringify({ title: "Refund policy", body_markdown: "Refunds take 14 days." }),
}),
);Rapportering af et problem
Hvert svar, vellykket eller ej, har en X-Request-Id-header, og hver fejl har den samme værdi i error.request_id. Log
den sammen med din egen registrering af anmodningen. Når du kontakter support om en anmodning, så send anmodningens id:
Det fører direkte til registreringen af netop den anmodning.
Håndtering af koder, du ikke kender
Nye fejlkoder kan dukke op i enhver version af API’et. Behandl en ukendt kode ud fra dens HTTP-status: en ukendt 4xx
som en anmodning, der ikke vil lykkes, som den er, og en ukendt 5xx som et midlertidigt problem.