انتقل إلى المحتوى

الأخطاء وحدود الطلبات في واجهة مُجيب البرمجية

حدود الطلبات في واجهة مُجيب البرمجية 60 طلبًا في الدقيقة لكل مفتاح، وكل خطأ يعود بالشكل نفسه: رمز HTTP وجسم JSON فيه code ثابت وmessage يشرحه. هذه الصفحة تجمع الرموز كلها، وما تفعله عند كل منها، وكيف تبقى داخل الحد.

كيف يبدو الخطأ في الواجهة؟

رابط القسم «كيف يبدو الخطأ في الواجهة؟»

كل خطأ جسمه كائن واحد اسمه error، فيه الحقلان code وmessage:

{ "error": { "code": "NOT_FOUND", "message": "Contact not found" } }
  • code رمز ثابت بحروف إنجليزية كبيرة. ابنِ برنامجك عليه.
  • message شرح بالإنجليزية للمطوّر، وقد يتغيّر نصه، فلا تبنِ عليه شيئًا.
  • issues و**issueCount** يظهران فقط مع الخطأ 400 عندما يكون معامل في الرابط غير صالح: issues قائمة بأول 20 مشكلة وُجدت، كل منها يسمّي المعامل في path، وissueCount عدد المشكلات كلها.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input",
"issues": [
{ "code": "too_big", "maximum": 100, "type": "number", "inclusive": true, "exact": false, "message": "Number must be less than or equal to 100", "path": ["limit"] }
],
"issueCount": 1
}
}

ما رموز الأخطاء وما معنى كل منها؟

رابط القسم «ما رموز الأخطاء وما معنى كل منها؟»

هذه كل الرموز التي تعيدها الواجهة:

HTTPcodeمتى يظهرما تفعله
400VALIDATION_ERRORمعامل غير معروف، أو limit خارج المسموح، أو تاريخ غير صحيح، أو from بعد to، أو status غير معروف، أو مؤشر صفحة لا يُقرأأصلح الطلب ولا تعِده كما هو
401UNAUTHORIZEDلا مفتاح، أو مفتاح غير صالح أو ملغى أو منتهٍ، أو حساب نشاط غير فعّالراجع مفتاح API
403FORBIDDENالمفتاح صالح لكن ينقصه contacts.read أو bookings.readأنشئ مفتاحًا بالصلاحية المطلوبة
404NOT_FOUNDمعرّف غير موجود في نشاطك، أو معرّف بصيغة غير صحيحة، أو مسار غير موجودتحقق من المعرّف والمسار
429RATE_LIMITEDتجاوزت حدود الطلباتانتظر ثم أعد المحاولة
500INTERNALخطأ غير متوقع في الخادمأعد المحاولة بعد قليل

المعرّف الذي ينتمي إلى نشاط آخر يعود بالخطأ 404 نفسه الذي يعود به المعرّف غير الموجود، فلا يكشف الرد أي شيء عن بيانات غيرك.

ما حدود الطلبات في واجهة مُجيب البرمجية؟

رابط القسم «ما حدود الطلبات في واجهة مُجيب البرمجية؟»

لكل مفتاح 60 طلبًا في كل دقيقة، ويبدأ العدّ من جديد مع بداية الدقيقة التالية. كل طلب بمفتاح صالح يُحسب، حتى الذي يعود بالخطأ 400 أو 403 أو 404.

يحمل كل رد بمفتاح صالح ثلاث ترويسات تصف حد مفتاحك:

الترويسةمعناها
X-RateLimit-Limitعدد الطلبات المسموح بها للمفتاح في الدقيقة
X-RateLimit-Remainingما بقي للمفتاح في الدقيقة الحالية
X-RateLimit-Resetعدد الثواني حتى تبدأ دقيقة المفتاح من جديد

وفوق حد المفتاح يوجد حد أوسع لكل عنوان شبكة، تشترك فيه كل الطلبات القادمة من العنوان نفسه، بأي مفتاح كانت. إذا وصلت إليه فإن ترويسات رد الخطأ 429 تصف ذلك الحد لا حد مفتاحك. أما رد الخطأ 401 فلا تعتمد على ترويساته في حساب حد مفتاحك.

