Hoppa till innehållet
Sursa Developers

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ältBetydelse
error.codeStabil kod i formen <area>.<reason>. Låt din kod förgrena sig på den.
error.messageEn läsbar förklaring på engelska. Den kan omformuleras när som helst; tolka den inte.
error.detailsStrukturerade 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_idId:t för det här anropet, detsamma som i svarshuvudet X-Request-Id.
error.doc_urlSidan om den här koden i portalen.
detailFelets 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

StatusBetydelse
200, 201, 202, 204Anropet lyckades. 202 betyder att det har tagits emot och fortfarande bearbetas.
400Anropet är felformat: en felaktig parameter, markör, metadata eller Idempotency-Key. Rätta anropet.
401Ingen giltig nyckel. Se Autentisering.
402En gräns i organisationens prisplan har nåtts, till exempel antalet kort eller lagringsutrymmet.
403Nyckeln är giltig men får inte göra det här: en roll, ett omfång eller en funktion i prisplanen saknas.
404Objektet finns inte, eller nyckeln får inte se det.
409Anropet 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.
410Objektet har gått ut, till exempel en uppladdning efter 24 timmar, eller vägen har tagits ur bruk.
413Brödtexten eller filen är för stor.
415Filtypen stöds inte, eller dess innehåll stämmer inte med namnet.
422Anropet är korrekt formaterat men ogiltigt: ett fält saknas eller ett värde ligger utanför intervallet.
429För många anrop eller en förbrukad kvot. Se Hastighetsbegränsningar och kvoter.
500, 502, 503, 504Ett 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

FelFörsöka igen?
Nätverksfel eller tidsgräns, inget svarJa, med samma Idempotency-Key.
429Ja, efter det antal sekunder som anges i Retry-After.
500, 502, 503, 504Ja, med exponentiell backoff: 1 s, 2 s, 4 s… upp till en minut, med jitter (slumpmässig variation).
409 api.idempotency_in_progressJa, efter Retry-After: det första anropet med den här nyckeln körs fortfarande.
Alla andra 4xxNej. 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.