مرجع المطوّرون

حدود الطلبات في الـ API كما تُطبَّق فعلياً

الحدود التي يطبّقها الكود فعلياً على واجهة الـ API: 60 طلباً في الدقيقة لكل عنوان IP، وحدود المسارات، وحدود الباقة بالدقيقة وباليوم، وشكل ردّ 429. أما الأرقام القديمة في اللوحة (120 و300 لكل مفتاح) فغير مطبّقة، والحدود الفعلية هي لكل عنوان IP إضافة إلى حدود الباقة.

آخر تحديث 22 أكتوبر 2026 · آخر تحقق 22 أكتوبر 2026

الغرض#

تسرد هذه الصفحة حدود الطلبات التي يطبّقها الكود فعلياً على واجهة التاجر (/api/v1) وواجهة شركة التوصيل (/api/company/v1).

من يتأثر بها#

  • التجار الذين يستدعون /api/v1 بمفتاح الـ API. هذه الواجهة لتجار المنصة فقط؛ والتاجر الذي أنشأته شركة توصيل يتلقى الرد 403 api_not_allowed.
  • مديرو شركات التوصيل الذين يستدعون /api/company/v1 بمفتاح الشركة.

الحدود المطبّقة فعلاً#

الطبقة تنطبق على تُحتسب لكل الحد
1. العدّاد العام للـ API كل طلب إلى /api/* عنوان IP 60 في الدقيقة
2. حدود المسارات، واجهة التاجر مجموعة /api/v1 كلها؛ ثم POST /parcels وGET /statement وPOST /webhooks وPOST /webhooks/{id}/test عنوان IP 120؛ ثم 60 و30 و20 و10 في الدقيقة
3. حدود المسارات، واجهة الشركة مجموعة /api/company/v1 كلها؛ ثم POST /parcels عنوان IP 300؛ ثم 120 في الدقيقة
4. حد الباقة بالدقيقة كل طلب بمفتاح الحساب الحساب قيمة api_per_minute في الباقة
5. حد الباقة باليوم كل طلب بمفتاح الحساب الحساب قيمة api_per_day في الباقة

كيف تتداخل الطبقات:

  • أول سقف تبلغه يوقف الطلب قبل تنفيذ الإجراء المطلوب، فلا يُنشأ شيء.
  • الطبقات من 1 إلى 3 مرتبطة بعنوان IP لا بمفتاح الـ API، فكل من يقف خلف عنوان عام واحد (مكتب أو خادم استضافة أو NAT، وحتى مفتاحان على الخادم نفسه) يتشاركها. والطبقة 1 تسمح بـ 60 طلباً فقط في الدقيقة على كل /api/*، لذلك يندر عملياً أن يُبلَغ حدّا المجموعة 120 و300 (العدّادات منفصلة، فلا يُضمَن ذلك)؛ أما حدود المسارات الأقل (60 و30 و20 و10) فقد تُبلَغ.
  • حدود المسارات بلا عدّاد خاص بكل مسار؛ كلها تُحتسب على عدّاد واحد لكل عنوان IP، وكل طلب إلى مسار له حد خاص (POST /parcels وGET /statement وPOST /webhooks وPOST /webhooks/{id}/test في واجهة التاجر، وPOST /parcels في واجهة الشركة) يُحتسب مرتين: مرة على مستوى المجموعة ومرة على مستوى المسار. لذلك يقارب سقفه العملي نصف الرقم في الجدول (مثلاً نحو 15 طلباً في الدقيقة إلى GET /statement لا 30، إن لم يصدر من العنوان نفسه طلب آخر).
  • كل عدّاد نافذة ثابتة تبدأ مع أول طلب محتسب وتُصفَّر بعد 60 ثانية، وعدّاد الباقة اليومي يُصفَّر عند 00:00 بتوقيت UTC.

حدود الباقة#

  • عند فتح نموذج باقة جديدة يأتي مملوءاً بهذه القيم: باقات التجار 60 طلباً في الدقيقة و5,000 في اليوم؛ وباقات الشركات 120 في الدقيقة و20,000 في اليوم. ويغيّرها المدير لأي باقة.
  • القيمة الفارغة أو 0 تعني بلا حد. والباقة القديمة التي لم تُضبط ميزاتها بعد ليس عليها أي حد.
  • حدود التاجر تنطبق على تجار المنصة فقط، ولا تنطبق إلا مع وجود باقة تجار مفعّلة واحدة على الأقل.
  • لمعرفة حدودك: يفتح التاجر صفحة الباقات (بطاقة الباقة تذكر أرقام الـ API، و«استهلاكك من الباقة» يعرض «طلبات الـ API اليوم»). ويرى مدير الشركة الباقة والاستهلاك في «الربط والـ API»، ويعيد GET /api/company/v1/me صفوف الاستهلاك نفسها (name وused وlimit، وlimit تساوي null عند عدم وجود حد).

شكل الطلب المرفوض#

حد الباقة (الطبقتان 4 و5). رد HTTP 429 بغلاف الأخطاء المعتاد في الـ API، مع ترويسة Retry-After بالثواني:

json
{
  "success": false,
  "error": {
    "code": "rate_limited",
    "message": "نص محلّي يذكر الحد ومدة الانتظار",
    "retry_after": 42
  }
}

حدود IP والمسارات (الطبقات 1 إلى 3). رد HTTP 429 من إطار العمل قبل تشغيل كود الـ API. إذا أرسلت Accept: application/json فستحصل على جسم JSON فيه message بقيمة Too Many Attempts. مع الترويسات Retry-After وX-RateLimit-Limit وX-RateLimit-Remaining وX-RateLimit-Reset. وبدون Accept: application/json (إذ يرسل curl افتراضياً Accept: */*) تحصل على صفحة خطأ HTML ومن دون Retry-After.

