واجهة التاجر في Delivery Syria
تسعير الطرود وإنشاؤها وعرضها وتتبّعها وإلغاؤها، وقراءة كشف المحفظة، وإدارة روابط الويب هوك.
استورد هذا الملف في Postman أو Insomnia أو أي أداة تدعم OpenAPI 3.1، أو أعطِ الأداة العنوان الظاهر أدناه. الخادم في الملف نسبي (بلا نطاق): بعد الاستيراد اضبط عنوان منصتك على أنه العنوان الأساسي.
https://deliverysyria.com/docs/api/merchant-v1.jsonنظرة عامة
تتيح واجهة التاجر (/api/v1) لنظام تاجر المنصة العمل مع الطرود والمحفظة. كل استدعاء يُوثَّق بمفتاح API في ترويسة Bearer، وكل ردّ بصيغة JSON وبالغلاف نفسه: {"success": true, "data": ...} (مع meta في القوائم المرقّمة) أو {"success": false, "error": {"code", "message"}}. أرسل دائماً Accept: application/json.
كُتب هذا المستند من كود التطبيق، وتفحصه اختبارات آلية مقابل المسارات وقواعد التحقق وأشكال الردود الفعلية. وهو يصف ما يفعله الكود فقط. ولا توجد ترويسة للإصدار ولا دعم لـ Idempotency-Key ولا لوحة «جرّب الآن». وحدود الطلبات موصوفة في كل عملية: طلبات في الدقيقة لكل عنوان IP، إضافة إلى حدود باقتك.
للأدلة والشروحات اقرأ مقالات المطورين في مركز التوثيق.
- العنوان الأساسي
https://YOUR_DOMAIN/api/v1استبدلYOUR_DOMAINبعنوان منصتك.- المصادقة
مفتاح الـ API الخاص بالمطوّر لديك في ترويسة
Authorization:Authorization: Bearer YOUR_API_KEY. تُقرأ هذه الترويسة فقط؛ والمفتاح في الاستعلام أو في الجسم يُتجاهل. أنشئ المفتاح من لوحة التاجر (الويب هوك والـ API ثم مفتاح API للمطورين). وهو يعمل على/api/v1فقط: المفاتيح الأخرى (ربط المتاجر ومفتاح الشركة) تعطيinvalid_key.Authorization: Bearer YOUR_API_KEY- Accept-Language
لغة رسائل الأخطاء والتسميات (تسمية الحالة وملاحظات الأحداث والأسماء). إذا بدأت القيمة بـ
enجاء الرد بالإنجليزية، وأي قيمة أخرى أو غياب الترويسة يعطي العربية. الحقول المقروءة آلياً لا تتغير أبداً.- حدود الطلبات
تُطبَّق ثلاث طبقات. (1) حدّ عام قدره 60 طلباً في الدقيقة لكل عنوان IP على كل طلب
/api. (2) حدود المسارات، وتُحتسب لكل عنوان IP على عدّاد واحد مشترك: حدّ المجموعة 120 في الدقيقة، و60 و30 و20 و10 لكل منPOST /parcelsوGET /statementوPOST /webhooksوPOST /webhooks/{id}/test؛ ولأن الطلب إلى مسار له حدّ خاص يُحسب على المجموعة وعلى المسار معاً، فإن المسار ذا الحدّ الخاص لا يتيح من عنوان IP واحد إلا نحو نصفه. (3) حدود الباقة لكل حساب في الدقيقة وفي اليوم (429 rate_limitedمعRetry-After). وتُذكر الحدود المطبّقة على كل عملية في العملية نفسها.- لا توجد لوحة «جرّب الآن»
لا يتضمن هذا المرجع لوحة «جرّب الآن» ولا يرسل أي طلب من متصفحك. فذلك يعني إدخال مفتاح API حقيقي في صفحة ويب واستدعاء الواجهة الفعلية ببيانات حقيقية. اختبر بالأمثلة البرمجية ومفتاحك الخاص من خادمك أو من الطرفية.
الحساب
ملف التاجر وباقته وأرصدة محافظه.
الطريقة GET
/me
#
جلب حسابك
تُرجع معرّف التاجر والاسم التجاري والباقة وأرصدة المحافظ. وهي أول استدعاء مناسب للتأكد من المفتاح.
الردود
200 حسابك.
حسابك.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
object |
مطلوب |
حسابك. |
merchant_id |
integer |
مطلوب |
معرّف حسابك كتاجر. |
business_name |
string | null |
مطلوب |
الاسم التجاري للتاجر. |
plan |
object | null |
مطلوب |
آخر اشتراك، أو null عند عدم وجود سجل اشتراك. |
name |
string | null |
مطلوب |
اسم الباقة. |
expires_on |
string (date) |
مطلوب |
تاريخ انتهاء الاشتراك ( |
active |
boolean |
مطلوب |
هل الباقة فعّالة حالياً. |
balances |
object |
مطلوب |
أرصدة المحافظ بالدولار. |
recharge |
number |
مطلوب |
رصيد الشحن (محفظة الشحن) بالدولار. |
cod_due |
number |
مطلوب |
مستحقات التحصيل عند الاستلام (محفظة المستحقات) بالدولار. |
held |
number |
مطلوب |
المبالغ المحجوزة بالدولار. |
company_due |
number |
مطلوب |
مستحقات الشركة بالدولار. |
currency |
string |
مطلوب |
رمز عملة المنصة المضبوط ( |
مثال
{
"success": true,
"data": {
"merchant_id": 12,
"business_name": "Example Shop",
"plan": {
"name": "Example Plan",
"expires_on": "2026-12-01",
"active": true
},
"balances": {
"recharge": 150.5,
"cod_due": 320,
"held": 0,
"company_due": 0
},
"currency": "$"
}
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
أمثلة برمجية
curl
curl -X GET "https://YOUR_DOMAIN/api/v1/me" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/me");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/me", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.get(
"https://YOUR_DOMAIN/api/v1/me",
headers={
"Authorization": f"Bearer {os.environ['DS_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
/companies
#
قائمة شركات التوصيل والشحن
تعرض شركات التوصيل وشركات الشحن التي يمكنك استخدامها. أرسل قيمة id على أنها company_id عند التسعير أو إنشاء الطرد. القائمة غير مرقّمة.
الردود
200 الشركات التي يمكنك استخدامها.
الشركات التي يمكنك استخدامها.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
array<object> |
مطلوب | |
id |
integer |
مطلوب |
أرسله على أنه |
name |
string |
مطلوب |
اسم الشركة. |
type |
string |
مطلوب |
إحدى القيم: |
pricing_mode |
string |
مطلوب |
طريقة احتساب السعر: إحدى القيم: |
supports_own_account |
boolean |
مطلوب |
تكون true عندما تسمح شركة الشحن بحسابات التجّار وتكون قد ربطتَ حسابك بها. |
coverage |
object | null |
مطلوب |
|
مثال
{
"success": true,
"data": [
{
"id": 3,
"name": "Example Delivery",
"type": "delivery_company",
"pricing_mode": "governorate",
"supports_own_account": false,
"coverage": null
},
{
"id": 5,
"name": "Example Carrier",
"type": "carrier",
"pricing_mode": "carrier_quote",
"supports_own_account": true,
"coverage": {
"SY": []
}
}
]
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
أمثلة برمجية
curl
curl -X GET "https://YOUR_DOMAIN/api/v1/companies" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/companies");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/companies", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.get(
"https://YOUR_DOMAIN/api/v1/companies",
headers={
"Authorization": f"Bearer {os.environ['DS_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
/governorates
#
قائمة المحافظات
تُرجع id وname وname_ar لكل محافظة فعّالة. أرسل name أو name_ar في recipient.governorate. القائمة غير مرقّمة.
الردود
200 المحافظات الفعّالة.
المحافظات الفعّالة.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
array<object> |
مطلوب | |
id |
integer |
مطلوب |
معرّف المحافظة. عند إرساله في |
name |
string |
مطلوب |
الاسم بالإنجليزية. |
name_ar |
string |
مطلوب |
الاسم بالعربية. |
مثال
{
"success": true,
"data": [
{
"id": 1,
"name": "Damascus",
"name_ar": "دمشق"
}
]
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
أمثلة برمجية
curl
curl -X GET "https://YOUR_DOMAIN/api/v1/governorates" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/governorates");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/governorates", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.get(
"https://YOUR_DOMAIN/api/v1/governorates",
headers={
"Authorization": f"Bearer {os.environ['DS_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
/pickup-locations
#
قائمة أماكن الاستلام لديك
تُرجع أماكن الاستلام لديك والافتراضي أولاً. عند عدم إرسال pickup_location_id مع الطرد يُستخدم المكان الافتراضي. أضف الأماكن من لوحة التاجر. القائمة غير مرقّمة.
الردود
200 أماكن الاستلام لديك.
أماكن الاستلام لديك.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
array<object> |
مطلوب | |
id |
integer |
مطلوب |
أرسله على أنه |
name |
string | null |
مطلوب |
اسم المكان. |
phone |
string | null |
مطلوب |
هاتف التواصل. |
address |
string | null |
مطلوب |
العنوان. |
lat |
number | null |
مطلوب |
خط العرض. |
lng |
number | null |
مطلوب |
خط الطول. |
default |
boolean |
مطلوب |
تكون true للمكان الافتراضي (يُستخدم عند عدم إرسال |
warehouse_id |
integer | null |
مطلوب |
معرّف المستودع عندما يكون المكان مستودعاً، وإلا null. |
active |
boolean |
مطلوب |
هل يمكن استخدام المكان. |
مثال
{
"success": true,
"data": [
{
"id": 7,
"name": "Main branch",
"phone": "0900000000",
"address": "Example street, building 1",
"lat": null,
"lng": null,
"default": true,
"warehouse_id": null,
"active": true
}
]
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
أمثلة برمجية
curl
curl -X GET "https://YOUR_DOMAIN/api/v1/pickup-locations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/pickup-locations");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/pickup-locations", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.get(
"https://YOUR_DOMAIN/api/v1/pickup-locations",
headers={
"Authorization": f"Bearer {os.environ['DS_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
/warehouse/stock
#
جلب بضاعتك في المستودعات
لكل حجز مستودع فعّال: المستودع ومعرّف مكان الاستلام الخاص به (استخدمه على أنه pickup_location_id للشحن من هذا المخزون) والمنصّات والأصناف بكمياتها. تُرجع قائمة فارغة عند عدم وجود حجز فعّال.
الردود
200 المخزون لكل حجز مستودع.
المخزون لكل حجز مستودع.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
array<object> |
مطلوب | |
warehouse_id |
integer |
مطلوب |
معرّف المستودع. |
warehouse |
string | null |
مطلوب |
اسم المستودع. |
pickup_location_id |
integer |
مطلوب |
مكان الاستلام لهذا الحجز: استخدمه على أنه |
pallets |
integer |
مطلوب |
عدد المنصّات المحجوزة. |
items |
array<object> |
مطلوب |
أصناف المخزون. |
item_id |
integer |
مطلوب |
معرّف صنف المخزون. |
sku |
string | null |
مطلوب |
رمز المنتج. |
name |
string | null |
مطلوب |
اسم المنتج. |
qty |
integer |
مطلوب |
الكمية في المخزون. |
reserved |
integer |
مطلوب |
الكمية المحجوزة لطرود أخرى. |
available |
integer |
مطلوب |
الكمية التي ما زال بإمكانك شحنها. |
مثال
{
"success": true,
"data": [
{
"warehouse_id": 1,
"warehouse": "Example Warehouse",
"pickup_location_id": 9,
"pallets": 2,
"items": [
{
"item_id": 5,
"sku": "A1",
"name": "Example item",
"qty": 20,
"reserved": 2,
"available": 18
}
]
}
]
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
أمثلة برمجية
curl
curl -X GET "https://YOUR_DOMAIN/api/v1/warehouse/stock" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/warehouse/stock");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/warehouse/stock", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.get(
"https://YOUR_DOMAIN/api/v1/warehouse/stock",
headers={
"Authorization": f"Bearer {os.environ['DS_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
/quote
#
تسعير طرد دون إنشائه
تحسب سعر الطرد على الخادم دون إنشائه ودون خصم أي مبلغ. تأخذ الحقول نفسها المستخدمة في POST /parcels والمطلوب فقط company_id، لكن الحقول التي يحتاجها السعر تعتمد على pricing_mode للشركة (انظر GET /companies): governorate يحتاج recipient.governorate (أو عنواناً تستطيع المنصة ربطه بمحافظة، أو إحداثيات)؛ وper_kg يحتاج weight؛ وper_km يحتاج recipient.lat وrecipient.lng ومكان استلام له موقع على الخريطة؛ وkm_kg يحتاج الاثنين؛ وcarrier_quote يطلب السعر من شركة الشحن. وفي التسعير الداخلي يُقرَّب الوزن إلى كيلوغرام كامل ويُطبَّق الحد الأدنى للأجرة عند الشركة. ويختلف الرد بين شركة التوصيل وشركة الشحن (انظر Quote).
جسم الطلب
application/json · مطلوب
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
company_id |
integer |
مطلوب |
شركة التوصيل أو الشحن، قيمة |
recipient |
object |
اختياري |
المستلم. يمكن بدلاً من ذلك إرسال كل حقل مسطحاً في المستوى الأعلى ( |
name |
string |
اختياري |
اسم المستلم. الحد الأقصى للطول 191 |
phone |
string |
اختياري |
رقم هاتف المستلم: أرقام ومسافات و الحد الأقصى للطول 30النمط |
address |
string |
اختياري |
عنوان المستلم. الحد الأقصى للطول 1000 |
governorate |
string |
اختياري |
اسم المحافظة ( الحد الأقصى للطول 120يُقبل أيضاً باسم |
lat |
number |
اختياري |
خط عرض موقع المستلم. مطلوب للتسعير حسب المسافة ( الحد الأدنى -90الحد الأقصى 90 |
lng |
number |
اختياري |
خط طول موقع المستلم. مطلوب للتسعير حسب المسافة ( الحد الأدنى -180الحد الأقصى 180يُقبل أيضاً باسم |
reference |
string |
اختياري |
مرجعك الخاص (رقم الطلب). لا يؤثر في السعر. الحد الأقصى للطول 191يُقبل أيضاً باسم |
cod_amount |
number |
اختياري |
مبلغ التحصيل عند الاستلام الذي يدفعه المستلم، من 0 إلى 100,000,000 دولار أمريكي (يُحوَّل المبلغ بغير الدولار إلى الدولار بسعر المنصة قبل فحص الحد). القيمة 0 تعني مدفوع مسبقاً. الحد الأدنى 0الحد الأقصى 100000000الافتراضي |
currency |
string |
اختياري |
رمز عملة إحدى القيم: الافتراضي |
weight |
number |
اختياري |
الوزن بالكيلوغرام من 0.01 إلى 1000. الافتراضي 1. في التسعير الداخلي يُقرَّب الوزن إلى كيلوغرام كامل (الحد الأدنى 1). الحد الأدنى 0.01الحد الأقصى 1000الافتراضي |
pickup_location_id |
integer |
اختياري |
أحد أماكن الاستلام لديك ( يُقبل أيضاً باسم |
note |
string |
اختياري |
ملاحظة لشركة التوصيل بحد أقصى 2000 محرف. الحد الأقصى للطول 2000 |
use_own_account |
boolean |
اختياري |
الشحن بحسابك الخاص لدى شركة شحن تسمح بحسابات التجّار. يفشل بالرمز |
shipping_paid_by |
string |
اختياري |
من يدفع أجرة الشحن، لشركات الشحن التي تدعم الاختيار: إحدى القيم: |
مثال
{
"company_id": 3,
"recipient": {
"governorate": "Damascus"
},
"weight": 2
}الردود
200 التسعيرة.
التسعيرة.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
oneOf |
مطلوب |
يعتمد الشكل على الشركة: شركة التوصيل تعطي |
بديل QuoteDeliveryCompany تسعيرة لشركة توصيل. | |||
pricing_mode |
string |
مطلوب |
آلية التسعير المستخدمة. إحدى القيم: |
pricing_label |
string | null |
مطلوب |
تسمية آلية التسعير بلغة الطلب. |
governorate |
string | null |
مطلوب |
المحافظة المستخدمة في التسعير حسب المحافظة، وإلا null. |
distance_km |
number |
مطلوب |
المسافة المستخدمة (0 ما لم تعتمد الآلية على المسافة). |
weight_kg |
number |
مطلوب |
الوزن المستخدم مقرَّباً إلى كيلوغرام كامل (الحد الأدنى 1). |
delivery_fee |
number |
مطلوب |
أجرة التوصيل بالدولار. |
platform_fee |
number |
مطلوب |
رسم المنصة بالدولار. |
charged_now |
number |
مطلوب |
المبلغ الذي يُخصم من محفظتك عند الإنشاء: أجرة التوصيل مع رسم المنصة، أو رسم المنصة فقط لشركة التوصيل الداخلية الخاصة بك. |
بديل QuoteCarrier تسعيرة لشركة شحن خارجية: كائن مختلف وأصغر. لا يتضمن pricing_label ولا governorate ولا distance_km ولا weight_kg ولا delivery_fee. | |||
pricing_mode |
string |
مطلوب |
قيمة ثابتة |
carrier |
string |
مطلوب |
اسم شركة الشحن. |
account |
string |
مطلوب |
الحساب الذي سيُستخدم: حساب المنصة أو حسابك الخاص لدى الشركة. إحدى القيم: |
carrier_fee |
number |
مطلوب |
سعر شركة الشحن بعملتها. |
carrier_currency |
string |
مطلوب |
عملة |
carrier_fee_usd |
number |
مطلوب |
سعر شركة الشحن بالدولار. |
platform_fee |
number |
مطلوب |
رسم المنصة بالدولار. |
charged_now |
number |
مطلوب |
المبلغ المخصوم من محفظتك عند الإنشاء بالدولار. |
held_now |
number |
مطلوب |
المبلغ المحجوز حتى التسليم (حسابك الخاص لدى الشركة) بالدولار. |
required_balance |
number |
مطلوب |
الرصيد الذي يجب أن يتوفر في محفظتك بالدولار. |
shipping_paid_by |
string |
مطلوب |
من يدفع أجرة الشحن ( |
receiver_pays |
number |
مطلوب |
المبلغ الذي يدفعه المستلم عند التسليم بالدولار. |
net_after_delivery |
number |
مطلوب |
صافي مبلغك بعد التسليم بالدولار. |
destination |
string | null |
مطلوب |
ملاحظة الوجهة من شركة الشحن. |
currency |
string |
مطلوب |
قيمة ثابتة |
مثال
{
"success": true,
"data": {
"pricing_mode": "governorate",
"pricing_label": "Fixed amount per governorate",
"governorate": "Damascus",
"distance_km": 0,
"weight_kg": 2,
"delivery_fee": 6,
"platform_fee": 1,
"charged_now": 7
}
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
422 validation_failed:
validation_failed: company_id مفقود أو غير متاح لك، أو ينقص حقل يحتاجه التسعير. quote_failed: تعذّر حساب السعر. carrier_error: رفضت شركة الشحن التسعير أو تعذّر عليها.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Missing company
{
"success": false,
"error": {
"code": "validation_failed",
"message": "company_id is required — get the list from GET /companies",
"fields": {
"company_id": [
"company_id is required — get the list from GET /companies"
]
}
}
}مثال — Price not calculated
{
"success": false,
"error": {
"code": "quote_failed",
"message": "Could not calculate the price."
}
}أمثلة برمجية
curl
curl -X POST "https://YOUR_DOMAIN/api/v1/quote" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"company_id": 3,
"recipient": {
"governorate": "Damascus"
},
"weight": 2
}'PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/quote");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_API_KEY"),
"Accept: application/json",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
'company_id' => 3,
'recipient' => [
'governorate' => 'Damascus',
],
'weight' => 2,
]),
]);
$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
const response = await fetch("https://YOUR_DOMAIN/api/v1/quote", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.DS_API_KEY}`,
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
"company_id": 3,
"recipient": {
"governorate": "Damascus"
},
"weight": 2
}),
});
const json = await response.json();
if (!json.success) {
throw new Error(`${response.status} ${json.error.code}: ${json.error.message}`);
}
console.log(json.data);Python
import os
import requests
response = requests.post(
"https://YOUR_DOMAIN/api/v1/quote",
headers={
"Authorization": f"Bearer {os.environ['DS_API_KEY']}",
"Accept": "application/json",
},
json={
"company_id": 3,
"recipient": {
"governorate": "Damascus",
},
"weight": 2,
},
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. الطرود في المرحلة awaiting_funds لا تُعرض (اجلب الواحد منها برقم التتبع أو المرجع). الرد مرقّم ويتضمن meta.
معاملات الاستعلام
| الاسم | النوع | مطلوب | الوصف |
|---|---|---|---|
reference |
string |
اختياري |
تطابق تام مع مثال |
from |
string (date) |
اختياري |
أول يوم إنشاء مثال |
to |
string (date) |
اختياري |
آخر يوم إنشاء مثال |
stage |
string |
اختياري |
تصفية حسب إحدى القيم: مثال |
per_page |
integer |
اختياري |
حجم الصفحة من 1 إلى 100 (الافتراضي 20). القيمة خارج المجال لا تُرفض بل تُقرَّب إلى أقرب حدّ، وتعود القيمة الفعلية في الحد الأدنى 1الحد الأقصى 100الافتراضي |
page |
integer |
اختياري |
رقم الصفحة ويبدأ من 1. القيمة غير الصالحة أو الأصغر من 1 تُعامل على أنها 1. والصفحة بعد الأخيرة تعيد قائمة فارغة. الحد الأدنى 1الافتراضي |
الردود
200 صفحة من الطرود.
صفحة من الطرود.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
array<Parcel> |
مطلوب | |
meta |
Meta |
مطلوب |
كتلة الترقيم. لا توجد روابط ولا مؤشر (cursor). |
مثال
{
"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"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 1,
"last_page": 1
}
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
أمثلة برمجية
curl
curl -X GET "https://YOUR_DOMAIN/api/v1/parcels?reference=ORDER-1043&from=2026-01-01&to=2026-01-31&stage=out_for_delivery" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/parcels?reference=ORDER-1043&from=2026-01-01&to=2026-01-31&stage=out_for_delivery");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/parcels?reference=ORDER-1043&from=2026-01-01&to=2026-01-31&stage=out_for_delivery", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.get(
"https://YOUR_DOMAIN/api/v1/parcels",
headers={
"Authorization": f"Bearer {os.environ['DS_API_KEY']}",
"Accept": "application/json",
},
params={
"reference": "ORDER-1043",
"from": "2026-01-01",
"to": "2026-01-31",
"stage": "out_for_delivery",
},
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 نفسه مجدداً لإعادة المحاولة بأمان: تحصل على الطرد الموجود مع "duplicate": true (HTTP 200) ولا يُخصم أي مبلغ (الطرود المستردّة أو المنتهية لا تُحتسب). لا توجد ترويسة Idempotency-Key. التاجر بلا باقة فعّالة يُرفض بالرمز plan_feature قبل معالجة الطرد، وبلوغ حصة الطرود يعطي 422 على الحقل plan. وإذا رفضت شركة شحن خارجية الطرد فلا يُنشأ شيء ولا يُخصم شيء (carrier_error).
جسم الطلب
application/json · مطلوب
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
company_id |
integer |
مطلوب |
شركة التوصيل أو الشحن، قيمة |
recipient |
object |
مطلوب |
المستلم. يمكن بدلاً من ذلك إرسال كل حقل مسطحاً في المستوى الأعلى ( |
name |
string |
مطلوب |
اسم المستلم. الحد الأقصى للطول 191 |
phone |
string |
مطلوب |
رقم هاتف المستلم: أرقام ومسافات و الحد الأقصى للطول 30النمط |
address |
string |
مطلوب |
عنوان المستلم. الحد الأقصى للطول 1000 |
governorate |
string |
اختياري |
اسم المحافظة ( الحد الأقصى للطول 120يُقبل أيضاً باسم |
lat |
number |
اختياري |
خط عرض موقع المستلم. مطلوب للتسعير حسب المسافة ( الحد الأدنى -90الحد الأقصى 90 |
lng |
number |
اختياري |
خط طول موقع المستلم. مطلوب للتسعير حسب المسافة ( الحد الأدنى -180الحد الأقصى 180يُقبل أيضاً باسم |
reference |
string |
اختياري |
مرجعك الخاص الفريد (رقم الطلب) بحد أقصى 191 محرفاً. يجعل إعادة المحاولة آمنة: إرسال المرجع نفسه مجدداً يُرجع الطرد الموجود مع الحد الأقصى للطول 191يُقبل أيضاً باسم |
cod_amount |
number |
اختياري |
مبلغ التحصيل عند الاستلام الذي يدفعه المستلم، من 0 إلى 100,000,000 دولار أمريكي (يُحوَّل المبلغ بغير الدولار إلى الدولار بسعر المنصة قبل فحص الحد). القيمة 0 تعني مدفوع مسبقاً. الحد الأدنى 0الحد الأقصى 100000000الافتراضي |
currency |
string |
اختياري |
رمز عملة إحدى القيم: الافتراضي |
weight |
number |
اختياري |
الوزن بالكيلوغرام من 0.01 إلى 1000. الافتراضي 1. في التسعير الداخلي يُقرَّب الوزن إلى كيلوغرام كامل (الحد الأدنى 1). الحد الأدنى 0.01الحد الأقصى 1000الافتراضي |
pickup_location_id |
integer |
اختياري |
أحد أماكن الاستلام لديك ( يُقبل أيضاً باسم |
warehouse_items |
array<object> |
اختياري |
المنتجات التي تُشحن من مخزونك. مطلوبة عندما يكون مكان الاستلام مستودعاً، وتُهمل في غير ذلك. وتُقبل أيضاً باسم يُقبل أيضاً باسم |
sku |
string |
اختياري |
رمز المنتج (SKU) في المخزون. |
item_id |
integer |
اختياري |
معرّف صنف المخزون (بديل لـ |
qty |
integer |
مطلوب |
الكمية التي تخرج مع الطرد؛ يجب ألا تتجاوز الكمية المتاحة. الحد الأدنى 1 |
note |
string |
اختياري |
ملاحظة لشركة التوصيل بحد أقصى 2000 محرف. الحد الأقصى للطول 2000 |
use_own_account |
boolean |
اختياري |
الشحن بحسابك الخاص لدى شركة شحن تسمح بحسابات التجّار. يفشل بالرمز |
shipping_paid_by |
string |
اختياري |
من يدفع أجرة الشحن، لشركات الشحن التي تدعم الاختيار: إحدى القيم: |
wait_for_balance |
boolean |
اختياري |
عند عدم كفاية رصيد المحفظة يُحفظ الطرد بالمرحلة |
مثال
{
"company_id": 3,
"reference": "ORDER-1043",
"recipient": {
"name": "Example Name",
"phone": "0900000000",
"governorate": "Damascus",
"address": "Example street, building 1"
},
"cod_amount": 25,
"weight": 1.5,
"note": "Call before arriving"
}الردود
200 يوجد طرد بالمرجع reference نفسه:
يوجد طرد بالمرجع reference نفسه: يُرجع كما هو مع duplicate: true.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
Parcel |
مطلوب |
الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً). |
duplicate |
boolean |
مطلوب |
قيمة ثابتة |
مثال
{
"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"
},
"duplicate": true
}201 تم إنشاء الطرد.
تم إنشاء الطرد.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
Parcel |
مطلوب |
الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً). |
مثال
{
"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"
}
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
402 insufficient_balance:
insufficient_balance: رصيد المحفظة لا يكفي (تذكر الرسالة المبلغ المطلوب والمتاح). أرسل wait_for_balance: true لحفظ الطرد بالمرحلة awaiting_funds بدلاً من ذلك.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Balance too low
{
"success": false,
"error": {
"code": "insufficient_balance",
"message": "Insufficient wallet balance. Required: 7.00, available: 2.00"
}
}403 الوصول مرفوض. ردّ مشترك، انظر أدناه
422 validation_failed:
validation_failed: حقل مفقود أو خاطئ (يسردها fields بأسماء المنصة الداخلية)، أو company_id غير متاح لك، أو استُنفدت الحصة (plan). carrier_error: رفضت شركة الشحن الخارجية الطرد أو أن حساب الشركة غير صالح للاستخدام.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Missing recipient phone
{
"success": false,
"error": {
"code": "validation_failed",
"message": "The customer phone field is required.",
"fields": {
"customer_phone": [
"The customer phone field is required."
]
}
}
}مثال — Carrier refused
{
"success": false,
"error": {
"code": "carrier_error",
"message": "Localized message from the carrier."
}
}أمثلة برمجية
curl
curl -X POST "https://YOUR_DOMAIN/api/v1/parcels" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"company_id": 3,
"reference": "ORDER-1043",
"recipient": {
"name": "Example Name",
"phone": "0900000000",
"governorate": "Damascus",
"address": "Example street, building 1"
},
"cod_amount": 25,
"weight": 1.5,
"note": "Call before arriving"
}'PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/parcels");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_API_KEY"),
"Accept: application/json",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
'company_id' => 3,
'reference' => 'ORDER-1043',
'recipient' => [
'name' => 'Example Name',
'phone' => '0900000000',
'governorate' => 'Damascus',
'address' => 'Example street, building 1',
],
'cod_amount' => 25,
'weight' => 1.5,
'note' => 'Call before arriving',
]),
]);
$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
const response = await fetch("https://YOUR_DOMAIN/api/v1/parcels", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.DS_API_KEY}`,
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
"company_id": 3,
"reference": "ORDER-1043",
"recipient": {
"name": "Example Name",
"phone": "0900000000",
"governorate": "Damascus",
"address": "Example street, building 1"
},
"cod_amount": 25,
"weight": 1.5,
"note": "Call before arriving"
}),
});
const json = await response.json();
if (!json.success) {
throw new Error(`${response.status} ${json.error.code}: ${json.error.message}`);
}
console.log(json.data);Python
import os
import requests
response = requests.post(
"https://YOUR_DOMAIN/api/v1/parcels",
headers={
"Authorization": f"Bearer {os.environ['DS_API_KEY']}",
"Accept": "application/json",
},
json={
"company_id": 3,
"reference": "ORDER-1043",
"recipient": {
"name": "Example Name",
"phone": "0900000000",
"governorate": "Damascus",
"address": "Example street, building 1",
},
"cod_amount": 25,
"weight": 1.5,
"note": "Call before arriving",
},
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 بترتيب زمني. وتجد أيضاً الطرود في المرحلة awaiting_funds.
معاملات المسار
| الاسم | النوع | مطلوب | الوصف |
|---|---|---|---|
tracking |
string |
مطلوب |
رقم التتبع، أو مثال |
الردود
200 الطرد مع أحداثه.
الطرد مع أحداثه.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
object |
مطلوب |
كائن الطرد مع تاريخه ( |
يتضمن كل حقول Parcel | |||
events |
array<object> |
مطلوب |
تاريخ الطرد بترتيب زمني. يظهر فقط عند جلب طرد واحد. |
status_code |
integer |
مطلوب |
رمز الحالة الداخلي الدقيق لتلك الخطوة. |
stage |
string |
مطلوب |
المرحلة المبسطة لتلك الخطوة. إحدى القيم: |
status_label |
string |
مطلوب |
تسمية الحالة بلغة الطلب. |
note |
string | null |
مطلوب |
ملاحظة نصية مسجّلة مع الحدث. |
at |
string (date-time) | null |
مطلوب |
وقت الحدث (ISO 8601 مع فرق التوقيت عن UTC). |
مثال
{
"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",
"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 مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
404 not_found:
not_found: لا يوجد طرد بهذا الرقم أو المرجع في حسابك (والطرد الملغى لم يعد موجوداً).
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Unknown parcel
{
"success": false,
"error": {
"code": "not_found",
"message": "No parcel with this number for your account."
}
}أمثلة برمجية
curl
curl -X GET "https://YOUR_DOMAIN/api/v1/parcels/DS-000000" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/parcels/DS-000000");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/parcels/DS-000000", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.get(
"https://YOUR_DOMAIN/api/v1/parcels/DS-000000",
headers={
"Authorization": f"Bearer {os.environ['DS_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}/cancel
#
إلغاء طرد واسترجاع الأجرة
تلغي الطرد وتسترجع ما خُصم عند الإنشاء. لا تعمل إلا ما دامت الحالة «معلّق» أو «مستلم في المستودع» وليس للطرد external_tracking_number. يُحذف الطرد (والاستدعاء الثاني يعطي 404). والإلغاء عبر الـ API لا يرسل ويب هوك parcel.cancelled.
معاملات المسار
| الاسم | النوع | مطلوب | الوصف |
|---|---|---|---|
tracking |
string |
مطلوب |
رقم التتبع، أو مثال |
الردود
200 أُلغي الطرد واستُرجعت الأجرة.
أُلغي الطرد واستُرجعت الأجرة.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
object |
مطلوب |
نتيجة الإلغاء. |
tracking_number |
string |
مطلوب |
رقم تتبع الطرد الملغى. |
cancelled |
boolean |
مطلوب |
قيمة ثابتة |
refunded |
boolean |
مطلوب |
قيمة ثابتة |
مثال
{
"success": true,
"data": {
"tracking_number": "DS-000000",
"cancelled": true,
"refunded": true
}
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
404 not_found:
not_found: لا يوجد طرد بهذا الرقم في حسابك.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Unknown parcel
{
"success": false,
"error": {
"code": "not_found",
"message": "No parcel with this number for your account."
}
}409 not_cancellable:
not_cancellable: خرج الطرد من الحالة «معلّق» أو «مستلم في المستودع»، أو أُرسل إلى شركة شحن خارجية.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Already on its way
{
"success": false,
"error": {
"code": "not_cancellable",
"message": "The parcel is out for delivery or sent to the shipping company — it cannot be cancelled from here."
}
}أمثلة برمجية
curl
curl -X POST "https://YOUR_DOMAIN/api/v1/parcels/DS-000000/cancel" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/parcels/DS-000000/cancel");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/parcels/DS-000000/cancel", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.post(
"https://YOUR_DOMAIN/api/v1/parcels/DS-000000/cancel",
headers={
"Authorization": f"Bearer {os.environ['DS_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
/statement
#
جلب كشف حساب المحفظة
كشف حساب محفظتك لفترة: الرصيد الافتتاحي والختامي لكل محفظة، وملخص لكل نوع حركة، وكل الحركات (الأقدم أولاً). المبالغ بالدولار. الرد مرقّم: meta يعدّ lines، أما wallets وby_category فتغطيان الفترة كلها.
معاملات الاستعلام
| الاسم | النوع | مطلوب | الوصف |
|---|---|---|---|
from |
string (date) |
اختياري |
أول يوم مثال |
to |
string (date) |
اختياري |
آخر يوم مثال |
wallet |
string |
اختياري |
هذه المحفظة فقط: إحدى القيم: |
category |
string |
اختياري |
هذا النوع من الحركات فقط، مثل النمط مثال |
per_page |
integer |
اختياري |
حجم الصفحة من 1 إلى 500 (الافتراضي 100). القيمة خارج المجال لا تُرفض بل تُقرَّب إلى أقرب حدّ، وتعود القيمة الفعلية في الحد الأدنى 1الحد الأقصى 500الافتراضي |
page |
integer |
اختياري |
رقم الصفحة ويبدأ من 1. القيمة غير الصالحة أو الأصغر من 1 تُعامل على أنها 1. والصفحة بعد الأخيرة تعيد قائمة فارغة. الحد الأدنى 1الافتراضي |
الردود
200 كشف الحساب.
كشف الحساب.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
object |
مطلوب |
كشف المحفظة لفترة. كل المبالغ بالدولار. |
period |
object |
مطلوب |
الفترة المطبّقة فعلياً. |
from |
string (date) |
مطلوب |
أول يوم ( |
to |
string (date) |
مطلوب |
آخر يوم ( |
currency |
string |
مطلوب |
قيمة ثابتة |
wallets |
array<object> |
مطلوب |
الرصيد الافتتاحي والختامي لكل محفظة. تغطي الفترة كلها بصرف النظر عن الصفحة. |
wallet |
string |
مطلوب |
رمز المحفظة. إحدى القيم: |
name |
string |
مطلوب |
تسمية المحفظة بلغة الطلب. |
opening |
number |
مطلوب |
الرصيد قبل الفترة. |
credits |
number |
مطلوب |
مجموع الإيداعات في الفترة. |
debits |
number |
مطلوب |
مجموع السحوبات في الفترة. |
closing |
number |
مطلوب |
الرصيد في نهاية الفترة. |
count |
integer |
مطلوب |
عدد الحركات. |
by_category |
array<object> |
مطلوب |
ملخص لكل نوع حركة. يغطي الفترة كلها بصرف النظر عن الصفحة. |
category |
string |
مطلوب |
رمز نوع الحركة، مثل |
name |
string |
مطلوب |
تسمية النوع بلغة الطلب. |
credits |
number |
مطلوب |
إيداعات هذا النوع. |
debits |
number |
مطلوب |
سحوبات هذا النوع. |
count |
integer |
مطلوب |
عدد الحركات. |
lines |
array<object> |
مطلوب |
حركات الصفحة المطلوبة، الأقدم أولاً (التاريخ ثم المعرّف). يسري الترقيم على هذه القائمة فقط. |
id |
integer |
مطلوب |
معرّف الحركة. |
date |
string (date-time) |
مطلوب |
وقت الحركة (ISO 8601). |
wallet |
string |
مطلوب |
رمز المحفظة. |
wallet_name |
string |
مطلوب |
تسمية المحفظة. |
type |
string |
مطلوب |
رمز نوع الحركة. |
type_name |
string |
مطلوب |
تسمية النوع. |
credit |
number |
مطلوب |
مبلغ الإيداع (0 للسحب). |
debit |
number |
مطلوب |
مبلغ السحب (0 للإيداع). |
balance |
number |
مطلوب |
رصيد المحفظة بعد الحركة. |
description |
string | null |
مطلوب |
وصف الحركة. |
parcel |
string | null |
مطلوب |
رقم التتبع عندما تتعلق الحركة بطرد. |
meta |
Meta |
مطلوب |
كتلة الترقيم. لا توجد روابط ولا مؤشر (cursor). |
مثال
{
"success": true,
"data": {
"period": {
"from": "2026-01-01",
"to": "2026-01-31"
},
"currency": "USD",
"wallets": [
{
"wallet": "recharge",
"name": "Shipping balance",
"opening": 50,
"credits": 200,
"debits": 132.5,
"closing": 117.5,
"count": 41
}
],
"by_category": [
{
"category": "parcel_created",
"name": "Parcel creation fee",
"credits": 0,
"debits": 132.5,
"count": 38
}
],
"lines": [
{
"id": 9811,
"date": "2026-01-02T10:14:00+00:00",
"wallet": "recharge",
"wallet_name": "Shipping balance",
"type": "parcel_created",
"type_name": "Parcel creation fee",
"credit": 0,
"debit": 3.5,
"balance": 46.5,
"description": "Example description",
"parcel": "DS-000000"
}
]
},
"meta": {
"page": 1,
"per_page": 20,
"total": 1,
"last_page": 1
}
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
أمثلة برمجية
curl
curl -X GET "https://YOUR_DOMAIN/api/v1/statement?from=2026-01-01&to=2026-01-31&category=parcel_created" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/statement?from=2026-01-01&to=2026-01-31&category=parcel_created");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/statement?from=2026-01-01&to=2026-01-31&category=parcel_created", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.get(
"https://YOUR_DOMAIN/api/v1/statement",
headers={
"Authorization": f"Bearer {os.environ['DS_API_KEY']}",
"Accept": "application/json",
},
params={
"from": "2026-01-01",
"to": "2026-01-31",
"category": "parcel_created",
},
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
/webhooks/events
#
قائمة الأحداث التي يمكنك الاشتراك بها
تعرض أسماء الأحداث مع اسمها المختصر ووصفها بلغة الطلب. أرسل * أو أسماءً بعينها في events عند إنشاء الرابط. لا تُعرض ping لأنها لا تُختار.
الردود
200 الأحداث.
الأحداث.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
array<object> |
مطلوب | |
event |
string |
مطلوب |
اسم الحدث. إحدى القيم: |
name |
string |
مطلوب |
اسم مختصر بلغة الطلب. |
description |
string |
مطلوب |
متى يُرسل، بلغة الطلب. |
مثال
{
"success": true,
"data": [
{
"event": "parcel.delivered",
"name": "Delivered",
"description": "The parcel was delivered (fully or partially) — includes the collected amount."
}
]
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
أمثلة برمجية
curl
curl -X GET "https://YOUR_DOMAIN/api/v1/webhooks/events" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/webhooks/events");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/webhooks/events", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.get(
"https://YOUR_DOMAIN/api/v1/webhooks/events",
headers={
"Authorization": f"Bearer {os.environ['DS_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
/webhooks
#
قائمة روابط الويب هوك لديك
تعرض روابط الويب هوك لديك. لا يُرجَع مفتاح التوقيع أبداً. القائمة غير مرقّمة.
الردود
200 روابطك.
روابطك.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
array<Webhook> |
مطلوب |
مثال
{
"success": true,
"data": [
{
"id": 7,
"name": "ERP",
"url": "https://example.com/hooks/delivery",
"events": [
"parcel.delivered",
"parcel.returned"
],
"active": true,
"disabled_reason": null,
"last_status": null,
"last_error": null,
"last_sent_at": null
}
]
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
أمثلة برمجية
curl
curl -X GET "https://YOUR_DOMAIN/api/v1/webhooks" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/webhooks");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/webhooks", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.get(
"https://YOUR_DOMAIN/api/v1/webhooks",
headers={
"Authorization": f"Bearer {os.environ['DS_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
/webhooks
#
إضافة رابط ويب هوك
تنشئ رابطاً وتُرجع مفتاح توقيعه (secret) مرة واحدة. تحتاج باقة فيها ميزة الويب هوك (403 plan_feature) وتتيح 10 روابط كحد أقصى، أو حدّ باقتك إن كان أقل (422 limit_reached). يجب أن يكون العنوان https وعاماً وبلا اسم مستخدم أو كلمة مرور وعلى المنفذ 443 أو 8443. وطريقة توقيع الرسائل وإعادة إرسالها في مقالات الويب هوك.
جسم الطلب
application/json · مطلوب
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
name |
string | null |
اختياري |
تسمية اختيارية بحد أقصى 100 محرف. الحد الأقصى للطول 100 |
url |
string (uri) |
مطلوب |
عنوان HTTPS بحد أقصى 500 محرف. يجب أن يُحلّ النطاق إلى عناوين عامة فقط، دون اسم مستخدم أو كلمة مرور، وعلى المنفذ 443 أو 8443. ولا تُتبع التحويلات. الحد الأقصى للطول 500النمط |
events |
array<string> |
مطلوب |
الأحداث المطلوب استقبالها: عنصر واحد على الأقل، كل منها إحدى القيم: الحد الأدنى للعناصر 1 |
active |
boolean |
اختياري |
هل الرابط مفعّل (الافتراضي true). |
مثال
{
"name": "ERP",
"url": "https://example.com/hooks/delivery",
"events": [
"parcel.delivered",
"parcel.returned"
]
}الردود
201 تم إنشاء الرابط.
تم إنشاء الرابط.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
object |
مطلوب |
رابط ويب هوك مع مفتاح التوقيع (يظهر مرة واحدة). |
id |
integer |
مطلوب |
معرّف الرابط. |
name |
string | null |
مطلوب |
التسمية التي أعطيتها للرابط. |
url |
string |
مطلوب |
عنوان HTTPS الذي يستقبل الرسائل. |
events |
array<string> |
مطلوب |
الأحداث المشترك بها؛ |
active |
boolean |
مطلوب |
تكون false عند التعطيل، ومنه الإيقاف التلقائي بعد 40 محاولة فاشلة متتالية. |
disabled_reason |
string | null |
مطلوب |
سبب إيقاف الرابط تلقائياً. |
last_status |
integer | null |
مطلوب |
حالة HTTP لآخر محاولة إرسال. |
last_error |
string | null |
مطلوب |
خطأ آخر محاولة فاشلة. |
last_sent_at |
string (date-time) | null |
مطلوب |
وقت آخر محاولة (ISO 8601). |
secret |
string |
مطلوب |
مفتاح التوقيع ( |
مثال
{
"success": true,
"data": {
"id": 7,
"name": "ERP",
"url": "https://example.com/hooks/delivery",
"events": [
"parcel.delivered",
"parcel.returned"
],
"active": true,
"disabled_reason": null,
"last_status": null,
"last_error": null,
"last_sent_at": null,
"secret": "whsec_EXAMPLE_ONLY_NOT_A_REAL_SECRET"
}
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
422 validation_failed:
validation_failed: حقل مفقود أو خاطئ (يجب أن يكون العنوان https وعاماً وعلى المنفذ 443 أو 8443، وكل حدث * أو اسماً بعينه). limit_reached: لديك أصلاً العدد الأقصى من الروابط.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Not https
{
"success": false,
"error": {
"code": "validation_failed",
"message": "The URL must start with https://",
"fields": {
"url": [
"The URL must start with https://"
]
}
}
}مثال — Too many endpoints
{
"success": false,
"error": {
"code": "limit_reached",
"message": "You have reached your plan limit: 10 webhook links."
}
}أمثلة برمجية
curl
curl -X POST "https://YOUR_DOMAIN/api/v1/webhooks" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "ERP",
"url": "https://example.com/hooks/delivery",
"events": [
"parcel.delivered",
"parcel.returned"
]
}'PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/webhooks");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_API_KEY"),
"Accept: application/json",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
'name' => 'ERP',
'url' => 'https://example.com/hooks/delivery',
'events' => [
'parcel.delivered',
'parcel.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
const response = await fetch("https://YOUR_DOMAIN/api/v1/webhooks", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.DS_API_KEY}`,
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "ERP",
"url": "https://example.com/hooks/delivery",
"events": [
"parcel.delivered",
"parcel.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
import os
import requests
response = requests.post(
"https://YOUR_DOMAIN/api/v1/webhooks",
headers={
"Authorization": f"Bearer {os.environ['DS_API_KEY']}",
"Accept": "application/json",
},
json={
"name": "ERP",
"url": "https://example.com/hooks/delivery",
"events": [
"parcel.delivered",
"parcel.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"])
الطريقة DELETE
/webhooks/{id}
#
حذف رابط ويب هوك
تحذف الرابط. الرسائل التي ما زالت بانتظار إعادة الإرسال تُعلَّم فاشلة عند حلول موعدها.
معاملات المسار
| الاسم | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
integer |
مطلوب |
معرّف رابط الويب هوك (من مثال |
الردود
200 تم حذف الرابط.
تم حذف الرابط.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
object |
مطلوب |
نتيجة الحذف. |
deleted |
boolean |
مطلوب |
قيمة ثابتة |
مثال
{
"success": true,
"data": {
"deleted": true
}
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
404 not_found:
not_found: لا يوجد هذا الرابط في حسابك.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Unknown webhook endpoint
{
"success": false,
"error": {
"code": "not_found",
"message": "Link not found."
}
}أمثلة برمجية
curl
curl -X DELETE "https://YOUR_DOMAIN/api/v1/webhooks/7" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/webhooks/7");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/webhooks/7", {
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.delete(
"https://YOUR_DOMAIN/api/v1/webhooks/7",
headers={
"Authorization": f"Bearer {os.environ['DS_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"])
الطريقة PATCH
/webhooks/{id}
#
تعديل رابط ويب هوك
تعدّل name أو url أو events أو active؛ أرسل ما تريد تغييره فقط. تفعيل active من جديد يصفّر عدّاد الإخفاق ويمسح سبب الإيقاف.
معاملات المسار
| الاسم | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
integer |
مطلوب |
معرّف رابط الويب هوك (من مثال |
جسم الطلب
application/json · مطلوب
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
name |
string | null |
اختياري |
التسمية بحد أقصى 100 محرف. الحد الأقصى للطول 100 |
url |
string (uri) |
اختياري |
عنوان HTTPS الجديد (بالقواعد نفسها عند الإنشاء). الحد الأقصى للطول 500النمط |
events |
array<string> |
اختياري |
القائمة الجديدة للأحداث (واحد على الأقل). إحدى القيم: الحد الأدنى للعناصر 1 |
active |
boolean |
اختياري |
تفعيله من جديد يصفّر عدّاد الإخفاق ويمسح سبب الإيقاف. |
مثال
{
"active": true
}الردود
200 الرابط بعد التعديل.
الرابط بعد التعديل.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
Webhook |
مطلوب |
رابط ويب هوك (لا يُرجَع مفتاح التوقيع أبداً). |
مثال
{
"success": true,
"data": {
"id": 7,
"name": "ERP",
"url": "https://example.com/hooks/delivery",
"events": [
"parcel.delivered",
"parcel.returned"
],
"active": true,
"disabled_reason": null,
"last_status": null,
"last_error": null,
"last_sent_at": null
}
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
404 not_found:
not_found: لا يوجد هذا الرابط في حسابك.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Unknown webhook endpoint
{
"success": false,
"error": {
"code": "not_found",
"message": "Link not found."
}
}422 validation_failed:
validation_failed: حقل خاطئ (بالقواعد نفسها عند الإنشاء).
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Not https
{
"success": false,
"error": {
"code": "validation_failed",
"message": "The URL must start with https://",
"fields": {
"url": [
"The URL must start with https://"
]
}
}
}أمثلة برمجية
curl
curl -X PATCH "https://YOUR_DOMAIN/api/v1/webhooks/7" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"active": true
}'PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/webhooks/7");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_API_KEY"),
"Accept: application/json",
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
'active' => true,
]),
]);
$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
const response = await fetch("https://YOUR_DOMAIN/api/v1/webhooks/7", {
method: "PATCH",
headers: {
"Authorization": `Bearer ${process.env.DS_API_KEY}`,
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
"active": true
}),
});
const json = await response.json();
if (!json.success) {
throw new Error(`${response.status} ${json.error.code}: ${json.error.message}`);
}
console.log(json.data);Python
import os
import requests
response = requests.patch(
"https://YOUR_DOMAIN/api/v1/webhooks/7",
headers={
"Authorization": f"Bearer {os.environ['DS_API_KEY']}",
"Accept": "application/json",
},
json={
"active": True,
},
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
/webhooks/{id}/test
#
إرسال رسالة اختبار
ترسل رسالة ping موقَّعة إلى الرابط وتبلغك بحالة HTTP التي ردّ بها نظامك. الاختبار الناجح يصفّر عدّاد الإخفاق. وهي محدودة بـ 10 طلبات في الدقيقة على مستوى المسار (نحو 5 عملياً، انظر ملاحظات حدود الطلبات).
معاملات المسار
| الاسم | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
integer |
مطلوب |
معرّف رابط الويب هوك (من مثال |
الردود
200 ردّ نظامك بحالة 2xx.
ردّ نظامك بحالة 2xx.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
success |
boolean |
مطلوب |
قيمة ثابتة |
data |
object |
مطلوب |
نتيجة رسالة اختبار ناجحة. |
delivered |
boolean |
مطلوب |
قيمة ثابتة |
response_status |
integer |
مطلوب |
حالة HTTP التي ردّ بها نظامك. |
مثال
{
"success": true,
"data": {
"delivered": true,
"response_status": 200
}
}401 مفتاح الـ API مفقود أو غير معروف. ردّ مشترك، انظر أدناه
403 الوصول مرفوض. ردّ مشترك، انظر أدناه
404 not_found:
not_found: لا يوجد هذا الرابط في حسابك.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Unknown webhook endpoint
{
"success": false,
"error": {
"code": "not_found",
"message": "Link not found."
}
}422 delivery_failed:
delivery_failed: لم تصل الرسالة (ردّ غير 2xx أو تحويل أو انتهاء مهلة أو خطأ اتصال). يحمل response_status الحالة التي أعادها نظامك، أو null.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Your system refused
{
"success": false,
"error": {
"code": "delivery_failed",
"message": "Not delivered: your system answered 500",
"response_status": 500
}
}أمثلة برمجية
curl
curl -X POST "https://YOUR_DOMAIN/api/v1/webhooks/7/test" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"PHP
<?php
$ch = curl_init("https://YOUR_DOMAIN/api/v1/webhooks/7/test");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("DS_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
const response = await fetch("https://YOUR_DOMAIN/api/v1/webhooks/7/test", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.DS_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
import os
import requests
response = requests.post(
"https://YOUR_DOMAIN/api/v1/webhooks/7/test",
headers={
"Authorization": f"Bearer {os.environ['DS_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"])الكائنات
كائنات تُرجعها عدة نقاط نهاية وأحداث ويب هوك. يوصَف كل منها مرة واحدة هنا، وتحيل إليه الجداول الأخرى.
Parcel
#
الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً).
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
integer |
مطلوب |
معرّف الطرد. |
tracking_number |
string |
مطلوب |
رقم التتبع. استخدمه في مسارات |
reference |
string | null |
مطلوب |
مرجعك الخاص (رقم الطلب) المرسل عند الإنشاء. |
stage |
string |
مطلوب |
حالة مبسطة وثابتة. يفضّل الاعتماد عليها بدل إحدى القيم: |
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). |
Meta
#
كتلة الترقيم. لا توجد روابط ولا مؤشر (cursor).
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
page |
integer |
مطلوب |
الصفحة الحالية. |
per_page |
integer |
مطلوب |
حجم الصفحة الفعلي. |
total |
integer |
مطلوب |
عدد السجلات بعد تطبيق الفلاتر. |
last_page |
integer |
مطلوب |
عدد الصفحات (1 عند عدم وجود نتائج). |
Webhook
#
رابط ويب هوك (لا يُرجَع مفتاح التوقيع أبداً).
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
integer |
مطلوب |
معرّف الرابط. |
name |
string | null |
مطلوب |
التسمية التي أعطيتها للرابط. |
url |
string |
مطلوب |
عنوان HTTPS الذي يستقبل الرسائل. |
events |
array<string> |
مطلوب |
الأحداث المشترك بها؛ |
active |
boolean |
مطلوب |
تكون false عند التعطيل، ومنه الإيقاف التلقائي بعد 40 محاولة فاشلة متتالية. |
disabled_reason |
string | null |
مطلوب |
سبب إيقاف الرابط تلقائياً. |
last_status |
integer | null |
مطلوب |
حالة HTTP لآخر محاولة إرسال. |
last_error |
string | null |
مطلوب |
خطأ آخر محاولة فاشلة. |
last_sent_at |
string (date-time) | null |
مطلوب |
وقت آخر محاولة (ISO 8601). |
أحداث الويب هوك
ترسل المنصة هذه الرسائل إلى عناوين HTTPS التي تسجّلها (الويب هوك الصادر). كل رسالة طلب POST بصيغة JSON وموقَّع، ويُعاد إرساله إذا لم يردّ نظامك بحالة 2xx. يعرض كل حدث أدناه جسم رسالته، وتشترك الأحداث كلها في الترويسات والتوقيع نفسها.
ترويسات الطلب
| الاسم | النوع | الوصف |
|---|---|---|
X-DS-Event | string | اسم الحدث (مثل |
X-DS-Event-Id | string | معرّف الحدث، |
X-DS-Delivery | string (uuid) | معرّف UUID لهذه الرسالة إلى هذا الرابط. هو نفسه عبر المحاولات. |
X-DS-Attempt | integer | رقم المحاولة ويبدأ من 1. |
X-DS-Timestamp | string | وقت الإرسال بثواني Unix ويتجدد في كل محاولة. وهو جزء من النص الموقَّع. |
X-DS-Signature | string |
|
التحقق من توقيع الويب هوك (X-DS-Signature)
حدث POST parcel.created
#
طرد جديد
أُنشئ طرد (من اللوحة أو الـ API أو متجر مربوط). الطرد الجديد يرسل عادةً هذا الحدث ثم parcel.status_changed (الحالة 5).
جسم الرسالة
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
string |
مطلوب |
معرّف الحدث ( النمط |
event |
string |
مطلوب |
قيمة ثابتة |
created_at |
string (date-time) |
مطلوب |
وقت إنشاء الحدث (ISO 8601). |
data |
Parcel |
مطلوب |
الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً). |
مثال
{
"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"
}
}حدث POST parcel.status_changed
#
تغيّرت حالة الطرد
أي تغيير في الحالة عبر مسار عمل الطرد، ومنه الانتقال التلقائي إلى الحالة 5 بعد الإنشاء مباشرة. وقد يرسل التغيير الواحد هذا الحدث وحدث المرحلة (لكل منهما معرّف حدث خاص). لا يُرسل من نماذج الموظفين المخصصة للاستلام والمراكز ولا من بعض نماذج التراجع: اقرأ الطرد عندما تحتاج إلى حالته الحالية.
جسم الرسالة
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
string |
مطلوب |
معرّف الحدث ( النمط |
event |
string |
مطلوب |
قيمة ثابتة |
created_at |
string (date-time) |
مطلوب |
وقت إنشاء الحدث (ISO 8601). |
data |
Parcel |
مطلوب |
الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً). |
مثال
{
"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"
}
}حدث POST parcel.out_for_delivery
#
خرج للتوصيل
الطرد مع المندوب (الحالتان 7 و8).
جسم الرسالة
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
string |
مطلوب |
معرّف الحدث ( النمط |
event |
string |
مطلوب |
قيمة ثابتة |
created_at |
string (date-time) |
مطلوب |
وقت إنشاء الحدث (ISO 8601). |
data |
Parcel |
مطلوب |
الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً). |
مثال
{
"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"
}
}حدث POST parcel.delivered
#
تم التسليم
سُلِّم الطرد كاملاً أو جزئياً (الحالتان 9 و32). يتضمن data.cod_collected المبلغ المحصَّل.
جسم الرسالة
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
string |
مطلوب |
معرّف الحدث ( النمط |
event |
string |
مطلوب |
قيمة ثابتة |
created_at |
string (date-time) |
مطلوب |
وقت إنشاء الحدث (ISO 8601). |
data |
Parcel |
مطلوب |
الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً). |
مثال
{
"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"
}
}حدث POST parcel.returning
#
قيد الإرجاع
تعذّر التسليم والطرد في طريق العودة.
جسم الرسالة
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
string |
مطلوب |
معرّف الحدث ( النمط |
event |
string |
مطلوب |
قيمة ثابتة |
created_at |
string (date-time) |
مطلوب |
وقت إنشاء الحدث (ISO 8601). |
data |
Parcel |
مطلوب |
الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً). |
مثال
{
"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"
}
}حدث POST parcel.returned
#
رُدّ للتاجر
استلم التاجر الطرد المرتجع (الحالتان 30 و13).
جسم الرسالة
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
string |
مطلوب |
معرّف الحدث ( النمط |
event |
string |
مطلوب |
قيمة ثابتة |
created_at |
string (date-time) |
مطلوب |
وقت إنشاء الحدث (ISO 8601). |
data |
Parcel |
مطلوب |
الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً). |
مثال
{
"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"
}
}حدث POST parcel.cancelled
#
أُلغي
أبلغت شركة الشحن الخارجية المربوطة بإلغاء الطرد وعاد المبلغ إلى رصيدك. لا يُرسل عند الإلغاء عبر POST /parcels/{tracking}/cancel.
جسم الرسالة
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
string |
مطلوب |
معرّف الحدث ( النمط |
event |
string |
مطلوب |
قيمة ثابتة |
created_at |
string (date-time) |
مطلوب |
وقت إنشاء الحدث (ISO 8601). |
data |
Parcel |
مطلوب |
الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً). |
مثال
{
"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"
}
}حدث POST parcel.awaiting_funds
#
بانتظار الرصيد
حُفظ الطلب لكن رصيدك لا يكفي (مع wait_for_balance أو طلبات المتاجر). يكتمل عند شحن الرصيد.
جسم الرسالة
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
string |
مطلوب |
معرّف الحدث ( النمط |
event |
string |
مطلوب |
قيمة ثابتة |
created_at |
string (date-time) |
مطلوب |
وقت إنشاء الحدث (ISO 8601). |
data |
Parcel |
مطلوب |
الطرد كما ترجعه الواجهة وكما تحمله رسائل الويب هوك (الحقول نفسها دائماً). |
مثال
{
"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"
}
}حدث POST wallet.topup
#
شُحن الرصيد
أُضيف رصيد إلى محفظة الشحن لديك بطلب شحن تمت الموافقة عليه أو بدفع إلكتروني. للتجّار فقط.
جسم الرسالة
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
string |
مطلوب |
معرّف الحدث ( النمط |
event |
string |
مطلوب |
قيمة ثابتة |
created_at |
string (date-time) |
مطلوب |
وقت إنشاء الحدث (ISO 8601). |
data |
object |
مطلوب |
بيانات |
id |
string |
مطلوب |
معرّف عملية الشحن ( |
method |
string | null |
مطلوب |
طريقة الدفع أو البوابة. |
source |
string |
مطلوب |
إحدى القيم: |
reference |
string | null |
اختياري |
مرجع الدفع. يظهر مع |
amount |
number |
مطلوب |
المبلغ بالدولار. |
currency |
string |
مطلوب |
قيمة ثابتة |
recharge_balance |
number |
مطلوب |
رصيد الشحن بعد الحدث بالدولار. |
مثال
{
"id": "evt_abcdefghijklmnopqrstuvwx",
"event": "wallet.topup",
"created_at": "2026-01-01T12:10:00+00:00",
"data": {
"id": "topup_1",
"method": "bank_transfer",
"source": "manual",
"amount": 100,
"currency": "USD",
"recharge_balance": 150
}
}حدث POST wallet.withdrawal
#
تقرّر طلب السحب
قُبل طلب سحب المستحقات أو رُفض. للتجّار فقط.
جسم الرسالة
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
string |
مطلوب |
معرّف الحدث ( النمط |
event |
string |
مطلوب |
قيمة ثابتة |
created_at |
string (date-time) |
مطلوب |
وقت إنشاء الحدث (ISO 8601). |
data |
object |
مطلوب |
بيانات |
id |
string |
مطلوب |
معرّف السحب ( |
status |
string |
مطلوب |
إحدى القيم: |
reference |
string | null |
اختياري |
مرجع الدفع. يظهر عند |
note |
string | null |
اختياري |
ملاحظة الإدارة. تظهر عند |
amount |
number |
مطلوب |
المبلغ بالدولار. |
currency |
string |
مطلوب |
قيمة ثابتة |
recharge_balance |
number |
مطلوب |
رصيد الشحن بعد الحدث بالدولار. |
مثال
{
"id": "evt_abcdefghijklmnopqrstuvwx",
"event": "wallet.withdrawal",
"created_at": "2026-01-01T12:10:00+00:00",
"data": {
"id": "withdrawal_1",
"status": "approved",
"reference": null,
"note": null,
"amount": 50,
"currency": "USD",
"recharge_balance": 150
}
}حدث POST ping
#
رسالة اختبار
تُرسل عبر POST /webhooks/{id}/test (وزر «إرسال تجربة» في اللوحة). لا يمكن اختيارها حدثاً ولا تُعاد تلقائياً.
جسم الرسالة
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id |
string |
مطلوب |
معرّف الحدث ( النمط |
event |
string |
مطلوب |
قيمة ثابتة |
created_at |
string (date-time) |
مطلوب |
وقت إنشاء الحدث (ISO 8601). |
data |
object |
مطلوب |
بيانات رسالة الاختبار |
message |
string |
مطلوب |
نص اختبار مترجم. |
مثال
{
"id": "evt_abcdefghijklmnopqrstuvwx",
"event": "ping",
"created_at": "2026-01-01T12:10:00+00:00",
"data": {
"message": "Test message from Delivery Syria"
}
}الأخطاء
كل خطأ تثيره الواجهة نفسها يستخدم غلاف JSON نفسه. ابنِ منطق برنامجك على error.code وحالة HTTP لا على نص الرسالة. هذه هي الرموز التي يمكن أن تُرجعها هذه الواجهة؛ أما الأخطاء التي يثيرها الإطار قبل تنفيذ كود الواجهة (حدود IP والمسار والمسارات المجهولة والطرق الخاطئة) فتأتي بصيغة بسيطة مختلفة {"message": "..."}.
الردود المشتركة
قد تصدر هذه الردود عن أي نقطة نهاية في هذه الواجهة. وتسرد كل نقطة ردودها الخاصة فقط وتحيل إلى هنا لهذه الردود.
401 مفتاح الـ API مفقود أو غير معروف.
مفتاح الـ API مفقود أو غير معروف. unauthenticated: لا مفتاح في ترويسة Authorization: Bearer. invalid_key: المفتاح غير معروف (جُدِّد أو أُلغي أو كُتب خطأً أو هو من نوع آخر).
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — No key
{
"success": false,
"error": {
"code": "unauthenticated",
"message": "Send the key in the header: Authorization: Bearer <API key>"
}
}مثال — Unknown key
{
"success": false,
"error": {
"code": "invalid_key",
"message": "The key is invalid or revoked. Generate a new key from the merchant dashboard."
}
}403 الوصول مرفوض.
الوصول مرفوض. account_inactive: المستخدم أو ملف التاجر موقوف أو غير موجود. api_not_allowed: التاجر تابع لشركة توصيل (الواجهة لتجّار المنصة فقط). plan_feature: الباقة لا تتضمن الـ API (أو ميزة الويب هوك عند POST /webhooks)، أو لا توجد للتاجر باقة فعّالة.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Suspended account
{
"success": false,
"error": {
"code": "account_inactive",
"message": "Merchant account suspended or not found."
}
}مثال — Company merchant
{
"success": false,
"error": {
"code": "api_not_allowed",
"message": "Your account belongs to a delivery company — the API is for platform merchant accounts only."
}
}مثال — Plan without the API
{
"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
{
"success": false,
"error": {
"code": "rate_limited",
"message": "Localized text with the limit and the wait time",
"retry_after": 42
}
}مثال — IP or route limit
{
"message": "Too Many Attempts."
}500 خطأ غير متوقع في الخادم.
خطأ غير متوقع في الخادم. تتضمن الرسالة مرجعاً قصيراً يستطيع الدعم العثور عليه في السجلات؛ أعد الطلب فقط إذا كانت نتيجته مجهولة.
الترويسات: X-RateLimit-Limit X-RateLimit-Remaining
مثال — Server error
{
"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_key | 401 | المفتاح غير معروف (جُدِّد أو أُلغي أو كُتب خطأً أو هو من نوع آخر). |
unauthenticated | 401 | لا مفتاح في ترويسة |
insufficient_balance | 402 | رصيد المحفظة لا يكفي (تذكر الرسالة المبلغ المطلوب والمتاح). أرسل |
account_inactive | 403 | المستخدم أو ملف التاجر موقوف أو غير موجود. |
api_not_allowed | 403 | التاجر تابع لشركة توصيل (الواجهة لتجّار المنصة فقط). |
plan_feature | 403 | الباقة لا تتضمن الـ API (أو ميزة الويب هوك عند |
not_found | 404 | لا يوجد طرد بهذا الرقم أو المرجع في حسابك (والطرد الملغى لم يعد موجوداً). |
not_cancellable | 409 | خرج الطرد من الحالة «معلّق» أو «مستلم في المستودع»، أو أُرسل إلى شركة شحن خارجية. |
carrier_error | 422 | رفضت شركة الشحن الخارجية الطرد أو أن حساب الشركة غير صالح للاستخدام. |
delivery_failed | 422 | لم تصل الرسالة (ردّ غير 2xx أو تحويل أو انتهاء مهلة أو خطأ اتصال). يحمل |
limit_reached | 422 | لديك أصلاً العدد الأقصى من الروابط. |
quote_failed | 422 | تعذّر حساب السعر. |
validation_failed | 422 |
|
rate_limited | 429 | |
server_error | 500 |
مصادر إضافية
- المصادقة ومفاتيح الـ API
- مرجع واجهة التاجر API v1
- الصفحات والفلاتر في الـ API
- إصدارات الواجهة وإعادة المحاولة الآمنة (Idempotency)
- الويب هوك الصادر: إشعارات فورية لنظامك
- إعادة محاولة الويب هوك والإيقاف التلقائي
- التحقق من توقيع الويب هوك (X-DS-Signature)
- واجهة شركة التوصيل في Delivery Syria
- مرجع واجهات الـ API