الطلبات التي تنشئها التطبيقات
إنشاء طلبات بالأسعار التي وافق عليها التاجر، والبنود المخصصة، والملاحظة والوسوم وخصائص التطبيق، وملف المتجر، والبحث في المنتجات.
في هذه الصفحة
هذه الصفحة لمن يحوّل تطبيقه عرض سعر أو فاتورة أو محادثة إلى طلب حقيقي: أدوات عروض الأسعار، وطلبات الجملة، ومساعدو المبيعات. في نهايتها تعرف كيف تنشئ طلباً بالأسعار التي اتفقت عليها، وما تفعله المنصّة به، وما يراه التاجر، وكيف تبقي الطلب مرتبطاً بسجلّك أنت بعد ذلك. المراجعة 2026-09-10 من واجهة المنصّة v1، وكلها إضافية.
ما يفتحه هذا#
POST /ordersينشئ طلباً بأسعار الوحدة التي ترسلها، لخيارات من الكتالوج ولبنود مخصصة لا وجود لها في الكتالوج أصلاً. تعيد المنصّة احتساب المجاميع، وتخصم المخزون، وتربط العميل، وتنبّه التاجر، وتطلقorder.createdبقيمةsource: "app"، تماماً كطلب من المتجر.PATCH /orders/{id}يحدّث ملاحظة الطلب، ويضيف وسوماً أو يزيلها، ويدمج خصائص تعود لتطبيقك وحده. الخاصيةreferenceتصير شريحة في صفحة الطلب عند التاجر.GET /storeيعطيك عملات المتجر، وجدول الصرف الذي تطبّقه صفحة الدفع، وطرق الدفع المفعّلة، وقائمة المحافظات، من دون أي نطاق.GET /products?q=يبحث في الكتالوج وGET /products/variants?ids=يعيد التحقق من الخيارات خلف بنودك قبل أن تلتزم.
النطاقات#
| النطاق | الجملة التي يراها التاجر | ما يفتحه |
|---|---|---|
orders:create |
إنشاء طلبات بأسعار يحددها التطبيق | POST /orders |
orders:write |
تحديث حالة الطلب وملاحظته ووسومه | PATCH /orders/{id}، PATCH /orders/{id}/status |
products:read |
قراءة المنتجات وخياراتها | GET /products، GET /products/variants |
orders:create منفصل عن orders:write عن قصد: التاجر الذي وافق على تحديث الحالة والملاحظة والوسوم لا يكتسب إنشاء الطلبات بصمت أبداً. ولا يتضمّن قراءة الطلبات أيضاً؛ جسم 201 هو القراءة الوحيدة التي يمنحها، فاطلب orders:read كذلك إن كنت ستعرض الطلبات أو تجلبها لاحقاً. تعرض شاشة الموافقة تحت النطاق العبارة «تظهر هذه الطلبات في لوحة التحكم موسومة باسم التطبيق، ويُخصم المخزون كأي طلب آخر.» الجدول الكامل في مرجع النطاقات.
أنشئ طلباً#
يتطلب orders:create وIdempotency-Key. اشتقّ المفتاح من سجلّك أنت، معرّف عرض السعر أو الفاتورة، فتعيد المهمة المكررة الطلب المسجّل بدلاً من إنشاء طلب ثانٍ.
curl -X POST https://dukkan.one/platform-api/v1/orders \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Idempotency-Key: quote-Q-1042-accepted" \
-H "Content-Type: application/json" \
-d @order.json{
"currency": "SYP",
"status": "placed",
"items": [
{
"variant_id": "c0ffee00-0001-4e8f-9b70-2d1c3e4f5a6b",
"quantity": 2,
"unit_price_minor": 225000
},
{
"variant_id": null,
"name": "تغليف هدية مع بطاقة إهداء",
"quantity": 1,
"unit_price_minor": 15000
}
],
"discount": {
"amount_minor": 15000,
"title": "خصم عرض السعر Q-1042"
},
"shipping": {
"amount_minor": 25000,
"method": "delivery"
},
"customer": {
"name": "ليان الحلبي",
"phone": "+963944123456",
"email": null
},
"shipping_address": {
"address": "شارع بغداد، بناء 22، الطابق الثالث",
"province": "damascus",
"city": "دمشق",
"notes": null
},
"payment_method": "cod",
"exchange_rate": null,
"note": "عرض السعر Q-1042 مقبول عبر واتساب",
"tags": [
"عرض سعر",
"جملة"
],
"attributes": {
"reference": {
"kind": "quote",
"number": "Q-1042",
"url": "https://offers.example.com/quotes/Q-1042"
},
"quote_id": "q_8f3a"
},
"inventory": "decrement"
}استجابة 201 هي الطلب كاملاً، مع kind على كل بند، وsource: "app"، وملاحظتك ووسومك وخصائصك، وبيانات العميل التي أرسلتها. تُعاد هذه البيانات بصرف النظر عن clients:read، لأنك أنت من أرسلها.
{
"data": {
"id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6c",
"order_number": "1043",
"status": "placed",
"payment_status": "unpaid",
"source": "app",
"line_pricing": "gross",
"subtotal": {
"amount_minor": 465000,
"currency": "SYP",
"decimals": 0
},
"discount": {
"amount_minor": 15000,
"currency": "SYP",
"decimals": 0
},
"shipping": {
"amount_minor": 25000,
"currency": "SYP",
"decimals": 0
},
"tax": {
"amount_minor": 0,
"currency": "SYP",
"decimals": 0
},
"total": {
"amount_minor": 475000,
"currency": "SYP",
"decimals": 0
},
"paid": {
"amount_minor": 0,
"currency": "SYP",
"decimals": 0
},
"refunded": {
"amount_minor": 0,
"currency": "SYP",
"decimals": 0
},
"exchange_rate": null,
"tags": [
"عرض سعر",
"جملة"
],
"created_at": "2026-09-10T09:30:00.412Z",
"updated_at": "2026-09-10T09:30:00.412Z",
"items": [
{
"id": "a1b2c3d4-0002-4e8f-9b70-2d1c3e4f5a6b",
"variant_id": "c0ffee00-0001-4e8f-9b70-2d1c3e4f5a6b",
"kind": "variant",
"name": "عطر العود الملكي — 50 مل",
"quantity": 2,
"unit_price": {
"amount_minor": 225000,
"currency": "SYP",
"decimals": 0
},
"total": {
"amount_minor": 450000,
"currency": "SYP",
"decimals": 0
}
},
{
"id": "a1b2c3d4-0003-4e8f-9b70-2d1c3e4f5a6b",
"variant_id": null,
"kind": "custom",
"name": "تغليف هدية مع بطاقة إهداء",
"quantity": 1,
"unit_price": {
"amount_minor": 15000,
"currency": "SYP",
"decimals": 0
},
"total": {
"amount_minor": 15000,
"currency": "SYP",
"decimals": 0
}
}
],
"fulfillments": [],
"refunds": [],
"note": "عرض السعر Q-1042 مقبول عبر واتساب",
"attributes": {
"reference": {
"kind": "quote",
"number": "Q-1042",
"url": "https://offers.example.com/quotes/Q-1042"
},
"quote_id": "q_8f3a"
},
"customer": {
"first_name": "ليان",
"last_name": "الحلبي",
"email": null,
"phone": "+963944123456"
},
"shipping_address": {
"address": "شارع بغداد، بناء 22، الطابق الثالث",
"province": "damascus",
"city": "دمشق",
"notes": null
}
}
}الجسم#
| الحقل | المعنى |
|---|---|
currency |
إحدى عملات المتجر المسموح بها (GET /store، الحقل storefront_currencies.allowed). وإلا 422 برمز currency_not_allowed مع details.allowed. |
status |
placed (الافتراضي) يترك للتاجر مراجعة الطلب في لوحة التحكم؛ وapproved يسجّل قبولاً صريحاً أعطاه العميل لك مسبقاً. كلاهما يتبع دورة الحياة العادية بعد ذلك. |
items[] |
من 1 إلى 200 بند. variant_id يسمّي خياراً من الكتالوج؛ وnull يجعل البند مخصصاً وعندها يلزم name. الكمية quantity من 1 إلى 100,000، وunit_price_minor سعر الوحدة المتفق عليه بالوحدات الصغرى لعملة currency؛ والصفر مسموح. |
discount |
مبلغ على مستوى الطلب مع عنوان اختياري، لا يتجاوز مجموع البنود. |
shipping |
المبلغ وmethod: إما delivery أو pickup. |
customer |
الاسم، ورقم الهاتف الدولي الكامل (يُخزَّن منسّقاً)، والبريد اختياري. لا تخترع المنصّة بريداً أبداً حين تتركه null. |
shipping_address |
مطلوب مع delivery. الحقل province إحدى القيم التي يعرضها GET /store تحت provinces. |
payment_method |
إما cod أو shamcash_manual؛ يجب أن يكون مفعّلاً في المتجر، وإلا 409 برمز payment_method_disabled. |
exchange_rate |
مطلوب عندما تختلف currency عن عملة التسعير، وممنوع في غير ذلك. |
note وtags وattributes |
الحقول نفسها التي يحرّرها PATCH /orders/{id}، راجع أدناه. |
inventory |
إما decrement (الافتراضي) أو skip، راجع المخزون والحالة. |
المجاميع والعملة#
كل حقل مالي عدد صحيح بالوحدات الصغرى لعملة الطلب، مقيساً بالأس العشري الذي تعتمده دكان لتلك العملة (SYP صفر، USD اثنان، JOD ثلاثة). ترسل أسعار الوحدة ومبلغَي الخصم والشحن؛ وتعيد المنصّة احتساب كل ما عداها:
- المجموع الفرعي = Σ
quantity×unit_price_minor - الإجمالي = المجموع الفرعي − الخصم + الشحن
- الضريبة = 0
حين لا يكون الطلب بعملة تسعير المتجر، أرسل السعر الذي طبّقته بالشكل { "scaled", "scale" } حيث السعر = scaled ÷ 10^scale، ووحدة واحدة من عملة التسعير = السعر من وحدات عملة الطلب. خذه من fx.rates في GET /store؛ فذلك الجدول يتضمّن تعديلات التاجر أصلاً وهو بالضبط ما تطبّقه صفحة الدفع. قرّب كل سعر وحدة بعد التحويل، لا الإجمالي، لتطابق أرقامك ما تكلّفه السلة نفسها في المتجر. تفعل الحزمة ذلك عنك بـ exchangeRateFor وbuildCreateOrderLines؛ راجع صفحة الحزمة. قواعد المال عموماً في المبالغ بالوحدات الصغرى.
المخزون والحالة#
inventory: "decrement"يخصم المخزون لكل بند من الكتالوج وفق سياسة المخزون في المتجر. عندما يكون بند ناقصاً يفشل الطلب كله بـ409ولا يُكتب شيء. أماinventory: "skip"فلا يكتب أي حركة، للطلبات التي لم تكن بضاعتها في مخزون هذا المتجر أصلاً.- البنود المخصصة (
kind: "custom") لا رابط لها بالكتالوج: لا تمسّ المخزون أبداً، والاسترداد عليها بالمبلغ فقط، ولا يكون معrestock. راجع حركات المخزون. status: "placed"هو الافتراضي الصحيح عندما ينبغي أن يؤكّد التاجر قبل أن يُشحن شيء. استخدمapprovedفقط حين جمع تطبيقك قبولاً صريحاً من العميل؛ تعرض لوحة التحكم «الحالة عند الإنشاء: مقبول» في سجل الطلب ليعرف التاجر سبب تجاوز خطوة المراجعة.
الأخطاء#
| الحالة | الرمز | المعنى |
|---|---|---|
422 |
invalid_request |
فشل حقل في التحقق؛ يسرد details.fields المسارات، مثل items.1.name أو shipping_address. |
422 |
currency_not_allowed |
currency ليست من العملات التي يبيع بها المتجر؛ يسرد details.allowed الرموز المقبولة. |
404 |
variant_not_found |
variant_id غير موجود في هذا المتجر؛ يسمّيه details.variant_id. |
409 |
variant_unavailable |
الخيار موقوف؛ يسمّيه details.variant_id. |
409 |
payment_method_disabled |
طريقة الدفع المختارة معطّلة في هذا المتجر. |
409 |
insufficient_stock |
بند أو أكثر من الكتالوج يتجاوز الكمية المتاحة؛ يسمّي details.lines[] كل بند ناقص بـ variant_id، ومعه requested وavailable عند قياس النقص مسبقاً. أما إذا سبقك طلب آخر إلى قفل الصف، فيعود variant_id وحده. لم يُكتب شيء. |
403 |
forbidden |
التثبيت بلا orders:create فعلي، أو المتجر متجر عرض في السوق. |
429 |
rate_limited |
دلو الكتابة المشترك، أو الحدود اليومية أدناه. احترم Retry-After. |
{
"error": {
"code": "insufficient_stock",
"message": "Not enough stock for one or more lines",
"request_id": "7d0c2b1a-5e4f-4a3b-8c9d-0e1f2a3b4c5e",
"details": {
"lines": [
{
"variant_id": "c0ffee00-0001-4e8f-9b70-2d1c3e4f5a6b",
"requested": 2,
"available": 1
}
]
}
}
}اقرأ قائمة lines كاملة، وأعد التسعير أو قسّم الطلب، ثم أرسل طلباً جديداً بمفتاح جديد. لا يسجّل 409 مفتاح التكرار أبداً، فالمفتاح نفسه متاح لإعادة الاستخدام متى زال السبب.
ما يراه التاجر#
- قائمة الطلبات: يحمل الطلب شريحة «من تطبيق»، ويمكن للتاجر التصفية حسب النوع «تطبيق» وحسب الوسم.
- صفحة الطلب: بطاقة «مرجع التطبيق» بشريحة من خاصية
reference(مثل «عرض سعر Q-1042») تفتح الرابط الذي أعطيته؛ وبطاقة «ملاحظة الطلب»؛ و«بند مخصص» على كل بند مخصص؛ وسجل «سجل الطلب» أول صفوفه «أنشأ تطبيق «اسم تطبيقك» هذا الطلب» بالعبارة «الأسعار كما حددها التطبيق · الحالة عند الإنشاء: قيد المراجعة». - التحرير: الأسعار والخصم والشحن في الطلب الذي أنشأه تطبيق مقفلة في لوحة التحكم («يديرها التطبيق ولا يمكن تعديلها هنا»)؛ والكميات تبقى قابلة للتعديل.
- الإشعارات: يتلقّى التاجر الدفعة والبريد نفسيهما كما في طلب من المتجر، وتستلم التطبيقات المشترِكة
order.createdبقيمةsource: "app". - إن أُزيل تطبيقك لاحقاً يحتفظ الطلب بكل شيء؛ وتقول بطاقة المرجع «تمت إزالة التطبيق، البيانات محفوظة».
حدّث الملاحظة والوسوم والخصائص#
يتطلب orders:write وIdempotency-Key. المال والبنود والعميل والعنوان ثابتة بعد الإنشاء؛ تحرّر هذه النقطة الحقول الثلاثة التي تحيط بها.
curl -X PATCH https://dukkan.one/platform-api/v1/orders/ORDER_ID \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Idempotency-Key: invoice-INV-2207-linked" \
-H "Content-Type: application/json" \
-d @update.json{
"note": "تم تأكيد الدفع عند الاستلام هاتفياً",
"tags": {
"add": [
"مؤكد"
],
"remove": [
"جملة"
]
},
"attributes": {
"reference": {
"kind": "invoice",
"number": "INV-2207",
"url": "https://offers.example.com/invoices/INV-2207"
},
"quote_id": null
}
}noteيستبدل ملاحظة الطلب؛ وnullيمسحها. حتى 2,000 حرف.tagsزوج من عمليات المجموعات، وليس استبدالاً أبداً، فتبقى وسوم التاجر ووسوم التطبيقات الأخرى. الوسم من 1 إلى 40 حرفاً من حروف Unicode والأرقام والمسافات و_و-؛ تنسّقه المنصّة (NFC مع إزالة الفراغات) وتزيل التكرار دون تمييز حالة الأحرف؛ ويحمل الطلب 10 وسوم على الأكثر. تطابقremoveدون تمييز حالة الأحرف. ويصفّيGET /orders?tag=حسب وسم واحد.attributesتُدمج في مساحة تطبيقك الخاصة. لا ترى التطبيقات الأخرى مفاتيحك أبداً ولا ترى أنت مفاتيحها؛ ويعيدGET /orders/{id}مفاتيحك وحدها. تطابق المفاتيح[a-z0-9_.-]{1,64}، بحد 20 لكل تطبيق، والقيم المفردة حتى 1,000 بايت UTF-8، و8 KB إجمالاً. الحد بالبايت، لذا تصل القيمة العربية إليه عند نحو 500 حرف. في PATCH تحذفnullالمفتاح.
الاستجابة هي الطلب المحدّث، بشكل 200 نفسه الذي يعيده GET /orders/{id}.
الخاصية reference#
لخاصية واحدة شكل ثابت ومكان ثابت في لوحة التحكم: reference تربط الطلب بالسجل الذي جاء منه في تطبيقك.
| الحقل | المعنى |
|---|---|
kind |
نوع السجل في تطبيقك، حتى 40 حرفاً، مثل quote أو invoice. |
number |
الرقم المقروء، حتى 80 حرفاً، مثل Q-1042. يظهر على الشريحة. |
url |
رابط عميق إلى تطبيقك، أو null. يجب أن يكون https على أصل تطبيقك المسجّل (أصل أحد عناوين إعادة التوجيه في إصدار التطبيق)؛ وأي شيء آخر يُرفض بـ 422. يفتحه التاجر في تبويب جديد. |
أرسلها عند الإنشاء أو أضفها لاحقاً؛ واستبدالها بكائن جديد يبدّل الشريحة.
ملف المتجر#
لا يحتاج إلى نطاق؛ كل ما فيه علني في المتجر أصلاً.
curl https://dukkan.one/platform-api/v1/store \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"{
"data": {
"id": "0d9e8f7a-6b5c-4d3e-2f1a-0b9c8d7e6f5a",
"slug": "sham-perfumes",
"name": "عطور الشام",
"description": "عطور شرقية أصيلة من دمشق",
"logo_url": "https://cdn.dukkan.one/stores/sham-perfumes/logo.png",
"banner_urls": [],
"storefront_url": "https://shamperfumes.com",
"whatsapp_number": "+963944000000",
"phone": null,
"address": "دمشق، الحميدية",
"accent_color": "#7A1F2B",
"locale": "ar",
"timezone": "Asia/Damascus",
"country": "SY",
"pricing_currency": {
"code": "SYP",
"decimals": 0
},
"storefront_currencies": {
"allowed": [
"SYP",
"USD"
],
"default": "SYP"
},
"fx": {
"base": "SYP",
"as_of": "2026-09-10T06:00:00Z",
"rates": {
"SYP": {
"scaled": 100000000,
"scale": 8
},
"USD": {
"scaled": 7700,
"scale": 8
}
}
},
"payment_methods": [
{
"id": "cod"
},
{
"id": "shamcash_manual",
"shamcash_id": "0944000000"
}
],
"provinces": [
{
"value": "damascus",
"ar": "دمشق",
"en": "Damascus"
},
{
"value": "aleppo",
"ar": "حلب",
"en": "Aleppo"
}
]
}
}pricing_currencyهي العملة التي تُخزَّن بها أسعار الكتالوج، مع أسّها العشري. وstorefront_currencies.allowedهي العملات التي يقبلهاPOST /orders.fxجدول الأسعار المعدّل من التاجر بدءاً من عملة التسعير، وnullحين لا جدول للمتجر. كل سعر هوscaled ÷ 10^scale، والعملة الأساس مضمّنة بسعر 1، وas_ofيخبرك بحداثته.payment_methodsيسرد الطرق اليدوية المفعّلة؛ ويحملshamcash_manualالمعرّفshamcash_idالذي يظهر عند الدفع لتعرض أنت المعرّف نفسه.provincesهي قيمshipping_address.provinceالمقبولة مع تسميات عربية وإنجليزية.storefront_urlهو الأصل العلني؛ والنطاق المخصص الموصول يتقدّم على النطاق الفرعي للمنصّة.
خزّنه مؤقتاً لكل تثبيت بضع دقائق؛ فالأسعار تتحرّك بضع مرات في اليوم على الأكثر.
ابحث في المنتجات والخيارات#
كلاهما يحتاج إلى products:read.
curl "https://dukkan.one/platform-api/v1/products?q=oud&status=active" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
curl "https://dukkan.one/platform-api/v1/products/variants?ids=c0ffee00-0001-4e8f-9b70-2d1c3e4f5a6b" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"{
"data": [
{
"id": "c0ffee00-0001-4e8f-9b70-2d1c3e4f5a6b",
"product_id": "b0b0b0b0-0001-4e8f-9b70-2d1c3e4f5a6b",
"sku": "OUD-50",
"price": {
"amount_minor": 250000,
"currency": "SYP",
"decimals": 0
},
"status": "active",
"name": "50 مل",
"attributes": {
"الحجم": "50 مل"
},
"barcode": null,
"compare_at_price": null,
"image_url": "https://cdn.dukkan.one/stores/sham-perfumes/products/oud-50.jpg",
"weight_gram": 180,
"available_quantity": 12,
"product_name": "عطر العود الملكي",
"product_status": "active"
}
]
}GET /products?q=يطابق من 2 إلى 80 حرفاً، دون تمييز حالة الأحرف، مع اسم المنتج واسم الخيار وSKU وDSIN والباركود، بالعربية أو اللاتينية، ويرتّب النتيجة. يجيب البحث بصفحة مرتّبة واحدة من دون مؤشر؛ فضيّق الاستعلام بدلاً من التصفّح. يصفّيstatusوids(حتى 100، مفصولة بفواصل)، ويُجمعان معupdated_at_minللمزامنة.GET /products/variants?ids=يأخذ حتى 100 معرّف ويعيد الخيارات الموجودة، لكل منهاproduct_nameوproduct_statusوpriceالحالي وcompare_at_priceوimage_url. تُحذف المعرّفات غير المعروفة ولا تكون خطأ أبداً، فقارن المعرّفات المُعادة بما طلبته. ويظهرavailable_quantityفقط حين يحمل التثبيتinventory:readأيضاً.
أعد التحقق من الخيارات خلف عرض السعر قبل POST /orders مباشرة: الخيار الذي أوقف منذ العرض يجيب بـ 409 عند الإنشاء، وتغيّر السعر أمر قد تودّ عرضه على العميل أولاً.
التكرار الآمن والحدود#
- تحمل كل كتابة
Idempotency-Key. حين تعيد المنصّة استجابة مسجّلة تقول ذلك بالترويسةIdempotency-Replayed: true؛ وتظهرها الحزمة بالحقلreplayed. - تتشارك الكتابات دلو التثبيت بحد 60 في الدقيقة. ويُحتسب إنشاء الطلبات إضافةً إلى ذلك ضمن 500 طلب لكل تثبيت يومياً و2,000 لكل متجر يومياً. كلاهما يجيب بـ
429معRetry-After. - ترفض متاجر العرض في السوق إنشاء الطلبات بـ
403.