OpenAPI 3.1الإصدار v1 8 نقطة نهاية · 8 حدث ويب هوك

واجهة شركة التوصيل في Delivery Syria

قراءة تجّارك ومناديبك وطرودك، وإنشاء طرود لتجّارك، وتعيين المناديب، وتحديث الحالات.

استورد هذا الملف في Postman أو Insomnia أو أي أداة تدعم OpenAPI 3.1، أو أعطِ الأداة العنوان الظاهر أدناه. الخادم في الملف نسبي (بلا نطاق): بعد الاستيراد اضبط عنوان منصتك على أنه العنوان الأساسي.

URL
https://deliverysyria.com/docs/api/company-v1.json

نظرة عامة

تتيح واجهة الشركة (/api/company/v1) لنظام شركة التوصيل قراءة تجّارها ومناديبها وطرودها، وإنشاء طرود لتجّارها، وتعيين المناديب، وتحديث حالات الطرود. كل شيء مقيّد بشركتك. كل استدعاء يُوثَّق بمفتاح API في ترويسة Bearer، وكل ردّ بصيغة JSON وبالغلاف نفسه: {"success": true, "data": ...} (مع meta في القوائم المرقّمة) أو {"success": false, "error": {"code", "message"}}. أرسل دائماً Accept: application/json.

كُتب هذا المستند من كود التطبيق، وتفحصه اختبارات آلية مقابل المسارات وقواعد التحقق وأشكال الردود الفعلية. وهو يصف ما يفعله الكود فقط. ولا توجد ترويسة للإصدار ولا دعم لـ Idempotency-Key ولا لوحة «جرّب الآن»، ولا تتضمن واجهة الشركة مسارات لإدارة روابط الويب هوك (استخدم لوحة الشركة). وحدود الطلبات موصوفة في كل عملية: طلبات في الدقيقة لكل عنوان IP، إضافة إلى حدود باقتك.

للأدلة والشروحات اقرأ مقالات المطورين في مركز التوثيق.

العنوان الأساسي
https://YOUR_DOMAIN/api/company/v1 استبدل YOUR_DOMAIN بعنوان منصتك.
المصادقة

مفتاح الـ API الخاص بشركة التوصيل لديك في ترويسة Authorization: Authorization: Bearer YOUR_COMPANY_API_KEY. تُقرأ هذه الترويسة فقط؛ والمفتاح في الاستعلام أو في الجسم يُتجاهل. ينشئ مدير الشركة المفتاح من لوحة الشركة (الربط والـ API). وهو يعمل على /api/company/v1 فقط: مفتاح التاجر يعطي invalid_key. أما مفاتيح WooCommerce التي تبدأ بـ ck_ فهي شيء مختلف ولا تعمل هنا أبداً.

HTTP
Authorization: Bearer YOUR_COMPANY_API_KEY
Accept-Language

لغة رسائل الأخطاء والتسميات (تسمية الحالة وملاحظات الأحداث والأسماء). إذا بدأت القيمة بـ en جاء الرد بالإنجليزية، وأي قيمة أخرى أو غياب الترويسة يعطي العربية. الحقول المقروءة آلياً لا تتغير أبداً.

حدود الطلبات

تُطبَّق ثلاث طبقات. (1) حدّ عام قدره 60 طلباً في الدقيقة لكل عنوان IP على كل طلب /api. (2) حدود المسارات، وتُحتسب لكل عنوان IP على عدّاد واحد مشترك: حدّ المجموعة 300 في الدقيقة، و120 لـ POST /parcels؛ ولأن طلب POST /parcels يُحسب على المجموعة وعلى المسار معاً، فلا يستطيع عنوان IP واحد إنشاء أكثر من نحو 60 طرداً في الدقيقة. (3) حدود الباقة لكل شركة في الدقيقة وفي اليوم (429 rate_limited مع Retry-After). وتُذكر الحدود المطبّقة على كل عملية في العملية نفسها.

لا توجد لوحة «جرّب الآن»

لا يتضمن هذا المرجع لوحة «جرّب الآن» ولا يرسل أي طلب من متصفحك. فذلك يعني إدخال مفتاح API حقيقي في صفحة ويب واستدعاء الواجهة الفعلية ببيانات حقيقية. اختبر بالأمثلة البرمجية ومفتاحك الخاص من خادمك أو من الطرفية.

الحساب

شركتك وباقتها واستهلاكها.

الطريقة GET /me #

جلب حساب شركتك

تُرجع شركتك وباقتها الفعّالة (مع ميزاتها) وصفوف الاستهلاك مقابل حدود الباقة. وهي أول استدعاء مناسب للتأكد من المفتاح.

الردود

200 حساب شركتك.

حساب شركتك.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

الحقلالنوع مطلوبالوصف
success boolean مطلوب

قيمة ثابتة true

data object مطلوب

حساب شركتك.

company object مطلوب

شركتك.

id integer مطلوب

معرّف الشركة.

name string | null مطلوب

اسم الشركة.

phone string | null مطلوب

هاتف الشركة.

plan object | null مطلوب

الاشتراك الفعّال، أو null إن لم يوجد.

name string | null مطلوب

اسم الباقة.

expires_at string مطلوب

انتهاء الاشتراك (YYYY-MM-DD HH:MM:SS).

features array<object> مطلوب

ميزات الباقة.

feature string مطلوب

تسمية للعرض بلغة الطلب (وقد تتضمن الحدود مثل أرقام الـ API في الدقيقة وفي اليوم).

enabled boolean مطلوب

هل تتضمنها الباقة.

usage array<object> مطلوب

الاستهلاك مقابل حدود الباقة.

name string مطلوب

ما يُعدّ، بلغة الطلب (مثل طلبات الـ API اليوم وروابط الويب هوك والتجّار).

used integer مطلوب

الكمية المستعملة.

limit integer | null مطلوب

الحدّ، أو null عند عدم وجود حد.

مثال

JSON · 200
{
  "success": true,
  "data": {
    "company": {
      "id": 3,
      "name": "Example Delivery",
      "phone": "0900000000"
    },
    "plan": {
      "name": "Example Plan",
      "expires_at": "2026-12-01 00:00:00",
      "features": [
        {
          "feature": "Company API — 120 per minute / 20,000 per day",
          "enabled": true
        }
      ]
    },
    "usage": [
      {
        "name": "API requests today",
        "used": 1240,
        "limit": 20000
      }
    ]
  }
}

401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه

402 انتهى اشتراك الشركة (subscription_expired). ردّ مشترك، انظر أدناه

403 الوصول مرفوض. ردّ مشترك، انظر أدناه

429 تجاوز حدّ الطلبات. ردّ مشترك، انظر أدناه

500 خطأ غير متوقع في الخادم. ردّ مشترك، انظر أدناه

أمثلة برمجية

curl
curl
curl -X GET "https://YOUR_DOMAIN/api/company/v1/me" \
  -H "Authorization: Bearer YOUR_COMPANY_API_KEY" \
  -H "Accept: application/json"