تحمل الردود الناجحة X-RateLimit-Limit وX-RateLimit-Remaining لحدود IP هذه (الأقرب إلى النفاد)، فتستطيع التباطؤ قبل أول 429. ولا تظهر حدود الباقة في هذه الترويسات.

نص error.message في ردّ حد الباقة محلّي (أرسل Accept-Language: en للإنجليزية، والافتراضي العربية)، أما رسالة Too Many Attempts. في حدود IP والمسارات فبالإنجليزية دائماً. فابنِ منطقك على رمز حالة HTTP والترويسة Retry-After (وعلى error.code في حد الباقة)، لا على نص الرسالة.

أرقام قديمة في اللوحة#

توثيق الـ API داخل اللوحة ينصّ على حدود لكل مفتاح، ولا يوجد في الكود حد لكل مفتاح: «120 طلب بالدقيقة لكل مفتاح، ومنها 60 لإنشاء الطرود» (صفحة توثيق واجهة التاجر) و«حد عام 300 طلب بالدقيقة للمفتاح، ومنها 120 لإنشاء الطرود» (صفحة توثيق واجهة الشركة). وتقول صفحة التاجر أيضاً إن الباقة الفعّالة لازمة «لتنشئ طرود»، والصحيح أنها لازمة، حين تنطبق الباقات، لكل المسارات (راجع «الصلاحيات والمتطلبات»). المطبّق هو الجدول أعلاه.

التعامل مع الحدود في برنامجك#

  1. اطلب JSON

    أرسل Accept: application/json في كل طلب، فيحمل كل رد 429 جسم JSON وترويسة Retry-After.

  2. انتظر `Retry-After` ثم أعد المحاولة

    عند 429 انتظر عدد الثواني المذكور في Retry-After (أو error.retry_after) ثم أعد المحاولة. وأضف تأخيراً عشوائياً إذا كانت عدة عمليات تعمل من عنوان IP واحد لأنها تتشارك العدّاد.

  3. اجعل إعادة محاولة الإنشاء آمنة

    أرسل reference مع POST /parcels. في واجهة التاجر، إرسال المرجع نفسه مرة ثانية (إعادة محاولة واحدة في كل مرة) يعيد الطرد الموجود (رد 200 مع "duplicate": true) بدل إنشاء طرد آخر، ويتجاهل هذا الفحص الطرود المستردة أو المنتهية. أما في واجهة الشركة فتكرار المرجع للتاجر نفسه يعطي 409 duplicate_reference: اجلب الطرد بـ GET /api/company/v1/parcels/{reference}.

  4. قلّل الاستعلام الدوري

    استعمل الويب هوك لتغيّرات الحالة، وخزّن مؤقتاً القوائم التي نادراً ما تتغير مثل /governorates و/companies و/pickup-locations.

الصلاحيات والمتطلبات#

  • لكل حساب مفتاح واحد: يولّده التاجر بزر «توليد» في صف «API للمطورين» ضمن «الويب هوك والـ API»، ويولّده مدير الشركة من «الربط والـ API».
  • حين تنطبق الباقات على حسابك يلزم أن تكون ميزة api مفعّلة في باقتك الفعّالة لكل مسارات /api/v1 (لا لإنشاء الطرود فقط)، وإلا يكون الرد 403 plan_feature؛ وكذلك التاجر بلا اشتراك فعّال. وللشركات: الاشتراك المنتهي يعطي 402 subscription_expired.
  • الحساب الموقوف يتلقى 403 account_inactive.

API

  • GET /api/v1/parcels
  • POST /api/v1/parcels
  • GET /api/v1/statement
  • POST /api/v1/webhooks
  • GET /api/company/v1/me
  • POST /api/company/v1/parcels