انتظر عدد الثواني المذكور في الترويسة Retry-After، ثم أعد الطلب نفسه. هكذا يبدو الرد عندما يستنفد المفتاح دقيقته:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 17
Content-Type: application/json; charset=utf-8
{"error":{"code":"RATE_LIMITED","message":"At most 60 requests a minute per key."}}

القيمة في X-RateLimit-Reset تقول متى تبدأ الدقيقة الجديدة فعلًا، وهي غالبًا أقل من Retry-After. انتظار أي منهما كافٍ. هذه دالة تنتظر وتعيد المحاولة:

async function getWithRetry(url, tries = 3) {
for (let i = 0; ; i++) {
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.MUJIB_API_KEY}` } });
if (res.status !== 429 || i === tries - 1) return res;
const wait = Number(res.headers.get('x-ratelimit-reset') ?? res.headers.get('retry-after') ?? '60');
await new Promise((r) => setTimeout(r, wait * 1000));
}
}
import os
import time
import requests
def get_with_retry(url, params=None, tries=3):
for i in range(tries):
res = requests.get(url, params=params, timeout=30,
headers={"Authorization": f"Bearer {os.environ['MUJIB_API_KEY']}"})
if res.status_code != 429 or i == tries - 1:
return res
wait = int(res.headers.get("X-RateLimit-Reset") or res.headers.get("Retry-After") or 60)
time.sleep(wait)

ما الأخطاء التي تستحق إعادة المحاولة؟

رابط القسم «ما الأخطاء التي تستحق إعادة المحاولة؟»

أعد المحاولة عند 429 و500 فقط، وأصلح الطلب في كل حالة أخرى.

  • 429: انتظر كما سبق، ثم أعد المحاولة.
  • 500: أعد المحاولة بعد ثوانٍ، وضاعف الانتظار إذا تكرر الخطأ.
  • 400 و401 و403 و404: إعادة الطلب نفسه تعيد الخطأ نفسه، وتستهلك من حدك. أصلح المعامل أو المفتاح أو المعرّف أولًا.

كيف أبقى داخل حدود الطلبات؟

رابط القسم «كيف أبقى داخل حدود الطلبات؟»

اطلب صفحات أكبر، واطلب ما تغيّر فقط، ودع مُجيب يخبرك بالأحداث.

  • اجعل limit في القوائم 100، فتقرأ أكبر عدد ممكن في كل طلب. انظر التقسيم إلى صفحات.
  • في العملاء استخدم since لتطلب الجدد فقط، وفي الحجوزات استخدم from وto لتطلب الأيام التي تهمك.
  • إذا كنت تسأل الواجهة كل دقيقة لتعرف الجديد، فاستخدم Webhooks بدلًا من ذلك.
  • اجعل لكل نظام مفتاحًا مستقلًا، فلكل مفتاح حده. وتذكّر أن الطلبات من خادم واحد تشترك في حد العنوان.

الأسئلة الشائعة

هل تُحسب الطلبات التي ترجع بخطأ ضمن الحد؟

نعم. كل طلب بمفتاح صالح يُحسب، حتى لو عاد بالخطأ 400 أو 403 أو 404. أما الطلب الذي يُرفض مفتاحه بالخطأ 401 فلا يُحسب على المفتاح.

هل لكل مفتاح حدّه الخاص؟

نعم. لكل مفتاح 60 طلبًا في الدقيقة، ولا يؤثر مفتاح في حد مفتاح آخر. لكن كل الطلبات من عنوان الشبكة نفسه تخضع أيضًا لحد أوسع مشترك.

هل أبني برنامجي على نص message في الخطأ؟

لا. ابنِ على رمز code فهو ثابت. نص message شرح بالإنجليزية للمطوّر وقد يتغيّر.

متى يبدأ العدّ من جديد؟

مع بداية كل دقيقة. الترويسة X-RateLimit-Reset تقول كم ثانية بقيت حتى ذلك.