PHP
PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/company/v1/me");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => "GET",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer " . getenv("DS_COMPANY_API_KEY"),
        "Accept: application/json",
    ],
]);
$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if (!($body["success"] ?? false)) {
    throw new RuntimeException("$status {$body["error"]["code"]}: {$body["error"]["message"]}");
}
print_r($body["data"]);
JavaScript
JavaScript
const response = await fetch("https://YOUR_DOMAIN/api/company/v1/me", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.DS_COMPANY_API_KEY}`,
    "Accept": "application/json",
  },
});
const json = await response.json();
if (!json.success) {
  throw new Error(`${response.status} ${json.error.code}: ${json.error.message}`);
}
console.log(json.data);
Python
Python
import os
import requests

response = requests.get(
    "https://YOUR_DOMAIN/api/company/v1/me",
    headers={
        "Authorization": f"Bearer {os.environ['DS_COMPANY_API_KEY']}",
        "Accept": "application/json",
    },
    timeout=30,
)
body = response.json()
if not body["success"]:
    raise RuntimeError(f"{response.status_code} {body['error']['code']}: {body['error']['message']}")
print(body["data"])

التجّار

تجّارك وأماكن الاستلام لديهم.

الطريقة GET /merchants #

قائمة تجّارك

تجّارك مع أماكن الاستلام لديهم، مرتّبين حسب المعرّف. الرد مرقّم ويتضمن meta.

معاملات الاستعلام

الاسمالنوعمطلوبالوصف
q string اختياري

جزء من الاسم التجاري أو من رقم الجوال.

مثال Example

per_page integer اختياري

حجم الصفحة من 1 إلى 100 (الافتراضي 50). القيمة خارج المجال لا تُرفض بل تُقرَّب إلى أقرب حدّ، وتعود القيمة الفعلية في meta.per_page.

الحد الأدنى 1الحد الأقصى 100الافتراضي 50

page integer اختياري

رقم الصفحة ويبدأ من 1. القيمة غير الصالحة أو الأصغر من 1 تُعامل على أنها 1. والصفحة بعد الأخيرة تعيد قائمة فارغة.

الحد الأدنى 1الافتراضي 1

الردود

200 صفحة من التجّار.

صفحة من التجّار.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

الحقلالنوع مطلوبالوصف
success boolean مطلوب

قيمة ثابتة true

data array<object> مطلوب
id integer مطلوب

أرسله على أنه merchant_id عند إنشاء طرد.

business_name string مطلوب

الاسم التجاري.

contact_name string | null مطلوب

الشخص المسؤول.

phone string | null مطلوب

رقم الجوال.

email string | null مطلوب

البريد الإلكتروني.

active boolean مطلوب

هل التاجر فعّال.

pickup_locations array<object> مطلوب

أماكن الاستلام لدى التاجر.

id integer مطلوب

أرسله على أنه pickup_location_id.

name string | null مطلوب

اسم المكان.

address string | null مطلوب

العنوان.

phone string | null مطلوب

هاتف التواصل.

default_shop integer مطلوب

علامة الافتراضي بالقيمة 0 أو 1 (بالمعنى نفسه لـ default).

إحدى القيم: 0 1

default boolean مطلوب

تكون true لمكان الاستلام الافتراضي للتاجر.

meta Meta مطلوب

كتلة الترقيم. لا توجد روابط ولا مؤشر (cursor).

مثال

JSON · 200
{
  "success": true,
  "data": [
    {
      "id": 41,
      "business_name": "Example Shop",
      "contact_name": "Example Name",
      "phone": "0900000000",
      "email": "shop@example.com",
      "active": true,
      "pickup_locations": [
        {
          "id": 7,
          "name": "Main branch",
          "address": "Example street, building 1",
          "phone": "0900000000",
          "default_shop": 1,
          "default": true
        }
      ]
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "last_page": 1
  }
}

401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه

402 انتهى اشتراك الشركة (subscription_expired). ردّ مشترك، انظر أدناه

403 الوصول مرفوض. ردّ مشترك، انظر أدناه

429 تجاوز حدّ الطلبات. ردّ مشترك، انظر أدناه

500 خطأ غير متوقع في الخادم. ردّ مشترك، انظر أدناه

أمثلة برمجية

curl
curl
curl -X GET "https://YOUR_DOMAIN/api/company/v1/merchants?q=Example" \
  -H "Authorization: Bearer YOUR_COMPANY_API_KEY" \
  -H "Accept: application/json"
PHP
PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/company/v1/merchants?q=Example");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => "GET",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer " . getenv("DS_COMPANY_API_KEY"),
        "Accept: application/json",
    ],
]);
$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if (!($body["success"] ?? false)) {
    throw new RuntimeException("$status {$body["error"]["code"]}: {$body["error"]["message"]}");
}
print_r($body["data"]);
JavaScript
JavaScript
const response = await fetch("https://YOUR_DOMAIN/api/company/v1/merchants?q=Example", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.DS_COMPANY_API_KEY}`,
    "Accept": "application/json",
  },
});
const json = await response.json();
if (!json.success) {
  throw new Error(`${response.status} ${json.error.code}: ${json.error.message}`);
}
console.log(json.data);
Python
Python
import os
import requests

response = requests.get(
    "https://YOUR_DOMAIN/api/company/v1/merchants",
    headers={
        "Authorization": f"Bearer {os.environ['DS_COMPANY_API_KEY']}",
        "Accept": "application/json",
    },
    params={
        "q": "Example",
    },
    timeout=30,
)
body = response.json()
if not body["success"]:
    raise RuntimeError(f"{response.status_code} {body['error']['code']}: {body['error']['message']}")
print(body["data"])

المناديب

مناديبك مع حمولتهم.

الطريقة GET /deliverymen #

قائمة مناديبك

كل مناديبك مع حمولتهم الحالية. القائمة غير مرقّمة.

  • الطلب GET /api/company/v1/deliverymen
  • حدّ الطلبات في الدقيقة لكل عنوان IP 60 عاماً، و300 للواجهة كلها
  • يتطلب ميزة الباقة: الـ API (تُفحص عندما تُطبَّق الباقات على حسابك)
  • أدلة مرجع واجهة شركة التوصيل API v1

الردود

200 مناديبك.

مناديبك.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

الحقلالنوع مطلوبالوصف
success boolean مطلوب

قيمة ثابتة true

data array<object> مطلوب
id integer مطلوب

أرسله على أنه deliveryman_id.

name string | null مطلوب

اسم المندوب.

phone string | null مطلوب

رقم جوال المندوب.

active boolean مطلوب

هل حساب المندوب فعّال.

open_parcels integer مطلوب

الطرود في الحالتين «تعيين مندوب» و«إعادة جدولة التسليم» التي لها حدث لهذا المندوب: تقدير لما يحمله المندوب (ويعدّ مربع التعيين في اللوحة بالطريقة نفسها).

parcel_limit integer مطلوب

حدّ طرود المندوب (5 عند عدم ضبط حد).

online boolean مطلوب

علامة دوام المندوب (متصل بالتطبيق).

available boolean مطلوب

تكون false إذا كان المندوب غير فعّال، أو إذا كانت شركتك تشترط اتصال المناديب وهذا المندوب غير متصل.

مثال

JSON · 200
{
  "success": true,
  "data": [
    {
      "id": 5,
      "name": "Example Courier",
      "phone": "0900000001",
      "active": true,
      "open_parcels": 12,
      "parcel_limit": 50,
      "online": true,
      "available": true
    }
  ]
}

401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه

402 انتهى اشتراك الشركة (subscription_expired). ردّ مشترك، انظر أدناه

403 الوصول مرفوض. ردّ مشترك، انظر أدناه

429 تجاوز حدّ الطلبات. ردّ مشترك، انظر أدناه

500 خطأ غير متوقع في الخادم. ردّ مشترك، انظر أدناه

أمثلة برمجية

curl
curl
curl -X GET "https://YOUR_DOMAIN/api/company/v1/deliverymen" \
  -H "Authorization: Bearer YOUR_COMPANY_API_KEY" \
  -H "Accept: application/json"
