الأخطاء
يستخدم 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 | معرّف هذا الطلب، وهو نفسه في ترويسة الاستجابة 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 | نعم، مع تراجع أُسّي: ثانية واحدة، ثم ثانيتان، ثم 4 ثوانٍ… حتى دقيقة، مع تشتيت عشوائي. |
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. سجّلها مع سجلك الخاص
للطلب. وحين تتواصل مع الدعم بشأن طلب، أرسل معرّف الطلب: فهو يقود مباشرة إلى سجل ذلك الطلب.
التعامل مع الرموز المجهولة
قد تظهر رموز أخطاء جديدة في أي إصدار من واجهة API. تعامل مع الرمز المجهول حسب حالة HTTP: الحالة 4xx المجهولة طلب
لن ينجح كما هو، والحالة 5xx المجهولة مشكلة مؤقتة.