Пређите на садржај
Sursa Developers

Грешке

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_idID овог захтева, исти као у заглављу одговора 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 као привремени проблем.