İçeriğe geç
Sursa Developers

Hatalar

Sursa, bir isteğin başarılı olup olmadığını HTTP durum kodlarıyla, neden başarılı olmadığını ise değişmeyen bir hata koduyla bildirir. Tüm hata yanıtları aynı biçimdedir:

{
  "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"
  }
}
AlanAnlamı
error.code<area>.<reason> biçiminde değişmeyen kod. Kodunuzdaki dallanmayı buna göre yapın.
error.messageOkunabilir İngilizce açıklama. Her an yeniden yazılabilir; bu metni ayrıştırmayın.
error.detailsHatayla ilgili yapılandırılmış bilgiler: parametre, bir sınır ya da ne zaman yeniden deneneceği gibi. Alanları koda göre değişir.
error.request_idBu isteğin kimliği; X-Request-Id yanıt başlığıyla aynıdır.
error.doc_urlBu portalda bu kodu anlatan sayfa.
detailHatanın daha önceki biçimi; mevcut entegrasyonlar için korunur. Yeni kod error alanını okumalıdır.

Her kodun Hata kodları altında kendi sayfası vardır: HTTP durumu, details alanları ve kodu döndüren uç noktalar. API başvurusunda her uç noktanın sayfası, o uç noktanın döndürebileceği kodları listeler.

HTTP durumları

DurumAnlamı
200, 201, 202, 204İstek başarılı oldu. 202, isteğin kabul edildiği ve hâlâ işlendiği anlamına gelir.
400İstek hatalı biçimlendirilmiş: hatalı bir parametre, imleç, metadata ya da Idempotency-Key. İsteği düzeltin.
401Geçerli bir anahtar yok. Kimlik doğrulama sayfasına bakın.
402Kuruluşun planındaki bir sınıra ulaşıldı: örneğin kart sayısı ya da depolama alanı.
403Anahtar geçerli, ancak bu işleme izin verilmiyor: bir rol, kapsam ya da plan özelliği eksik.
404Nesne yok ya da anahtar bu nesneye erişemiyor.
409İstek mevcut durumla çakışıyor: yinelenen bir external_id, açık bir senkronizasyon, aynı Idempotency-Key ile gönderilmiş ve hâlâ çalışan bir istek.
410Nesnenin süresi dolmuş (örneğin 24 saati geçmiş bir yükleme) ya da yol kullanımdan kaldırılmış.
413Gövde ya da dosya çok büyük.
415Dosya türü desteklenmiyor ya da dosyanın içeriği adıyla uyuşmuyor.
422İstek doğru biçimlendirilmiş, ancak geçersiz: eksik bir alan ya da izin verilen aralığın dışında bir değer.
429Çok fazla istek gönderildi ya da bir kota tükendi. Hız sınırları ve kotalar sayfasına bakın.
500, 502, 503, 504Sursa tarafında bir sorun var. Daha sonra yeniden deneyin.

Geçerlilik hataları

validation.failed kodlu 422 yanıtında detail alanı, başarısız olan her alanı konumuyla birlikte listeler:

{
  "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…"}
}

Hangi hatalar yeniden denenmeli

HataYeniden denensin mi?
Ağ hatası ya da zaman aşımı, yanıt yokEvet, aynı Idempotency-Key ile.
429Evet, Retry-After başlığındaki saniye sayısı kadar bekledikten sonra.
500, 502, 503, 504Evet, üstel geri çekilmeyle: 1 sn, 2 sn, 4 sn… bir dakikaya kadar, rastgele sapmayla.
409 api.idempotency_in_progressEvet, Retry-After süresinden sonra: bu anahtarla gönderilen ilk istek hâlâ çalışıyor.
Diğer tüm 4xxHayır. Aynı istek yine başarısız olur; önce isteği düzeltin.

POST ve PATCH isteklerini yalnızca bir Idempotency-Key ile yeniden deneyin; böylece yanıtı kaybolan bir isteğin yeniden denenmesi ikinci bir nesne oluşturamaz. GET, PUT ve DELETE istekleri olduğu gibi güvenle yeniden denenebilir.

// 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." }),
  }),
);

Sorun bildirme

Başarılı olsun ya da olmasın her yanıtta bir X-Request-Id başlığı bulunur ve her hatada aynı değer error.request_id alanında yer alır. Bu değeri, isteğe ilişkin kendi kaydınızla birlikte günlüğe yazın. Bir istekle ilgili olarak destek ekibine başvurduğunuzda isteğin kimliğini gönderin: bu kimlik doğrudan o isteğin kaydına götürür.

Bilmediğiniz kodları ele alma

API’nin her sürümünde yeni hata kodları ortaya çıkabilir. Bilinmeyen bir kodu HTTP durumuna göre ele alın: bilinmeyen bir 4xx kodunu olduğu gibi başarılı olmayacak bir istek olarak, bilinmeyen bir 5xx kodunu geçici bir sorun olarak değerlendirin.