PHP
PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/company/v1/deliverymen");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => "GET",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer " . getenv("DS_COMPANY_API_KEY"),
        "Accept: application/json",
    ],
]);
$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if (!($body["success"] ?? false)) {
    throw new RuntimeException("$status {$body["error"]["code"]}: {$body["error"]["message"]}");
}
print_r($body["data"]);
JavaScript
JavaScript
const response = await fetch("https://YOUR_DOMAIN/api/company/v1/deliverymen", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.DS_COMPANY_API_KEY}`,
    "Accept": "application/json",
  },
});
const json = await response.json();
if (!json.success) {
  throw new Error(`${response.status} ${json.error.code}: ${json.error.message}`);
}
console.log(json.data);
Python
Python
import os
import requests

response = requests.get(
    "https://YOUR_DOMAIN/api/company/v1/deliverymen",
    headers={
        "Authorization": f"Bearer {os.environ['DS_COMPANY_API_KEY']}",
        "Accept": "application/json",
    },
    timeout=30,
)
body = response.json()
if not body["success"]:
    raise RuntimeError(f"{response.status_code} {body['error']['code']}: {body['error']['message']}")
print(body["data"])

الطرود

عرض الطرود وقراءتها، وإنشاء طرد لتاجر، وتعيين مندوب، وتحديث الحالة.

الطريقة GET /parcels #

عرض طرودك

تعرض طرود شركتك الأحدث أولاً (حسب المعرّف) دون events. الرد مرقّم ويتضمن meta.

معاملات الاستعلام

الاسمالنوعمطلوبالوصف
merchant_id integer اختياري

طرود هذا التاجر فقط.

مثال 41

deliveryman_id integer اختياري

الطرود التي يحملها هذا المندوب فقط.

مثال 5

reference string اختياري

تطابق تام مع مرجع التاجر.

مثال ORDER-1043

from string (date) اختياري

أول يوم إنشاء YYYY-MM-DD شاملاً. لا يُتحقق من الصيغة: استخدم هذه الصيغة فقط.

مثال 2026-01-01

to string (date) اختياري

آخر يوم إنشاء YYYY-MM-DD شاملاً. لا يُتحقق من الصيغة: استخدم هذه الصيغة فقط.

مثال 2026-01-31

updated_since string اختياري

الطرود المحدَّثة في هذا الوقت أو بعده فقط، بصيغة YYYY-MM-DD HH:MM:SS. مفيد للمزامنة الدورية.

مثال 2026-01-01 10:00:00

stage string اختياري

تصفية حسب المرحلة. وعلى خلاف واجهة التاجر تُرفض القيمة المجهولة بالرمز 422 validation_failed. تطابق processing رموز الحالة 2 و3 و4 و5 و6 و19 فقط، فبعض الطرود التي مرحلتها processing لا يعيدها هذا الفلتر. وawaiting_funds غير مقبولة.

إحدى القيم: pending processing out_for_delivery delivered partially_delivered returning returned

مثال processing

per_page integer اختياري

حجم الصفحة من 1 إلى 100 (الافتراضي 20). القيمة خارج المجال لا تُرفض بل تُقرَّب إلى أقرب حدّ، وتعود القيمة الفعلية في meta.per_page.

الحد الأدنى 1الحد الأقصى 100الافتراضي 20

page integer اختياري

رقم الصفحة ويبدأ من 1. القيمة غير الصالحة أو الأصغر من 1 تُعامل على أنها 1. والصفحة بعد الأخيرة تعيد قائمة فارغة.

الحد الأدنى 1الافتراضي 1

الردود

200 صفحة من الطرود.

صفحة من الطرود.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

الحقلالنوع مطلوبالوصف
success boolean مطلوب

قيمة ثابتة true

data array<Parcel> مطلوب
meta Meta مطلوب

كتلة الترقيم. لا توجد روابط ولا مؤشر (cursor).

مثال

JSON · 200
{
  "success": true,
  "data": [
    {
      "id": 1043,
      "tracking_number": "DS-000000",
      "reference": "ORDER-1043",
      "stage": "out_for_delivery",
      "status_code": 7,
      "status_label": "Delivery Man Assign",
      "company_id": 3,
      "company_name": "Example Delivery",
      "external_tracking_number": null,
      "recipient": {
        "name": "Example Name",
        "phone": "0900000000",
        "governorate": "Damascus",
        "address": "Example street, building 1",
        "lat": null,
        "lng": null
      },
      "cod_amount": 25,
      "cod_collected": 0,
      "weight_kg": 1.5,
      "charges": {
        "delivery_fee": 6,
        "platform_fee": 1
      },
      "delivery_attempts": 0,
      "note": null,
      "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
      "created_at": "2026-01-01T10:00:00+00:00",
      "updated_at": "2026-01-01T12:10:00+00:00",
      "merchant": {
        "id": 41,
        "name": "Example Shop"
      },
      "deliveryman": {
        "id": 5,
        "name": "Example Courier"
      }
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "last_page": 1
  }
}

401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه

402 انتهى اشتراك الشركة (subscription_expired). ردّ مشترك، انظر أدناه

403 الوصول مرفوض. ردّ مشترك، انظر أدناه

422 validation_failed:

validation_failed: قيمة stage مجهولة. تسرد الرسالة القيم المتاحة؛ ولا يوجد كائن fields.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Unknown stage

JSON · 422
{
  "success": false,
  "error": {
    "code": "validation_failed",
    "message": "stage is unknown. Available: pending، processing، out_for_delivery، delivered، partially_delivered، returning، returned"
  }
}

429 تجاوز حدّ الطلبات. ردّ مشترك، انظر أدناه

500 خطأ غير متوقع في الخادم. ردّ مشترك، انظر أدناه

أمثلة برمجية

curl
curl
curl -X GET "https://YOUR_DOMAIN/api/company/v1/parcels?merchant_id=41&deliveryman_id=5&reference=ORDER-1043&from=2026-01-01" \
  -H "Authorization: Bearer YOUR_COMPANY_API_KEY" \
  -H "Accept: application/json"
PHP
PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/company/v1/parcels?merchant_id=41&deliveryman_id=5&reference=ORDER-1043&from=2026-01-01");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => "GET",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer " . getenv("DS_COMPANY_API_KEY"),
        "Accept: application/json",
    ],
]);
$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if (!($body["success"] ?? false)) {
    throw new RuntimeException("$status {$body["error"]["code"]}: {$body["error"]["message"]}");
}
print_r($body["data"]);
JavaScript
JavaScript
const response = await fetch("https://YOUR_DOMAIN/api/company/v1/parcels?merchant_id=41&deliveryman_id=5&reference=ORDER-1043&from=2026-01-01", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.DS_COMPANY_API_KEY}`,
    "Accept": "application/json",
  },
});
const json = await response.json();
if (!json.success) {
  throw new Error(`${response.status} ${json.error.code}: ${json.error.message}`);
}
console.log(json.data);
Python
Python
import os
import requests

response = requests.get(
    "https://YOUR_DOMAIN/api/company/v1/parcels",
    headers={
        "Authorization": f"Bearer {os.environ['DS_COMPANY_API_KEY']}",
        "Accept": "application/json",
    },
    params={
        "merchant_id": "41",
        "deliveryman_id": "5",
        "reference": "ORDER-1043",
        "from": "2026-01-01",
    },
    timeout=30,
)
body = response.json()
if not body["success"]:
    raise RuntimeError(f"{response.status_code} {body['error']['code']}: {body['error']['message']}")
print(body["data"])

الطريقة POST /parcels #

إنشاء طرد لأحد تجّارك

تنشئ طرداً نيابةً عن أحد تجّارك. تستخدم الأجرة تسعير شركتك ولا يُؤخذ شيء من محافظ المنصة. المرجع reference نفسه للتاجر نفسه يعطي 409 duplicate_reference أياً كانت حالة الطرد السابق (اعتبره «أُنشئ من قبل»)؛ وبلا reference ينشئ كل استدعاء طرداً جديداً. ويلزم إرسال المحافظة أو الإحداثيات بحسب آلية التسعير لدى شركتك.

جسم الطلب

application/json · مطلوب

الحقلالنوع مطلوبالوصف
merchant_id integer مطلوب

التاجر الذي يُنشأ الطرد له: قيمة id من GET /merchants. يجب أن يكون تاجراً لدى شركتك.

recipient object مطلوب

المستلم. يمكن بدلاً من ذلك إرسال كل حقل مسطحاً في المستوى الأعلى (customer_name وcustomer_phone وcustomer_address وcustomer_city وlat وlong)؛ والشكل المتداخل هو الموثَّق.

name string مطلوب

اسم المستلم.

الحد الأقصى للطول 191

phone string مطلوب

رقم هاتف المستلم: أرقام ومسافات و+ و- وأقواس، من 6 إلى 30 محرفاً.

الحد الأقصى للطول 30النمط ^[+0-9\s\-()]{6,30}$

address string مطلوب

عنوان المستلم.

الحد الأقصى للطول 1000

governorate string اختياري

اسم المحافظة (name بالإنجليزية أو name_ar بالعربية من GET /governorates). وإن أرسلت المعرّف فأرسله نصاً مثل "3" لأن الرقم في JSON يُرفض. مطلوب للتسعير حسب المحافظة، وإلا تحاول المنصة استنتاجها من العنوان ثم من الإحداثيات.

الحد الأقصى للطول 120يُقبل أيضاً باسم customer_city, city

lat number اختياري

خط عرض موقع المستلم. مطلوب للتسعير حسب المسافة (per_km وkm_kg).

الحد الأدنى -90الحد الأقصى 90

lng number اختياري

خط طول موقع المستلم. مطلوب للتسعير حسب المسافة (per_km وkm_kg).

الحد الأدنى -180الحد الأقصى 180يُقبل أيضاً باسم long

reference string اختياري

مرجع التاجر الخاص (رقم الطلب) بحد أقصى 191 محرفاً. المرجع الذي استخدمه التاجر من قبل يعطي 409 duplicate_reference؛ وعلى خلاف واجهة التاجر لا يُرجَع الطرد القديم.

الحد الأقصى للطول 191يُقبل أيضاً باسم invoice_no

cod_amount number اختياري

مبلغ التحصيل عند الاستلام الذي يدفعه المستلم، من 0 إلى 100,000,000 دولار أمريكي (يُحوَّل المبلغ بغير الدولار إلى الدولار بسعر المنصة قبل فحص الحد). القيمة 0 تعني مدفوع مسبقاً.

الحد الأدنى 0الحد الأقصى 100000000الافتراضي 0

currency string اختياري

رمز عملة cod_amount (لا فرق بين الأحرف الكبيرة والصغيرة). يُخزَّن المبلغ بالدولار، لذا يكون cod_amount في كائنات الطرد بالدولار دائماً. وقد لا تقبل الشركة إلا بعض العملات. وغياب سعر الصرف يعطي 422.

