Грешке
Sursa помоћу HTTP статусних кодова саопштава да ли је захтев успео, а помоћу стабилног кода грешке – зашто није успео. Сваки одговор са грешком има исти облик:
{
"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"
}
}
| Поље | Значење |
|---|---|
error.code | Стабилан код у облику <area>.<reason>. Логику свог кода гранајте према њему. |
error.message | Читљиво објашњење на енглеском. Може да се преформулише у сваком тренутку; не рашчлањујте га. |
error.details | Структурисане чињенице о грешци, на пример параметар, ограничење или када треба поновити захтев. Поља зависе од кода. |
error.request_id | ID овог захтева, исти као у заглављу одговора X-Request-Id. |
error.doc_url | Страница о овом коду на овом порталу. |
detail | Ранији облик грешке, задржан због постојећих интеграција. Нови код треба да чита error. |
Сваки код има сопствену страницу у одељку Кодови грешака, са HTTP статусом, пољима details и операцијама
које га враћају. Страница сваке операције у API референци наводи кодове које та операција може да
врати.
HTTP статуси
| Статус | Значење |
|---|---|
200, 201, 202, 204 | Захтев је успео. 202 значи да је захтев прихваћен и да се још обрађује. |
400 | Захтев је неисправно формиран: погрешан параметар, курсор, metadata или Idempotency-Key. Исправите захтев. |
401 | Нема важећег кључа. Погледајте Аутентификација. |
402 | Достигнуто је ограничење плана организације, на пример број картица или простор за складиштење. |
403 | Кључ је важећи, али нема дозволу за ово: недостаје улога, опсег или функција плана. |
404 | Објекат не постоји или кључ нема право да га види. |
409 | Захтев је у сукобу са тренутним стањем: дупликат external_id, отворена синхронизација, захтев са истим Idempotency-Key који се још извршава. |
410 | Објекту је истекао рок, на пример отпремању после 24 сата, или је путања повучена из употребе. |
413 | Тело или фајл је превелик. |
415 | Тип фајла није подржан или његов садржај не одговара његовом имену. |
422 | Захтев је исправно формиран, али није валидан: недостаје поље или је вредност ван дозвољеног распона. |
429 | Превише захтева или је квота потрошена. Погледајте Ограничења учесталости и квоте. |
500, 502, 503, 504 | Проблем на страни платформе Sursa. Покушајте поново касније. |
Грешке валидације
За 422 са кодом validation.failed detail наводи свако поље које није прошло
проверу, са његовом локацијом:
{
"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…"}
}
Које грешке треба поновити
| Грешка | Поновити? |
|---|---|
| Мрежна грешка или истек времена, нема одговора | Да, са истим Idempotency-Key. |
429 | Да, после броја секунди из Retry-After. |
500, 502, 503, 504 | Да, са експоненцијално растућом паузом: 1 s, 2 s, 4 s… до једног минута, уз насумично одступање. |
409 api.idempotency_in_progress | Да, после Retry-After: први захтев са овим кључем се још извршава. |
Било који други 4xx | Не. Исти захтев ће поново пасти; прво га исправите. |
Захтеве POST и PATCH понављајте само са Idempotency-Key, како поновни покушај
после изгубљеног одговора не би креирао други објекат. GET, PUT и DELETE могу безбедно да се понове такви
какви су.
// 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." }),
}),
);Пријава проблема
Сваки одговор, успешан или не, има заглавље X-Request-Id, а свака грешка има исту вредност у error.request_id.
Уписујте је у лог заједно са сопственим записом о захтеву. Када се обраћате подршци у вези са неким захтевом,
пошаљите његов ID захтева: он води право до записа о том захтеву.
Обрада кодова које не познајете
Нови кодови грешака могу да се појаве у било којој верзији API интерфејса. Непознат код третирајте према његовом
HTTP статусу: непознат 4xx као захтев који у том облику неће успети, а непознат 5xx као привремени проблем.