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

الصفحات والفلاتر في الـ API

كيف تُقسَّم قوائم الـ API إلى صفحات (page و per_page و meta) وأي الفلاتر تعمل فعلاً، ومنها قيم stage في واجهة التاجر: القيمتان processing و awaiting_funds تُتجاهلان بينما ترفض واجهة الشركة القيم المجهولة.

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

الغرض#

تشرح هذه الصفحة كيف تُقسَّم قوائم الـ API إلى صفحات، وأي الفلاتر تعمل فعلاً كما هي مبرمجة، وخصوصاً قيم stage المقبولة في واجهة التاجر.

من يستخدمها وما المطلوب#

  • التاجر (تاجر منصة) بمفتاح API على /api/v1، ومدير شركة التوصيل بمفتاح الشركة على /api/company/v1. راجع مقالة حدود الطلبات.

القوائم المقسّمة إلى صفحات#

الطلب per_page الافتراضي الأقصى الترتيب الفلاتر
GET /api/v1/parcels 20 100 الأحدث أولاً (بحسب id) reference وfrom وto وstage
GET /api/v1/statement 100 500 الأقدم أولاً (التاريخ ثم id) from وto وwallet وcategory
GET /api/company/v1/parcels 20 100 الأحدث أولاً (بحسب id) merchant_id وdeliveryman_id وreference وfrom وto وupdated_since وstage
GET /api/company/v1/merchants 50 100 بحسب id تصاعدياً q

أما هذه القوائم فلا ترقيم لها، وتعيد كل السجلات دفعة واحدة: في واجهة التاجر /companies و/governorates و/pickup-locations و/warehouse/stock و/webhooks و/webhooks/events، وفي واجهة الشركة /deliverymen.

شكل الرد#

json
{
  "success": true,
  "data": [ { "id": 1043, "tracking_number": "DS261013AB12CD", "reference": "ORDER-1043", "stage": "delivered", "status_code": 9 } ],
  "meta": { "page": 1, "per_page": 50, "total": 132, "last_page": 3 }
}

(كائنات الطرد مختصرة هنا.) المفاتيح الأربعة في meta هي الوحيدة؛ لا يوجد links ولا مؤشر (cursor). ويشذ GET /statement في data: فهي كائن يضم period وcurrency وwallets وby_category وlines (المصفوفة المقسّمة إلى صفحات)، وتُحصي meta عناصر lines وحدها. القواعد:

  • page يبدأ من 1. القيمة غير الصحيحة أو الأقل من 1 تعامَل كأنها 1.
  • per_page خارج المجال المسموح لا يُرفض بل يُقصّ إلى أقرب حد (مثلاً 500 في قائمة الطرود تصبح 100). والقيمة الفعلية تعود في meta.per_page.
  • صفحة بعد الأخيرة تعيد data فارغة، وتبقى total وlast_page في meta كما هما. وعند عدم وجود نتائج تكون قيمة last_page هي 1.
  • total هو عدد السجلات بعد تطبيق الفلاتر.

فلاتر قائمة الطرود (التاجر)#

  • reference: تطابق تام مع مرجع الطرد الذي أرسلته عند الإنشاء.
  • from وto: بصيغة YYYY-MM-DD، وتشملان اليومين، وتُقارَنان بتاريخ إنشاء الطرد (التوقيت UTC). لا يُتحقَّق من الصيغة، فلا تستعمل غيرها.
  • stage: ست قيم فقط تعمل، وهي تطابق حقل stage في كائن الطرد:
قيمة stage تطابق status_code
pending 1
out_for_delivery 7 و8
delivered 9
partially_delivered 32
returning 24 و26 و27 و11 و12
returned 30 و13

الطرود في حالة awaiting_funds (تُنشأ مع wait_for_balance أو من طلبات المتاجر المربوطة) لا تظهر في القائمة، لكن يمكن جلب الواحد منها برقم التتبع أو بـ reference عبر GET /parcels/{tracking}.