إحدى القيم: USD SYP SAR AED QAR KWD JOD IQD EGP LBP TRY EUR

الافتراضي USDيُقبل أيضاً باسم cod_currency

weight number اختياري

الوزن بالكيلوغرام من 0.01 إلى 1000. الافتراضي 1. في التسعير الداخلي يُقرَّب الوزن إلى كيلوغرام كامل (الحد الأدنى 1).

الحد الأدنى 0.01الحد الأقصى 1000الافتراضي 1يُقبل أيضاً باسم weight_kg

pickup_location_id integer اختياري

أحد أماكن الاستلام لدى التاجر (pickup_locations في GET /merchants). يُستخدم المكان الافتراضي للتاجر عند عدم الإرسال. وتُبلَّغ الأخطاء على الحقل shop_id.

يُقبل أيضاً باسم shop_id

note string اختياري

ملاحظة لشركة التوصيل بحد أقصى 2000 محرف.

الحد الأقصى للطول 2000

shipping_paid_by string اختياري

من يدفع أجرة الشحن، لشركات الشحن التي تدعم الاختيار: sender (المرسل) أو customer (المستلم) أو included_in_cod (ضمن مبلغ التحصيل).

إحدى القيم: sender customer included_in_cod

مثال

JSON
{
  "merchant_id": 41,
  "reference": "ORDER-1043",
  "recipient": {
    "name": "Example Name",
    "phone": "0900000000",
    "governorate": "Damascus",
    "address": "Example street, building 1"
  },
  "cod_amount": 25,
  "weight": 1
}

الردود

201 تم إنشاء الطرد.

تم إنشاء الطرد.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

الحقلالنوع مطلوبالوصف
success boolean مطلوب

قيمة ثابتة true

data Parcel مطلوب

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

مثال

JSON · 201
{
  "success": true,
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "processing",
    "status_code": 5,
    "status_label": "Received Warehouse",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 0,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": null
  }
}

401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه

402 insufficient_balance:

insufficient_balance: الرصيد لا يكفي لأجرة الطرد. subscription_expired: انتهى اشتراك شركتك.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Balance too low

JSON · 402
{
  "success": false,
  "error": {
    "code": "insufficient_balance",
    "message": "Insufficient wallet balance. Required: 7.00, available: 2.00"
  }
}

مثال — Subscription ended

JSON · 402
{
  "success": false,
  "error": {
    "code": "subscription_expired",
    "message": "Company subscription expired — renew the subscription from the company dashboard."
  }
}

403 الوصول مرفوض. ردّ مشترك، انظر أدناه

409 duplicate_reference:

duplicate_reference: لدى التاجر طرد بالمرجع reference نفسه. اجلبه بـ GET /parcels?merchant_id=<id>&reference=<reference> (أما GET /parcels/{reference} وحده فيبحث بين كل تجّارك).

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Reference already used

JSON · 409
{
  "success": false,
  "error": {
    "code": "duplicate_reference",
    "message": "A parcel with the same reference already exists for this merchant — use GET /parcels/ORDER-1043."
  }
}
422 validation_failed:

validation_failed: merchant_id مفقود أو ليس تاجراً لدى شركتك (الخطأ على الحقل merchant_id)، أو حقل آخر مفقود أو خاطئ. carrier_error: تعذّرت معالجة الطرد لدى شركة الشحن.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Unknown merchant

JSON · 422
{
  "success": false,
  "error": {
    "code": "validation_failed",
    "message": "merchant_id is required and must be a merchant of your company (GET /merchants).",
    "fields": {
      "merchant_id": [
        "Merchant not found in your company."
      ]
    }
  }
}

مثال — Carrier refused

JSON · 422
{
  "success": false,
  "error": {
    "code": "carrier_error",
    "message": "Localized message from the carrier."
  }
}

429 تجاوز حدّ الطلبات. ردّ مشترك، انظر أدناه

500 خطأ غير متوقع في الخادم. ردّ مشترك، انظر أدناه

أمثلة برمجية

