Pogreške
Sursa koristi HTTP statusne kodove da bi rekla je li zahtjev uspio, a stabilan kod pogreške da bi rekla zašto nije uspio. Svaki odgovor s pogreškom ima isti oblik:
{
"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"
}
}
| Polje | Značenje |
|---|---|
error.code | Stabilan kod u obliku <area>.<reason>. Na njemu granajte svoj kod. |
error.message | Čitljivo objašnjenje na engleskom. Može se u bilo kojem trenutku preformulirati; ne raščlanjujte ga. |
error.details | Strukturirane činjenice o pogrešci, kao što su parametar, ograničenje ili kad ponovno pokušati. Njegova polja ovise o kodu. |
error.request_id | ID ovog zahtjeva, isti kao u zaglavlju odgovora X-Request-Id. |
error.doc_url | Stranica o ovom kodu na ovom portalu. |
detail | Raniji oblik pogreške, zadržan zbog postojećih integracija. Novi kod treba čitati error. |
Svaki kod ima vlastitu stranicu u odjeljku Kodovi pogrešaka, s HTTP statusom, poljima objekta details i
operacijama koje ga vraćaju. Stranica svake operacije u referenci API-ja navodi kodove koje ta
operacija može vratiti.
HTTP statusi
| Status | Značenje |
|---|---|
200, 201, 202, 204 | Zahtjev je uspio. 202 znači da je zahtjev prihvaćen i da se još obrađuje. |
400 | Zahtjev je neispravno oblikovan: pogrešan parametar, kursor, metadata ili Idempotency-Key. Ispravite zahtjev. |
401 | Nema valjanog ključa. V. Autentifikacija. |
402 | Dosegnuto je ograničenje plana organizacije, kao što je broj kartica ili prostor za pohranu. |
403 | Ključ je valjan, ali to ne smije učiniti: nedostaje uloga, opseg ili mogućnost plana. |
404 | Objekt ne postoji ili ga ključ ne smije vidjeti. |
409 | Zahtjev je u sukobu s trenutačnim stanjem: dvostruki external_id, otvorena sinkronizacija, zahtjev s istim Idempotency-Key koji se još izvršava. |
410 | Objekt je istekao, primjerice učitavanje nakon 24 sata, ili je ruta ukinuta. |
413 | Tijelo ili datoteka su preveliki. |
415 | Vrsta datoteke nije podržana ili njezin sadržaj ne odgovara njezinu imenu. |
422 | Zahtjev je ispravno oblikovan, ali nije valjan: nedostaje polje ili je vrijednost izvan raspona. |
429 | Previše zahtjeva ili je kvota potrošena. V. Ograničenja učestalosti i kvote. |
500, 502, 503, 504 | Problem na strani Surse. Pokušajte ponovno kasnije. |
Pogreške provjere valjanosti
Za 422 s kodom validation.failed detail navodi svako polje koje nije prošlo
provjeru, svako s njegovim mjestom:
{
"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…"}
}
Koje pogreške treba ponovno pokušati
| Pogreška | Ponovno pokušati? |
|---|---|
| Mrežna pogreška ili istek vremena, nema odgovora | Da, s istim Idempotency-Key. |
429 | Da, nakon broja sekundi navedenog u Retry-After. |
500, 502, 503, 504 | Da, s eksponencijalno rastućom stankom: 1 s, 2 s, 4 s… do jedne minute, uz nasumično odstupanje (jitter). |
409 api.idempotency_in_progress | Da, nakon Retry-After: prvi zahtjev s ovim ključem još se izvršava. |
Bilo koji drugi 4xx | Ne. Isti zahtjev ponovno neće uspjeti; najprije ga ispravite. |
Zahtjeve POST i PATCH ponovno pokušavajte samo s Idempotency-Key, kako ponovni
pokušaj nakon izgubljenog odgovora ne bi mogao stvoriti drugi objekt. GET, PUT i DELETE sigurno je ponovno
pokušati takve kakvi jesu.
// 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." }),
}),
);Prijava problema
Svaki odgovor, uspješan ili ne, ima zaglavlje X-Request-Id, a svaka pogreška ima istu vrijednost u
error.request_id. Zapišite je uz vlastiti zapis o zahtjevu. Kad se obraćate podršci zbog nekog zahtjeva, pošaljite
njegov ID zahtjeva: on vodi izravno do zapisa o tom zahtjevu.
Obrada nepoznatih kodova
Novi kodovi pogrešaka mogu se pojaviti u bilo kojoj verziji API-ja. Nepoznati kod obrađujte prema njegovu HTTP
statusu: nepoznati 4xx kao zahtjev koji u tom obliku neće uspjeti, nepoznati 5xx kao privremeni problem.