الاختلافات في واجهة الشركة#

  • أي قيمة غير معروفة في stage تُرفض بـ 422 validation_failed مع رسالة تسرد القيم المتاحة، بدل تجاهلها.
  • القيمة processing تعمل هنا وتطابق الأكواد 2 و3 و4 و5 و6 و19 فقط. وأي طرد يحمل كود حالة خارج الفئات الموثّقة (مثل كود قديم أو غير معتاد) يُعرض بقيمة stage تساوي processing، لكن هذا الفلتر لا يطابقه. أما awaiting_funds فغير مقبولة (422).
  • updated_since بصيغة YYYY-MM-DD HH:MM:SS تعيد الطرود التي تحدّثت منذ ذلك الوقت، وهي الأنسب للمزامنة الدورية.
  • merchant_id وdeliveryman_id يُطبَّقان عند إرسالهما، ويبحث q في قائمة التجار عن اسم النشاط أو رقم الموبايل.

فلاتر كشف الحساب (/statement)#

  • from وto تُقبلان بصيغة YYYY-MM-DD حرفياً، وإلا تُهملان ويُستعمل الافتراضي: من أول الشهر إلى اليوم. إذا كانت from بعد to تُبدَّلان. والمدى الأطول من 366 يوماً يُقصَّر بتحريك from إلى 366 يوماً قبل to بدون خطأ.
  • wallet: إحدى القيم recharge أو held أو return أو payout_pending، وإلا تُهمل.
  • category: أحرف لاتينية صغيرة وشرطة سفلية (من 2 إلى 60 حرفاً)، ولا تُقارَن بقائمة فئات معروفة: فالقيمة غير المعروفة لا تعيد lines ويبقى by_category فارغاً، أما wallets فتبقى فيها المحافظ برصيدَي الافتتاح والإغلاق، وتكون credits وdebits وcount أصفاراً.
  • أقسام wallets وby_category تغطي الفترة كاملة بغض النظر عن الصفحة؛ الصفحات تخص lines فقط.

قراءة كل الصفحات#

  1. اطلب الصفحة 1 بقيمة `per_page` ثابتة

    أرسل per_page=100 مع فلاترك، وأبقِ الفلاتر نفسها في الطلبات التالية.

  2. اقرأ `meta.last_page`

    هذا هو عدد الصفحات. لا تعتمد على عدد عناصر data لتعرف أنك وصلت إلى النهاية.

  3. اطلب بقية الصفحات

    زد page حتى last_page، وعند رد 429 انتظر Retry-After ثم أعد الطلب نفسه.

  4. تعامل مع تغيّر القائمة أثناء القراءة

    تظهر الطرود الجديدة في أعلى القائمة وتختفي الملغاة، فقد يتكرر طرد أو يفوتك آخر. أزل التكرار بحسب id، وثبّت المدى بـ from وto، وللمزامنة الدائمة استعمل الويب هوك أو (للشركات) updated_since.

python
import time
import requests

BASE = "https://YOUR_PLATFORM_DOMAIN/api/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY", "Accept": "application/json"}


def all_parcels(filters):
    page = 1
    while True:
        response = requests.get(
            f"{BASE}/parcels",
            headers=HEADERS,
            params={**filters, "per_page": 100, "page": page},
            timeout=30,
        )
        if response.status_code == 429:
            time.sleep(int(response.headers.get("Retry-After", 60)))
            continue
        response.raise_for_status()
        body = response.json()
        yield from body["data"]
        if page >= body["meta"]["last_page"]:
            break
        page += 1


for parcel in all_parcels({"stage": "delivered", "from": "2026-10-01", "to": "2026-10-31"}):
    print(parcel["tracking_number"], parcel["stage"])

أخطاء شائعة#

  • توقّع أن stage=processing يصفّي النتائج في واجهة التاجر: لن تحصل إلا على كل الطرود. صفِّ النتائج من جانبك بحسب الحقل stage.
  • per_page=500 على الطرود: لا خطأ، لكنك لن تحصل إلا على 100؛ اقرأ meta.per_page.
  • تواريخ بصيغة مختلفة (مثل 13/10/2026): في قائمة الطرود لا يُتحقَّق منها (نتائج غير متوقعة)، وفي كشف الحساب تُهمل.

الصلاحيات والحدود#

يلزم مفتاح API فعّال، وميزة api في الباقة حين تنطبق الباقات على حسابك (وإلا 403 plan_feature)؛ وواجهة التاجر لتجار المنصة لا لتجار الشركات. كل طلب صفحة يحتسب ضمن 60 طلباً في الدقيقة لكل عنوان IP وضمن حد باقتك، لذلك اختر per_page كبيراً بدل كثرة الصفحات الصغيرة.

API

  • GET /api/v1/parcels
  • GET /api/v1/statement
  • GET /api/company/v1/parcels
  • GET /api/company/v1/merchants