curl
curl
curl -X POST "https://YOUR_DOMAIN/api/company/v1/parcels" \
  -H "Authorization: Bearer YOUR_COMPANY_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "merchant_id": 41,
  "reference": "ORDER-1043",
  "recipient": {
    "name": "Example Name",
    "phone": "0900000000",
    "governorate": "Damascus",
    "address": "Example street, building 1"
  },
  "cod_amount": 25,
  "weight": 1
}'
PHP
PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/company/v1/parcels");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => "POST",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer " . getenv("DS_COMPANY_API_KEY"),
        "Accept: application/json",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS     => json_encode([
        'merchant_id' => 41,
        'reference' => 'ORDER-1043',
        'recipient' => [
            'name' => 'Example Name',
            'phone' => '0900000000',
            'governorate' => 'Damascus',
            'address' => 'Example street, building 1',
        ],
        'cod_amount' => 25,
        'weight' => 1,
    ]),
]);
$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if (!($body["success"] ?? false)) {
    throw new RuntimeException("$status {$body["error"]["code"]}: {$body["error"]["message"]}");
}
print_r($body["data"]);
JavaScript
JavaScript
const response = await fetch("https://YOUR_DOMAIN/api/company/v1/parcels", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.DS_COMPANY_API_KEY}`,
    "Accept": "application/json",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "merchant_id": 41,
    "reference": "ORDER-1043",
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1"
    },
    "cod_amount": 25,
    "weight": 1
  }),
});
const json = await response.json();
if (!json.success) {
  throw new Error(`${response.status} ${json.error.code}: ${json.error.message}`);
}
console.log(json.data);
Python
Python
import os
import requests

response = requests.post(
    "https://YOUR_DOMAIN/api/company/v1/parcels",
    headers={
        "Authorization": f"Bearer {os.environ['DS_COMPANY_API_KEY']}",
        "Accept": "application/json",
    },
    json={
        "merchant_id": 41,
        "reference": "ORDER-1043",
        "recipient": {
            "name": "Example Name",
            "phone": "0900000000",
            "governorate": "Damascus",
            "address": "Example street, building 1",
        },
        "cod_amount": 25,
        "weight": 1,
    },
    timeout=30,
)
body = response.json()
if not body["success"]:
    raise RuntimeError(f"{response.status_code} {body['error']['code']}: {body['error']['message']}")
print(body["data"])

الطريقة GET /parcels/{tracking} #

جلب طرد واحد مع أحداثه

تأخذ رقم تتبع أو reference وتُرجع الطرد مع events بترتيب زمني.

  • الطلب GET /api/company/v1/parcels/{tracking}
  • حدّ الطلبات في الدقيقة لكل عنوان IP 60 عاماً، و300 للواجهة كلها
  • يتطلب ميزة الباقة: الـ API (تُفحص عندما تُطبَّق الباقات على حسابك)
  • أدلة مرجع واجهة شركة التوصيل API v1

معاملات المسار

الاسمالنوعمطلوبالوصف
tracking string مطلوب

رقم التتبع، أو reference الذي أرسله التاجر (يُعتمد أحدث تطابق بين طرود كل تجّارك، فإن تشارك تاجران قيمة المرجع نفسها قد تحصل على طرد التاجر الآخر: فضّل رقم التتبع).

مثال DS-000000

الردود

200 الطرد مع أحداثه.

الطرد مع أحداثه.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

الحقلالنوع مطلوبالوصف
success boolean مطلوب

قيمة ثابتة true

data object مطلوب

كائن الطرد مع تاريخه (events). يُرجَع عند جلب طرد واحد.

يتضمن كل حقول Parcel
events array<object> مطلوب

تاريخ الطرد بترتيب زمني. يظهر فقط عند جلب طرد واحد.

status_code integer مطلوب

رمز الحالة الداخلي الدقيق لتلك الخطوة.

stage string مطلوب

المرحلة المبسطة لتلك الخطوة.

إحدى القيم: pending processing out_for_delivery delivered partially_delivered returning returned

status_label string مطلوب

تسمية الحالة بلغة الطلب.

note string | null مطلوب

ملاحظة نصية مسجّلة مع الحدث.

at string (date-time) | null مطلوب

وقت الحدث (ISO 8601 مع فرق التوقيت عن UTC).

مثال

JSON · 200
{
  "success": true,
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "out_for_delivery",
    "status_code": 7,
    "status_label": "Delivery Man Assign",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 0,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": {
      "id": 5,
      "name": "Example Courier"
    },
    "events": [
      {
        "status_code": 1,
        "stage": "pending",
        "status_label": "Pending",
        "note": "Parcel created (api)",
        "at": "2026-01-01T10:00:00+00:00"
      },
      {
        "status_code": 5,
        "stage": "processing",
        "status_label": "Received Warehouse",
        "note": null,
        "at": "2026-01-01T10:00:01+00:00"
      }
    ]
  }
}

401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه

402 انتهى اشتراك الشركة (subscription_expired). ردّ مشترك، انظر أدناه

403 الوصول مرفوض. ردّ مشترك، انظر أدناه

404 not_found:

not_found: لا يوجد طرد بهذا الرقم أو المرجع لدى شركتك.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Unknown parcel

JSON · 404
{
  "success": false,
  "error": {
    "code": "not_found",
    "message": "No parcel with this number in your company."
  }
}

429 تجاوز حدّ الطلبات. ردّ مشترك، انظر أدناه

500 خطأ غير متوقع في الخادم. ردّ مشترك، انظر أدناه

أمثلة برمجية

curl
curl
curl -X GET "https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000" \
  -H "Authorization: Bearer YOUR_COMPANY_API_KEY" \
  -H "Accept: application/json"
PHP
PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => "GET",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer " . getenv("DS_COMPANY_API_KEY"),
        "Accept: application/json",
    ],
]);
$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if (!($body["success"] ?? false)) {
    throw new RuntimeException("$status {$body["error"]["code"]}: {$body["error"]["message"]}");
}
print_r($body["data"]);
JavaScript
JavaScript
const response = await fetch("https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000", {
  method: "GET",
  headers: {
    "Authorization": `Bearer ${process.env.DS_COMPANY_API_KEY}`,
    "Accept": "application/json",
  },
});
const json = await response.json();
if (!json.success) {
  throw new Error(`${response.status} ${json.error.code}: ${json.error.message}`);
}
console.log(json.data);
Python
Python
import os
import requests

response = requests.get(
    "https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000",
    headers={
        "Authorization": f"Bearer {os.environ['DS_COMPANY_API_KEY']}",
        "Accept": "application/json",
    },
    timeout=30,
)
body = response.json()
if not body["success"]:
    raise RuntimeError(f"{response.status_code} {body['error']['code']}: {body['error']['message']}")
print(body["data"])

الطريقة POST /parcels/{tracking}/assign #

تعيين مندوب

تعيّن مندوباً من مناديب شركتك. عيّن الطرود الموجودة في المستودع أو المركز (الحالة «مستلم في المستودع» أو «مستلم في المركز») أو المعيّنة أصلاً. والطرد الذي مع المندوب نفسه (الحالة «تعيين مندوب» أو «إعادة جدولة التسليم») يُرجع دون تغيير. والطرد الذي لا انتقال في حالته إلى «تعيين مندوب»، كالمعلّق أو الذي ما زال في الاستلام، يرفضه مسار العمل وتردّ الواجهة 500 server_error: تحقق من status_code أولاً. وإذا كانت شركتك تشترط اتصال المناديب وهذا المندوب غير متصل تحصل على 422 على الحقل delivery_man_id.

معاملات المسار

الاسمالنوعمطلوبالوصف
tracking string مطلوب

رقم التتبع، أو reference الذي أرسله التاجر (يُعتمد أحدث تطابق بين طرود كل تجّارك، فإن تشارك تاجران قيمة المرجع نفسها قد تحصل على طرد التاجر الآخر: فضّل رقم التتبع).

مثال DS-000000

جسم الطلب

application/json · مطلوب

الحقلالنوع مطلوبالوصف
deliveryman_id integer مطلوب

المندوب: قيمة id من GET /deliverymen. يجب أن يكون أحد مناديبك.

note string اختياري

ملاحظة اختيارية تُسجَّل مع التعيين.

force boolean اختياري

أرسل true لتجاوز حدّ طرود المندوب.

مثال

JSON
{
  "deliveryman_id": 5,
  "note": "Call before arriving",
  "force": false
}

الردود

200 الطرد بعد التعيين.

الطرد بعد التعيين.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

الحقلالنوع مطلوبالوصف
success boolean مطلوب

قيمة ثابتة true

data Parcel مطلوب

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

مثال

JSON · 200
{
  "success": true,
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "out_for_delivery",
    "status_code": 7,
    "status_label": "Delivery Man Assign",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 0,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": {
      "id": 5,
      "name": "Example Courier"
    }
  }
}

401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه

402 انتهى اشتراك الشركة (subscription_expired). ردّ مشترك، انظر أدناه

403 الوصول مرفوض. ردّ مشترك، انظر أدناه

404 not_found:

not_found: لا يوجد طرد بهذا الرقم لدى شركتك.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Unknown parcel

JSON · 404
{
  "success": false,
  "error": {
    "code": "not_found",
    "message": "No parcel with this number in your company."
  }
}
409 deliveryman_full:

deliveryman_full: يحمل المندوب أصلاً الحد الأقصى من الطرود المفتوحة. أرسل force: true لتجاوز الحد.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Courier full

JSON · 409
{
  "success": false,
  "error": {
    "code": "deliveryman_full",
    "message": "The courier has reached the parcel limit (50 / 50 undelivered). Send force=true to bypass the limit."
  }
}
422 validation_failed:

validation_failed: deliveryman_id مفقود أو ليس أحد مناديبك (الرسالة فقط دون fields)، أو المندوب غير متصل (الحقل delivery_man_id).

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Unknown courier

JSON · 422
{
  "success": false,
  "error": {
    "code": "validation_failed",
    "message": "deliveryman_id is required and must be a courier of your company (GET /deliverymen)."
  }
}

429 تجاوز حدّ الطلبات. ردّ مشترك، انظر أدناه

500 خطأ غير متوقع في الخادم. ردّ مشترك، انظر أدناه

أمثلة برمجية

curl
curl
curl -X POST "https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000/assign" \
  -H "Authorization: Bearer YOUR_COMPANY_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "deliveryman_id": 5,
  "note": "Call before arriving",
  "force": false
}'
PHP
PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000/assign");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => "POST",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer " . getenv("DS_COMPANY_API_KEY"),
        "Accept: application/json",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS     => json_encode([
        'deliveryman_id' => 5,
        'note' => 'Call before arriving',
        'force' => false,
    ]),
]);
$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if (!($body["success"] ?? false)) {
    throw new RuntimeException("$status {$body["error"]["code"]}: {$body["error"]["message"]}");
}
print_r($body["data"]);
JavaScript
JavaScript
const response = await fetch("https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000/assign", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.DS_COMPANY_API_KEY}`,
    "Accept": "application/json",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "deliveryman_id": 5,
    "note": "Call before arriving",
    "force": false
  }),
});
const json = await response.json();
if (!json.success) {
  throw new Error(`${response.status} ${json.error.code}: ${json.error.message}`);
}
console.log(json.data);
Python
Python
import os
import requests

response = requests.post(
    "https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000/assign",
    headers={
        "Authorization": f"Bearer {os.environ['DS_COMPANY_API_KEY']}",
        "Accept": "application/json",
    },
    json={
        "deliveryman_id": 5,
        "note": "Call before arriving",
        "force": False,
    },
    timeout=30,
)
body = response.json()
if not body["success"]:
    raise RuntimeError(f"{response.status_code} {body['error']['code']}: {body['error']['message']}")
print(body["data"])

الطريقة POST /parcels/{tracking}/status #

تحديث حالة طرد

تطبّق تغيير حالة عبر مسار عمل الطرد: received أو deliver أو partial أو fail أو reschedule أو returned. والطرود المرسلة إلى شركة شحن خارجية لا يمكن تغييرها هنا (409 not_allowed). والتغيير الذي لا يسمح به مسار العمل، أو collected الأكبر من مبلغ التحصيل، يعطي 409 invalid_transition مع السبب في الرسالة. لا تسجّل الطرد مسلَّماً قبل تعيين مندوب.

معاملات المسار

الاسمالنوعمطلوبالوصف
tracking string مطلوب

رقم التتبع، أو reference الذي أرسله التاجر (يُعتمد أحدث تطابق بين طرود كل تجّارك، فإن تشارك تاجران قيمة المرجع نفسها قد تحصل على طرد التاجر الآخر: فضّل رقم التتبع).

مثال DS-000000

جسم الطلب

application/json · مطلوب

الحقلالنوع مطلوبالوصف
action string مطلوب

التغيير المطلوب: received (مستلم في المستودع) أو deliver (تم التسليم) أو partial (تسليم جزئي؛ collected مطلوب) أو fail (إرجاع إلى المندوب، المرحلة returning) أو reschedule (عودة إلى المستودع لتوزيع جديد وتُحسب محاولة) أو returned (استلم التاجر المرتجع، نهائي).

إحدى القيم: received deliver partial fail reschedule returned

