الأخطاء ورموز الحالة في واجهات الـ API
رموز حالة HTTP وأكواد الأخطاء الحقيقية في واجهتي التاجر والشركة: شكل الخطأ، وترتيب الفحوصات، وجدول بمعنى كل كود وإصلاحه، وأخطاء التحقق 422، وكيف تتعامل معها في برنامجك.
آخر تحديث 22 أكتوبر 2026 · آخر تحقق 22 أكتوبر 2026
الغرض#
تسرد هذه الصفحة رموز حالة HTTP وأكواد الأخطاء التي تعيدها فعلاً واجهة التاجر (/api/v1) وواجهة الشركة (/api/company/v1)، ومعنى كل منها وطريقة إصلاحه. ابنِ معالجة الأخطاء على error.code.
شكل الخطأ#
النجاح هو 200، أو 201 عند إنشاء مورد جديد، كطرد أو رابط ويب هوك. و200 مع "duplicate": true تعني أن reference موجود مسبقاً (واجهة التاجر). وكل خطأ يُرجعه الـ API نفسه يأتي بهذا الشكل:
{
"success": false,
"error": {
"code": "validation_failed",
"message": "...",
"fields": { "customer_phone": ["..."] }
}
}
codeكود قصير بصيغة snake_case، وعليه يعتمد برنامجك.messageنص بلغة الطلب: العربية افتراضياً، والإنجليزية معAccept-Language: en. وبعض الرسائل موجودة بالعربية فقط، فلا تبنِ المنطق على النص أبداً.- يظهر
fieldsفي معظم أخطاء التحقق: أسماء الحقول مع رسائلها، ويكرّرmessageعادةً أول رسالة فيها (والاستثناء خطأmerchant_idفي واجهة الشركة: يحملfields.merchant_idالرسالة «تاجر غير موجود عند شركتك.» بينما يحملmessageنصmerchant_idالأطول الوارد في جدول التحقق). وبعض أخطاء واجهة الشركة (stageغير معروف، أوdeliveryman_idناقص أو لمندوب من شركة أخرى، أوactionغير معروف) تحملmessageفقط. وأسماء الحقول هي الأسماء الداخلية للمنصة (customer_nameوcustomer_phoneوcustomer_addressوcustomer_cityوlatوlongوshop_idبدلpickup_location_id). - يظهر
retry_after(بالثواني) معrate_limited، وreferenceمعserver_error، وresponse_statusمعdelivery_failed.
ترتيب الفحوصات#
يمرّ كل استدعاء بهذه الفحوصات ويتوقف عند أول فشل. وبعدها تطبّق النقطة قواعد التحقق وقواعد العمل الخاصة بها.
| الخطوة | واجهة التاجر | واجهة الشركة |
|---|---|---|
| 1 | وجود المفتاح: unauthenticated |
وجود المفتاح: unauthenticated |
| 2 | صحة المفتاح: invalid_key |
صحة المفتاح: invalid_key |
| 3 | الحساب فعّال: account_inactive |
الحساب والشركة فعّالان: account_inactive |
| 4 | ليس تاجر شركة: api_not_allowed |
الاشتراك فعّال: subscription_expired |
| 5 | الباقة تتضمن الـ API: plan_feature |
الباقة تتضمن الـ API: plan_feature |
| 6 | حدّ الباقة: rate_limited |
حدّ الباقة: rate_limited |
رموز الحالة وأكواد الأخطاء#
| HTTP | error.code |
الواجهة | المعنى | طريقة الإصلاح |
|---|---|---|---|---|
| 401 | unauthenticated |
كلتاهما | لا يوجد مفتاح في ترويسة Authorization: Bearer |
أرسل المفتاح في هذه الترويسة |
| 401 | invalid_key |
كلتاهما | المفتاح غير معروف: جُدّد أو أُلغي أو كُتب خطأ أو هو من نوع آخر | انسخ المفتاح الحالي من اللوحة؛ واستخدم مفتاح «API للمطورين» (sk_) على /api/v1 ومفتاح الشركة (ck_) على /api/company/v1 |
| 402 | insufficient_balance |
كلتاهما | الرصيد لا يكفي؛ وتذكر الرسالة المبلغ المطلوب والمتاح | اشحن المحفظة، أو أرسل wait_for_balance: true (واجهة التاجر) |
| 402 | subscription_expired |
الشركة | انتهى اشتراك الشركة | جدّده من لوحة الشركة |
| 403 | account_inactive |
كلتاهما | مستخدم المفتاح، أو التاجر أو الشركة، موقوف أو غير موجود | تواصل مع مسؤول المنصة |
| 403 | api_not_allowed |
التاجر | التاجر تابع لشركة توصيل | استخدم حساب تاجر منصة |
| 403 | plan_feature |
كلتاهما | الباقة لا تتضمن الميزة (الـ API، أو الويب هوك لـ POST /webhooks)، أو ليس للتاجر باقة فعّالة |
اشترك أو رقِّ الباقة؛ وتسمّي الرسالة الميزة |
| 404 | not_found |
كلتاهما | لا يوجد طرد بهذا الرقم أو المرجع في حسابك أو شركتك، أو لا يوجد ويب هوك كهذا | تحقق من القيمة؛ والطرد الملغى لم يعد موجوداً |
| 409 | not_cancellable |
التاجر | غادر الطرد حالة «بانتظار الاستلام» أو «بالمستودع — جاهز للتوزيع»، أو ذهب إلى شركة شحن خارجية | لا يمكن إلغاء سوى الطرد «بانتظار الاستلام» أو «بالمستودع — جاهز للتوزيع» الذي لم يُرسل إلى شركة شحن خارجية |
| 409 | duplicate_reference |
الشركة | للتاجر طرد بالـ reference نفسه |
اجلبه بـ GET /parcels?merchant_id=<id>&reference=<reference> (فـ GET /parcels/{reference} وحده يبحث في طرود كل تجّارك) |
| 409 | deliveryman_full |
الشركة | يحمل المندوب أقصى عدد من الطرود المفتوحة | اختر مندوباً آخر، أو أرسل force: true |
| 409 | not_allowed |
الشركة | الطرد عند شركة شحن خارجية تتحكم بحالته | لا تغيّر حالته من هنا |
| 409 | invalid_transition |
الشركة | الإجراء لا يناسب الحالة الحالية، أو collected أكبر من مبلغ التحصيل |
اقرأ السبب في الرسالة |
| 422 | validation_failed |
كلتاهما | حقل ناقص أو خاطئ؛ ويعدّدها fields (وفي بعض حالات واجهة الشركة تأتي الرسالة فقط) |
راجع القسم التالي |
| 422 | quote_failed |
التاجر | تعذّر حساب السعر | افحص company_id وحقول المستلم |
| 422 | carrier_error |
كلتاهما | رفضت شركة الشحن الخارجية الطرد، أو هي غير مفعّلة، أو لا يمكن استخدامها (حسابك الخاص غير مربوط، أو العملة أو shipping_paid_by غير مدعوم) |
عالج السبب المذكور في الرسالة |
| 422 | limit_reached |
التاجر | بلغت أقصى عدد من روابط الويب هوك | احذف رابطاً أو رقِّ الباقة |
| 422 | delivery_failed |
التاجر | لم يصل ping التجريبي إلى رابطك؛ وقد يُضاف response_status |
افحص رابطك وخادمك |
| 429 | rate_limited |
كلتاهما | بلغت حدّ الباقة في الدقيقة أو في اليوم (أما الحد العام وحدود المسارات فتردّ بلا error.code، انظر «أخطاء خارج هذا الشكل») |
انتظر retry_after ثانية |
| 500 | server_error |
كلتاهما | خطأ غير متوقع في المنصة. وتُرجعه واجهة الشركة في كل مرة أيضاً عند تعيين مندوب لطرد لا تسمح حالته بالانتقال إلى «مع مندوب التوصيل» | أعد المحاولة لاحقاً وأعطِ الدعم قيمة reference؛ وعند التعيين افحص status_code أولاً |
وهكذا يظهر الحقلان الإضافيان retry_after وreference:
{
"success": false,
"error": {
"code": "rate_limited",
"message": "...",
"retry_after": 42
}
}
{
"success": false,
"error": {
"code": "server_error",
"message": "...",
"reference": "E3FA91C"
}
}
أخطاء التحقق (422)#
يربط fields كل حقل فاشل برسائله. وهذه الحقول التي ستصادفها أكثر من غيرها:
| الحقل | السبب المعتاد | مثال على الرسالة |
|---|---|---|
company_id |
غائب، أو الشركة غير متاحة لك | «company_id مطلوب — جيب القائمة من GET /companies» |
customer_name وcustomer_phone وcustomer_address |
غائبة؛ والهاتف يقبل من 6 إلى 30 حرفاً من الأرقام و+ والمسافات و- والأقواس |
نص التحقق القياسي |
customer_city |
تعذّر العثور على المحافظة، أو لا سعر للشركة إليها، أو هي خارج التغطية | «شركة التوصيل تحسب حسب المحافظة: ما قدرنا نعرف محافظة المستلم من العنوان "..." — اختر المحافظة من القائمة.» |
lat وlong |
خارج النطاق، أو التسعير حسب المسافة يحتاج موقع المستلم | «شركة التوصيل تحسب حسب المسافة: حدد موقع المستلم على الخريطة.» |
shop_id |
مكان الاستلام ليس لك، أو لا تملك أي مكان، أو لا موقع له على الخريطة للتسعير حسب المسافة، أو انتهى حجز المستودع | «الفرع المختار لا يتبع لك» |
warehouse_items |
مكان الاستلام مستودع والمنتجات غائبة أو تتجاوز المخزون | تسمّي الرسالة المنتج والكمية |
weight |
خارج المدى من 0.01 إلى 1000، أو أكبر من أقصى وزن للشركة | «"..." بتقبل طرود لحد N كغ — وزن الطرد M كغ.» |
cod_amount |
سالب أو أكبر من 100,000,000 | نص التحقق القياسي |
cod_currency أو currency |
عملة غير مدعومة، أو لا تقبلها الشركة، أو لا سعر صرف | «"..." بتقبل المبالغ بـ: ... — غيّر عملة الطرد.» |
shipping_paid_by |
ليس sender ولا customer ولا included_in_cod |
نص التحقق القياسي |
plan |
استُهلكت حصة الطرود في باقة التاجر (واجهة التاجر فقط؛ أما انتهاء الباقة أو غيابها فيعطي 403 والكود plan_feature) |
«وصلت لحد باقتك: N طرد خلال مدة الاشتراك (لحد ...)، واستعملت M. رقّي باقتك أو جدّد الاشتراك لتكمّل.» |
merchant_id |
واجهة الشركة: ليس من تجّارك | message: «merchant_id مطلوب ولازم يكون تاجر عند شركتك (GET /merchants).»؛ وfields.merchant_id: «تاجر غير موجود عند شركتك.» |
collected |
واجهة الشركة: partial بدون رقم |
«التسليم الجزئي بدو collected (المبلغ اللي انحصّل).» |
delivery_man_id |
واجهة الشركة: تشترط شركتك أن يكون المندوب متصلاً وهو غير متصل | تطلب الرسالة من المندوب أن يضغط «متصل» في تطبيق المندوب |
url وevents وname وactive |
قواعد ويب هوك واجهة التاجر: https فقط، ومضيف عام، وحدث واحد على الأقل | «لازم الرابط يكون https://» |
أخطاء خارج هذا الشكل#
تُنتَج بعض الأخطاء قبل أن يعمل كود الـ API، فلا تستخدم الغلاف:
- المسار غير الموجود (
404) وطريقة HTTP الخاطئة (405) والحد العام للطلبات وحدود المسارات (429). معAccept: application/jsonتحصل على جسم JSON فيهmessage؛ وبدونها تحصل على صفحة HTML. - ومع ترويسة JSON تردّ هذه الحدود بـ
{"message": "Too Many Attempts."}ومعه الترويساتRetry-AfterوX-RateLimit-LimitوX-RateLimit-RemainingوX-RateLimit-Reset. فقد يأتي429من ثلاثة مصادر: الحد العام (60 طلباً في الدقيقة لكل عنوان IP) وحدود المسارات (بلاerror.code)، وحدّ الباقة (rate_limitedداخل الغلاف). - في حالات نادرة قد يقع خلل غير متوقع قبل معالجة الأخطاء الخاصة بالـ API، فيكون الرد
{"success": false, "message": "..."}مع500.
{ "message": "Too Many Attempts." }
التعامل مع الأخطاء في برنامجك#
افحص حالة HTTP أولاً
4xxتعني أن طلبك يجب أن يتغيّر، عدا429. و5xxتعني عادةً أن المشكلة من جهة المنصة، فأعد المحاولة لاحقاً. وهناك حالة لا تزول بإعادة المحاولة: في واجهة الشركة، تعيين مندوب لطرد لا تسمح حالته بالانتقال إلى «مع مندوب التوصيل»، كطرد بانتظار الاستلام أو ما زال في مرحلة الاستلام، يعطي500والكودserver_errorفي كل مرة؛ فافحصstatus_codeللطرد قبل استدعاء التعيين.اعتمد على error.code
استخدم
error.codeلتحديد ما يفعله برنامجك، وerror.fieldsلإبراز الحقول، وerror.messageلعرضه على المستخدم فقط.انتظر عند 429
توقّف مدة
error.retry_afterثانية، أو المدة الواردة في ترويسةRetry-Afterعندما يردّ الحد العام أو أحد حدود المسارات (بلاerror.code)، ثم أعد المحاولة.اجعل إعادة محاولة الإنشاء آمنة
بعد انتهاء المهلة أو
500عند إنشاء طرد، ابحث عن الطرد قبل إنشائه من جديد: بـGET /parcels/{reference}في واجهة التاجر، وبـGET /parcels?merchant_id=<id>&reference=<reference>في واجهة الشركة (فـGET /parcels/{reference}وحده هناك يبحث في طرود كل تجّارك وقد يُرجع طرد تاجر آخر). وفي واجهة التاجر يُرجع إرسالreferenceنفسه الطرد الموجود مع"duplicate": true.
أخطاء شائعة#
- اعتبار
200مع"duplicate": trueطرداً جديداً. هو الطرد الذي أنشأته سابقاً. - توقّع
409عند تكرارreferenceفي واجهة التاجر. ذلك في واجهة الشركة؛ أما واجهة التاجر فتُرجع الطرد القديم. - إعادة محاولة
4xxدون تغيير. أصلح الطلب أولاً. - تحليل
error.message. يتغيّر مع اللغة، وبعض الرسائل بالعربية فقط. - عدم إرسال
Accept: application/json. عندها تصلك الأخطاء التي تقع قبل كود الـ API (انظر «أخطاء خارج هذا الشكل») صفحات HTML. - تجاهل
fields. فهو، عندما يوجد، يسمّي الحقل الذي فشل بالضبط.
الحدود والصلاحيات#
plan_featureوrate_limitedوapi_not_allowedتتوقف على باقتك ونوع حسابك، لا على جسم الطلب.- تُستخدم اللغتان
arوenفقط في الرسائل. - الأكواد المعلَّمة «التاجر» أو «الشركة» موجودة في تلك الواجهة وحدها.
API
POST /api/v1/parcelsPOST /api/v1/parcels/{tracking}/cancelPOST /api/company/v1/parcelsPOST /api/company/v1/parcels/{tracking}/status