Fel
Sursa använder HTTP-statuskoder för att säga om ett anrop lyckades och en stabil felkod för att säga varför det inte gjorde det. Varje felsvar har samma 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"
}
}
| Fält | Betydelse |
|---|---|
error.code | Stabil kod i formen <area>.<reason>. Låt din kod förgrena sig på den. |
error.message | En läsbar förklaring på engelska. Den kan omformuleras när som helst; tolka den inte. |
error.details | Strukturerade fakta om felet, till exempel parametern, en gräns eller när du ska försöka igen. Fälten beror på koden. |
error.request_id | Id:t för det här anropet, detsamma som i svarshuvudet X-Request-Id. |
error.doc_url | Sidan om den här koden i portalen. |
detail | Felets tidigare form, som finns kvar för befintliga integrationer. Ny kod bör läsa error. |
Varje kod har en egen sida under Felkoder, med dess HTTP-status, fälten i details och de slutpunkter som
returnerar den. Sidan för varje slutpunkt i API-referensen listar de koder som slutpunkten kan
returnera.
HTTP-statusar
| Status | Betydelse |
|---|---|
200, 201, 202, 204 | Anropet lyckades. 202 betyder att det har tagits emot och fortfarande bearbetas. |
400 | Anropet är felformat: en felaktig parameter, markör, metadata eller Idempotency-Key. Rätta anropet. |
401 | Ingen giltig nyckel. Se Autentisering. |
402 | En gräns i organisationens prisplan har nåtts, till exempel antalet kort eller lagringsutrymmet. |
403 | Nyckeln är giltig men får inte göra det här: en roll, ett omfång eller en funktion i prisplanen saknas. |
404 | Objektet finns inte, eller nyckeln får inte se det. |
409 | Anropet står i konflikt med det aktuella tillståndet: ett external_id som redan finns, en öppen synkning, ett anrop med samma Idempotency-Key som fortfarande körs. |
410 | Objektet har gått ut, till exempel en uppladdning efter 24 timmar, eller vägen har tagits ur bruk. |
413 | Brödtexten eller filen är för stor. |
415 | Filtypen stöds inte, eller dess innehåll stämmer inte med namnet. |
422 | Anropet är korrekt formaterat men ogiltigt: ett fält saknas eller ett värde ligger utanför intervallet. |
429 | För många anrop eller en förbrukad kvot. Se Hastighetsbegränsningar och kvoter. |
500, 502, 503, 504 | Ett problem hos Sursa. Försök igen senare. |
Valideringsfel
Vid 422 med koden validation.failed listar detail varje fält som inte godkändes,
vart och ett med sin plats:
{
"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…"}
}
Vilka fel du ska försöka igen vid
| Fel | Försöka igen? |
|---|---|
| Nätverksfel eller tidsgräns, inget svar | Ja, med samma Idempotency-Key. |
429 | Ja, efter det antal sekunder som anges i Retry-After. |
500, 502, 503, 504 | Ja, med exponentiell backoff: 1 s, 2 s, 4 s… upp till en minut, med jitter (slumpmässig variation). |
409 api.idempotency_in_progress | Ja, efter Retry-After: det första anropet med den här nyckeln körs fortfarande. |
Alla andra 4xx | Nej. Samma anrop misslyckas igen; rätta det först. |
Gör bara nya försök med POST- och PATCH-anrop när de har en Idempotency-Key, så
att ett nytt försök efter ett förlorat svar inte kan skapa ett andra objekt. GET, PUT och DELETE är säkra att
försöka igen som de är.
// 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." }),
}),
);Rapportera ett problem
Varje svar, lyckat eller inte, har huvudet X-Request-Id, och varje fel har samma värde i error.request_id. Logga
det tillsammans med din egen post om anropet. När du kontaktar supporten om ett anrop skickar du dess anrops-id: det
leder direkt till posten om det anropet.
Hantera koder som du inte känner till
Nya felkoder kan tillkomma i vilken version av API:et som helst. Behandla en okänd kod utifrån dess HTTP-status: en
okänd 4xx som ett anrop som inte kommer att lyckas som det är, en okänd 5xx som ett tillfälligt problem.