collected number اختياري

المبلغ المحصَّل بالدولار. مطلوب مع partial؛ ولا يجوز أن يتجاوز مبلغ التحصيل.

الحد الأدنى 0

note string اختياري

ملاحظة اختيارية تُسجَّل مع التغيير.

مثال

JSON
{
  "action": "partial",
  "collected": 15,
  "note": "One item returned"
}

الردود

200 الطرد بعد التغيير.

الطرد بعد التغيير.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

الحقلالنوع مطلوبالوصف
success boolean مطلوب

قيمة ثابتة true

data Parcel مطلوب

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

مثال

JSON · 200
{
  "success": true,
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "delivered",
    "status_code": 9,
    "status_label": "Delivered",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 25,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": {
      "id": 5,
      "name": "Example Courier"
    }
  }
}

401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه

402 انتهى اشتراك الشركة (subscription_expired). ردّ مشترك، انظر أدناه

403 الوصول مرفوض. ردّ مشترك، انظر أدناه

404 not_found:

not_found: لا يوجد طرد بهذا الرقم لدى شركتك.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Unknown parcel

JSON · 404
{
  "success": false,
  "error": {
    "code": "not_found",
    "message": "No parcel with this number in your company."
  }
}
409 not_allowed:

not_allowed: الطرد لدى شركة شحن خارجية هي التي تتحكم بحالته. invalid_transition: الإجراء لا يناسب الحالة الحالية، أو collected أعلى من المسموح.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — External carrier

JSON · 409
{
  "success": false,
  "error": {
    "code": "not_allowed",
    "message": "This parcel is with an external shipping company — its status updates from them automatically."
  }
}

مثال — Wrong status

JSON · 409
{
  "success": false,
  "error": {
    "code": "invalid_transition",
    "message": "Localized text that names the action, the current status and the reason."
  }
}
422 validation_failed:

validation_failed: action مجهول (الرسالة فقط)، أو partial دون collected رقمي (الحقل collected).

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Missing collected amount

JSON · 422
{
  "success": false,
  "error": {
    "code": "validation_failed",
    "message": "Partial delivery requires collected (the amount collected).",
    "fields": {
      "collected": [
        "Partial delivery requires collected (the amount collected)."
      ]
    }
  }
}

429 تجاوز حدّ الطلبات. ردّ مشترك، انظر أدناه

500 خطأ غير متوقع في الخادم. ردّ مشترك، انظر أدناه

أمثلة برمجية

curl
curl
curl -X POST "https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000/status" \
  -H "Authorization: Bearer YOUR_COMPANY_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
  "action": "partial",
  "collected": 15,
  "note": "One item returned"
}'
PHP
PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000/status");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => "POST",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer " . getenv("DS_COMPANY_API_KEY"),
        "Accept: application/json",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS     => json_encode([
        'action' => 'partial',
        'collected' => 15,
        'note' => 'One item returned',
    ]),
]);
$body   = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if (!($body["success"] ?? false)) {
    throw new RuntimeException("$status {$body["error"]["code"]}: {$body["error"]["message"]}");
}
print_r($body["data"]);
JavaScript
JavaScript
const response = await fetch("https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000/status", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.DS_COMPANY_API_KEY}`,
    "Accept": "application/json",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "action": "partial",
    "collected": 15,
    "note": "One item returned"
  }),
});
const json = await response.json();
if (!json.success) {
  throw new Error(`${response.status} ${json.error.code}: ${json.error.message}`);
}
console.log(json.data);
Python
Python
import os
import requests

response = requests.post(
    "https://YOUR_DOMAIN/api/company/v1/parcels/DS-000000/status",
    headers={
        "Authorization": f"Bearer {os.environ['DS_COMPANY_API_KEY']}",
        "Accept": "application/json",
    },
    json={
        "action": "partial",
        "collected": 15,
        "note": "One item returned",
    },
    timeout=30,
)
body = response.json()
if not body["success"]:
    raise RuntimeError(f"{response.status_code} {body['error']['code']}: {body['error']['message']}")
print(body["data"])

الكائنات

كائنات تُرجعها عدة نقاط نهاية وأحداث ويب هوك. يوصَف كل منها مرة واحدة هنا، وتحيل إليه الجداول الأخرى.

Meta #

كتلة الترقيم. لا توجد روابط ولا مؤشر (cursor).

الحقلالنوع مطلوبالوصف
page integer مطلوب

الصفحة الحالية.

per_page integer مطلوب

حجم الصفحة الفعلي.

total integer مطلوب

عدد السجلات بعد تطبيق الفلاتر.

last_page integer مطلوب

عدد الصفحات (1 عند عدم وجود نتائج).

Parcel #

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

الحقلالنوع مطلوبالوصف
id integer مطلوب

معرّف الطرد.

tracking_number string مطلوب

رقم التتبع. استخدمه في مسارات {tracking} وفي صفحة التتبع العامة.

reference string | null مطلوب

مرجعك الخاص (رقم الطلب) المرسل عند الإنشاء.

stage string مطلوب

حالة مبسطة وثابتة. يفضّل الاعتماد عليها بدل status_code في منطق برنامجك: awaiting_funds (محفوظ بانتظار رصيد المحفظة)، وpending (الحالة 1)، وout_for_delivery (7 و8)، وdelivered (9)، وpartially_delivered (32)، وreturning (11 و12 و24 و26 و27)، وreturned (13 و30)، وprocessing (كل حالة أخرى).

إحدى القيم: pending processing out_for_delivery delivered partially_delivered returning returned awaiting_funds

status_code integer مطلوب

رمز الحالة الداخلي الدقيق (مثلاً 1 معلّق، 5 مستلم في المستودع، 7 تعيين مندوب، 9 تم التسليم، 13 رُدّ للتاجر، 32 تسليم جزئي).

status_label string مطلوب

تسمية الحالة بلغة الطلب.

company_id integer مطلوب

شركة التوصيل أو الشحن التي تتولى الطرد.

company_name string | null مطلوب

اسم تلك الشركة.

external_tracking_number string | null مطلوب

رقم التتبع لدى شركة الشحن الخارجية إن أُرسل الطرد إليها.

recipient object مطلوب

مستلم الطرد.

name string | null مطلوب

اسم المستلم.

phone string | null مطلوب

هاتف المستلم.

governorate string | null مطلوب

محافظة المستلم.

address string | null مطلوب

عنوان المستلم.

lat number | null مطلوب

خط عرض موقع المستلم.

lng number | null مطلوب

خط طول موقع المستلم.

cod_amount number مطلوب

مبلغ التحصيل عند الاستلام، بالدولار الأمريكي دائماً.

cod_collected number مطلوب

المبلغ المحصَّل حتى الآن بالدولار (المبلغ المحصَّل عند التسليم الجزئي).

weight_kg number | null مطلوب

وزن الطرد بالكيلوغرام.

charges object مطلوب

رسوم الطرد.

delivery_fee number مطلوب

أجرة التوصيل بالدولار (تكلفة شركة الشحن لطرد الشحن).

platform_fee number مطلوب

رسم المنصة بالدولار.

delivery_attempts integer مطلوب

عدد محاولات التسليم.

note string | null مطلوب

الملاحظة المرسلة مع الطرد.

tracking_url string (uri) مطلوب

صفحة التتبع العامة للطرد.

created_at string (date-time) | null مطلوب

وقت الإنشاء (ISO 8601 مع فرق التوقيت عن UTC).

updated_at string (date-time) | null مطلوب

وقت آخر تحديث (ISO 8601 مع فرق التوقيت عن UTC).

merchant object | null مطلوب

التاجر صاحب الطرد.

id integer مطلوب

معرّف التاجر.

name string | null مطلوب

الاسم التجاري للتاجر.

deliveryman object | null مطلوب

المندوب الذي يحمل الطرد، أو null إن لم يكن لدى أحد.

id integer مطلوب

معرّف المندوب.

name string | null مطلوب

اسم المندوب.

أحداث الويب هوك

ترسل المنصة هذه الرسائل إلى عناوين HTTPS التي تسجّلها (الويب هوك الصادر). كل رسالة طلب POST بصيغة JSON وموقَّع، ويُعاد إرساله إذا لم يردّ نظامك بحالة 2xx. يعرض كل حدث أدناه جسم رسالته، وتشترك الأحداث كلها في الترويسات والتوقيع نفسها.

ترويسات الطلب

الاسمالنوعالوصف
X-DS-Eventstring

اسم الحدث (مثل parcel.delivered، أو ping للاختبار).

X-DS-Event-Idstring

معرّف الحدث، evt_ يليه 24 حرفاً صغيراً. هو نفسه في كل محاولة ولكل رابط: استخدمه لتجاهل التكرار.

X-DS-Deliverystring (uuid)

معرّف UUID لهذه الرسالة إلى هذا الرابط. هو نفسه عبر المحاولات.

X-DS-Attemptinteger

رقم المحاولة ويبدأ من 1.

X-DS-Timestampstring

وقت الإرسال بثواني Unix ويتجدد في كل محاولة. وهو جزء من النص الموقَّع.

X-DS-Signaturestring

sha256= يليه التمثيل السداسي بأحرف صغيرة لـ HMAC-SHA256 بمفتاح توقيع الرابط (whsec_... بالسلسلة كاملة) على النص X-DS-Timestamp + "." + جسم الطلب الخام. قارن بدالة زمنها ثابت.

حدث POST parcel.created #

طرد جديد

أُنشئ طرد لأحد تجّارك. الطرد الجديد يرسل عادةً هذا الحدث ثم parcel.status_changed (الحالة 5). تُرسل إلى روابط الويب هوك التي تسجّلها في لوحة الشركة (الربط والـ API ثم Webhook) لطرود شركتك فقط؛ وكائن data هو كائن طرد الشركة مع merchant وdeliveryman.

جسم الرسالة

الحقلالنوع مطلوبالوصف
id string مطلوب

معرّف الحدث (evt_ يليه 24 حرفاً صغيراً)؛ وهو نفسه ترويسة X-DS-Event-Id.

النمط ^evt_[a-z0-9]{24}$

event string مطلوب

قيمة ثابتة "parcel.created"

created_at string (date-time) مطلوب

وقت إنشاء الحدث (ISO 8601).

data Parcel مطلوب

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

مثال

JSON
{
  "id": "evt_abcdefghijklmnopqrstuvwx",
  "event": "parcel.created",
  "created_at": "2026-01-01T12:10:00+00:00",
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "out_for_delivery",
    "status_code": 7,
    "status_label": "Delivery Man Assign",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 0,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": {
      "id": 5,
      "name": "Example Courier"
    }
  }
}

حدث POST parcel.status_changed #

تغيّرت حالة الطرد

أي تغيير في الحالة عبر مسار عمل الطرد. وقد يرسل التغيير الواحد هذا الحدث وحدث المرحلة، لكل منهما معرّف حدث خاص. لا يُرسل من نماذج الموظفين المخصصة للاستلام والمراكز ولا من بعض نماذج التراجع: اقرأ الطرد عندما تحتاج إلى حالته الحالية. تُرسل إلى روابط الويب هوك التي تسجّلها في لوحة الشركة (الربط والـ API ثم Webhook) لطرود شركتك فقط؛ وكائن data هو كائن طرد الشركة مع merchant وdeliveryman.

جسم الرسالة

الحقلالنوع مطلوبالوصف
id string مطلوب

معرّف الحدث (evt_ يليه 24 حرفاً صغيراً)؛ وهو نفسه ترويسة X-DS-Event-Id.

النمط ^evt_[a-z0-9]{24}$

event string مطلوب

قيمة ثابتة "parcel.status_changed"

created_at string (date-time) مطلوب

وقت إنشاء الحدث (ISO 8601).

data Parcel مطلوب

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

مثال

JSON
{
  "id": "evt_abcdefghijklmnopqrstuvwx",
  "event": "parcel.status_changed",
  "created_at": "2026-01-01T12:10:00+00:00",
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "out_for_delivery",
    "status_code": 7,
    "status_label": "Delivery Man Assign",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 0,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": {
      "id": 5,
      "name": "Example Courier"
    }
  }
}

حدث POST parcel.out_for_delivery #

خرج للتوصيل

الطرد مع المندوب (الحالتان 7 و8). تُرسل إلى روابط الويب هوك التي تسجّلها في لوحة الشركة (الربط والـ API ثم Webhook) لطرود شركتك فقط؛ وكائن data هو كائن طرد الشركة مع merchant وdeliveryman.

جسم الرسالة

الحقلالنوع مطلوبالوصف
id string مطلوب

معرّف الحدث (evt_ يليه 24 حرفاً صغيراً)؛ وهو نفسه ترويسة X-DS-Event-Id.

النمط ^evt_[a-z0-9]{24}$

event string مطلوب

قيمة ثابتة "parcel.out_for_delivery"

created_at string (date-time) مطلوب

وقت إنشاء الحدث (ISO 8601).

data Parcel مطلوب

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

مثال

JSON
{
  "id": "evt_abcdefghijklmnopqrstuvwx",
  "event": "parcel.out_for_delivery",
  "created_at": "2026-01-01T12:10:00+00:00",
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "out_for_delivery",
    "status_code": 7,
    "status_label": "Delivery Man Assign",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 0,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": {
      "id": 5,
      "name": "Example Courier"
    }
  }
}

حدث POST parcel.delivered #

تم التسليم

سُلِّم الطرد كاملاً أو جزئياً (الحالتان 9 و32). يتضمن data.cod_collected المبلغ المحصَّل. تُرسل إلى روابط الويب هوك التي تسجّلها في لوحة الشركة (الربط والـ API ثم Webhook) لطرود شركتك فقط؛ وكائن data هو كائن طرد الشركة مع merchant وdeliveryman.

جسم الرسالة

الحقلالنوع مطلوبالوصف
id string مطلوب

معرّف الحدث (evt_ يليه 24 حرفاً صغيراً)؛ وهو نفسه ترويسة X-DS-Event-Id.

النمط ^evt_[a-z0-9]{24}$

event string مطلوب

قيمة ثابتة "parcel.delivered"

created_at string (date-time) مطلوب

وقت إنشاء الحدث (ISO 8601).

data Parcel مطلوب

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

مثال

JSON
{
  "id": "evt_abcdefghijklmnopqrstuvwx",
  "event": "parcel.delivered",
  "created_at": "2026-01-01T12:10:00+00:00",
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "out_for_delivery",
    "status_code": 7,
    "status_label": "Delivery Man Assign",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 0,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": {
      "id": 5,
      "name": "Example Courier"
    }
  }
}

حدث POST parcel.returning #

قيد الإرجاع

تعذّر التسليم والطرد في طريق العودة. تُرسل إلى روابط الويب هوك التي تسجّلها في لوحة الشركة (الربط والـ API ثم Webhook) لطرود شركتك فقط؛ وكائن data هو كائن طرد الشركة مع merchant وdeliveryman.

جسم الرسالة

الحقلالنوع مطلوبالوصف
id string مطلوب

معرّف الحدث (evt_ يليه 24 حرفاً صغيراً)؛ وهو نفسه ترويسة X-DS-Event-Id.

النمط ^evt_[a-z0-9]{24}$

event string مطلوب

قيمة ثابتة "parcel.returning"

created_at string (date-time) مطلوب

وقت إنشاء الحدث (ISO 8601).

data Parcel مطلوب

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

مثال

JSON
{
  "id": "evt_abcdefghijklmnopqrstuvwx",
  "event": "parcel.returning",
  "created_at": "2026-01-01T12:10:00+00:00",
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "out_for_delivery",
    "status_code": 7,
    "status_label": "Delivery Man Assign",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 0,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": {
      "id": 5,
      "name": "Example Courier"
    }
  }
}

حدث POST parcel.returned #

رُدّ للتاجر

استلم التاجر الطرد المرتجع (الحالتان 30 و13). تُرسل إلى روابط الويب هوك التي تسجّلها في لوحة الشركة (الربط والـ API ثم Webhook) لطرود شركتك فقط؛ وكائن data هو كائن طرد الشركة مع merchant وdeliveryman.

جسم الرسالة

الحقلالنوع مطلوبالوصف
id string مطلوب

معرّف الحدث (evt_ يليه 24 حرفاً صغيراً)؛ وهو نفسه ترويسة X-DS-Event-Id.

النمط ^evt_[a-z0-9]{24}$

event string مطلوب

قيمة ثابتة "parcel.returned"

created_at string (date-time) مطلوب

وقت إنشاء الحدث (ISO 8601).

data Parcel مطلوب

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

مثال

JSON
{
  "id": "evt_abcdefghijklmnopqrstuvwx",
  "event": "parcel.returned",
  "created_at": "2026-01-01T12:10:00+00:00",
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "out_for_delivery",
    "status_code": 7,
    "status_label": "Delivery Man Assign",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 0,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": {
      "id": 5,
      "name": "Example Courier"
    }
  }
}

حدث POST parcel.cancelled #

أُلغي

أبلغت شركة الشحن الخارجية المربوطة بإلغاء الطرد. تُرسل إلى روابط الويب هوك التي تسجّلها في لوحة الشركة (الربط والـ API ثم Webhook) لطرود شركتك فقط؛ وكائن data هو كائن طرد الشركة مع merchant وdeliveryman.

جسم الرسالة

الحقلالنوع مطلوبالوصف
id string مطلوب

معرّف الحدث (evt_ يليه 24 حرفاً صغيراً)؛ وهو نفسه ترويسة X-DS-Event-Id.

النمط ^evt_[a-z0-9]{24}$

event string مطلوب

قيمة ثابتة "parcel.cancelled"

created_at string (date-time) مطلوب

وقت إنشاء الحدث (ISO 8601).

data Parcel مطلوب

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

مثال

JSON
{
  "id": "evt_abcdefghijklmnopqrstuvwx",
  "event": "parcel.cancelled",
  "created_at": "2026-01-01T12:10:00+00:00",
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "out_for_delivery",
    "status_code": 7,
    "status_label": "Delivery Man Assign",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 0,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": {
      "id": 5,
      "name": "Example Courier"
    }
  }
}

حدث POST parcel.awaiting_funds #

بانتظار الرصيد

حُفظ الطلب لكن رصيد التاجر لا يكفي. تُرسل إلى روابط الويب هوك التي تسجّلها في لوحة الشركة (الربط والـ API ثم Webhook) لطرود شركتك فقط؛ وكائن data هو كائن طرد الشركة مع merchant وdeliveryman.

جسم الرسالة

الحقلالنوع مطلوبالوصف
id string مطلوب

معرّف الحدث (evt_ يليه 24 حرفاً صغيراً)؛ وهو نفسه ترويسة X-DS-Event-Id.

النمط ^evt_[a-z0-9]{24}$

event string مطلوب

قيمة ثابتة "parcel.awaiting_funds"

created_at string (date-time) مطلوب

وقت إنشاء الحدث (ISO 8601).

data Parcel مطلوب

الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).

مثال

JSON
{
  "id": "evt_abcdefghijklmnopqrstuvwx",
  "event": "parcel.awaiting_funds",
  "created_at": "2026-01-01T12:10:00+00:00",
  "data": {
    "id": 1043,
    "tracking_number": "DS-000000",
    "reference": "ORDER-1043",
    "stage": "out_for_delivery",
    "status_code": 7,
    "status_label": "Delivery Man Assign",
    "company_id": 3,
    "company_name": "Example Delivery",
    "external_tracking_number": null,
    "recipient": {
      "name": "Example Name",
      "phone": "0900000000",
      "governorate": "Damascus",
      "address": "Example street, building 1",
      "lat": null,
      "lng": null
    },
    "cod_amount": 25,
    "cod_collected": 0,
    "weight_kg": 1.5,
    "charges": {
      "delivery_fee": 6,
      "platform_fee": 1
    },
    "delivery_attempts": 0,
    "note": null,
    "tracking_url": "https://YOUR_DOMAIN/t/DS-000000",
    "created_at": "2026-01-01T10:00:00+00:00",
    "updated_at": "2026-01-01T12:10:00+00:00",
    "merchant": {
      "id": 41,
      "name": "Example Shop"
    },
    "deliveryman": {
      "id": 5,
      "name": "Example Courier"
    }
  }
}

الأخطاء

كل خطأ تثيره الواجهة نفسها يستخدم غلاف JSON نفسه. ابنِ منطق برنامجك على error.code وحالة HTTP لا على نص الرسالة. هذه هي الرموز التي يمكن أن تُرجعها هذه الواجهة؛ أما الأخطاء التي يثيرها الإطار قبل تنفيذ كود الواجهة (حدود IP والمسار والمسارات المجهولة والطرق الخاطئة) فتأتي بصيغة بسيطة مختلفة {"message": "..."}.

الردود المشتركة

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

401 مفتاح الـ API مفقود أو غير معروف.

مفتاح الـ API مفقود أو غير معروف. unauthenticated: لا مفتاح في ترويسة Authorization: Bearer. invalid_key: المفتاح غير معروف (جُدِّد أو أُلغي أو كُتب خطأً أو هو من نوع آخر: مفتاح الشركة ck_... وحده يعمل هنا).

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — No key

JSON · 401
{
  "success": false,
  "error": {
    "code": "unauthenticated",
    "message": "Send the key in the header: Authorization: Bearer <API key>"
  }
}

مثال — Unknown key

JSON · 401
{
  "success": false,
  "error": {
    "code": "invalid_key",
    "message": "The key is invalid or revoked. Generate a new key from the company dashboard ← Integrations and API."
  }
}
402 انتهى اشتراك الشركة (subscription_expired).

انتهى اشتراك الشركة (subscription_expired). والشركات المملوكة للمنصة أو لتاجر مستثناة من فحص الاشتراك.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Subscription ended

JSON · 402
{
  "success": false,
  "error": {
    "code": "subscription_expired",
    "message": "Company subscription expired — renew the subscription from the company dashboard."
  }
}
403 الوصول مرفوض.

الوصول مرفوض. account_inactive: مستخدم المفتاح أو الشركة موقوف أو غير موجود. plan_feature: باقة الشركة لا تتضمن ميزة الـ API.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Suspended company

JSON · 403
{
  "success": false,
  "error": {
    "code": "account_inactive",
    "message": "Company account suspended."
  }
}

مثال — Plan without the API

JSON · 403
{
  "success": false,
  "error": {
    "code": "plan_feature",
    "message": "Localized text that names the feature and the plan problem."
  }
}
429 تجاوز حدّ الطلبات.

تجاوز حدّ الطلبات. يشترك في هذه الحالة ردّان مختلفان: (1) حدّ الباقة (في الدقيقة أو في اليوم): غلاف الخطأ بصيغة JSON مع error.code بقيمة rate_limited وerror.retry_after وترويسة Retry-After. (2) حدّ عنوان IP أو المسار: يردّ الإطار قبل تنفيذ كود الـ API بـ {"message": "Too Many Attempts."} (بصيغة JSON فقط عند إرسال Accept: application/json، وإلا صفحة HTML) مع الترويسات Retry-After وX-RateLimit-Limit وX-RateLimit-Remaining وX-RateLimit-Reset.

الترويسات: Retry-After X-RateLimit-Limit X-RateLimit-Remaining X-RateLimit-Reset

مثال — Plan limit

JSON · 429
{
  "success": false,
  "error": {
    "code": "rate_limited",
    "message": "Localized text with the limit and the wait time",
    "retry_after": 42
  }
}

مثال — IP or route limit

JSON · 429
{
  "message": "Too Many Attempts."
}
500 خطأ غير متوقع في الخادم.

خطأ غير متوقع في الخادم. تتضمن الرسالة مرجعاً قصيراً يستطيع الدعم العثور عليه في السجلات؛ أعد الطلب فقط إذا كانت نتيجته مجهولة.

الترويسات: X-RateLimit-Limit X-RateLimit-Remaining

مثال — Server error

JSON · 500
{
  "success": false,
  "error": {
    "code": "server_error",
    "message": "An error occurred on our side. If it happens again, contact support and mention reference E000000.",
    "reference": "E000000"
  }
}

رموز الأخطاء

الرمزHTTPالوصف
invalid_key401

المفتاح غير معروف (جُدِّد أو أُلغي أو كُتب خطأً أو هو من نوع آخر: مفتاح الشركة ck_... وحده يعمل هنا).

unauthenticated401

لا مفتاح في ترويسة Authorization: Bearer.

insufficient_balance402

الرصيد لا يكفي لأجرة الطرد.

subscription_expired402

انتهى اشتراك شركتك.

account_inactive403

مستخدم المفتاح أو الشركة موقوف أو غير موجود.

plan_feature403

باقة الشركة لا تتضمن ميزة الـ API.

not_found404

لا يوجد طرد بهذا الرقم أو المرجع لدى شركتك.

deliveryman_full409

يحمل المندوب أصلاً الحد الأقصى من الطرود المفتوحة. أرسل force: true لتجاوز الحد.

duplicate_reference409

لدى التاجر طرد بالمرجع reference نفسه. اجلبه بـ GET /parcels?merchant_id=<id>&reference=<reference> (أما GET /parcels/{reference} وحده فيبحث بين كل تجّارك).

invalid_transition409

الإجراء لا يناسب الحالة الحالية، أو collected أعلى من المسموح.

not_allowed409

الطرد لدى شركة شحن خارجية هي التي تتحكم بحالته.

carrier_error422

تعذّرت معالجة الطرد لدى شركة الشحن.

validation_failed422

قيمة stage مجهولة. تسرد الرسالة القيم المتاحة؛ ولا يوجد كائن fields.

rate_limited429
server_error500

مصادر إضافية