واجهة API للدروبشيبنغ
لمن هذه الصفحة
Section titled “لمن هذه الصفحة”للمطورين الذين يؤتمتون متجرًا يملكونه أو يعملون فيه، عبر REST API أو حزم Posty5 البرمجية أو n8n. لا يستدعي المتسوّقون ولا الموردون هذه المسارات. وإن كنت تدير المتجر يدويًا، فدليل التاجر هو الصفحة المناسبة لك. افتح دليل التاجر
المصادقة
Section titled “المصادقة”يحمل كل طلب مفتاح API الخاص بك في هذه الترويسة —
X-API-Key: YOUR_API_KEYأنشئ مفتاحًا من لوحة تحكم Posty5، في إعدادات الحساب، ضمن مفاتيح API. مفاتيح API متاحة لحسابات المطورين.
كل مسار أدناه يعمل على متجر واحد ويتحقق من صلاحية المتجر المذكورة بجانبه. يجب أن يكون صاحب المفتاح مالك المتجر أو عضوًا في فريقه يملك تلك الصلاحية.
عندما لا تتضمن خطة مالك المتجر الدروبشيبنغ (Pro أو أعلى)، تُرفض هذه المسارات — ربط مورّد (بمفتاح API أو بتسجيل الدخول)، واستبدال بيانات اعتماده، وتفعيل الربط، وتغيير أتمتته، وتصفّح منتجات المورّد، وجلب منتج واحد من المورّد، وتحليل رابط منتج، ومعاينة الاستيراد أو تنفيذه، وإنشاء رابط منتج، وإرسال طلب المورّد أو إعادة محاولته أو دفعه. خطة المالك هي التي تحدد، لا خطة عضو فريق العمل الذي يستدعي المسار. أما بقية المسارات فتبقى متاحة على أي خطة، فيستطيع المتجر الذي نزل عن Pro أن يقرأ ما لديه، ويوقف الربط، ويغيّر إعداداته، ويختبره أو يلغي ربطه، ويعدّل روابط المنتجات أو يزامنها أو يحذفها، ويلغي طلب المورّد أو ينفّذه يدويًا.
الرابط الأساسي
Section titled “الرابط الأساسي”- dropshipping.developer.base.hostAt
- dropshipping.developer.base.prefixIs
- dropshipping.developer.base.docsAt
المسارات
Section titled “المسارات”المسارات أدناه نسبية إلى بادئة الموردين. المعامل الأول دائمًا هو معرّف المتجر، والمعرّف الذي يليه هو ربط المورد.
عمليات الربط
Section titled “عمليات الربط”| الطريقة | المسار | الصلاحية | ماذا يفعل |
|---|---|---|---|
GET | /:storeId/catalogue | suppliers.view | الموردون الذين يستطيع هذا المتجر ربطهم، وما يستطيعه كل منهم. |
GET | /:storeId | suppliers.view | عمليات ربط الموردين في المتجر، مع حالتها وإعدادات الأتمتة. لا تُعاد بيانات الاعتماد أبدًا. |
POST | /:storeId | suppliers.manage | ربط مورد بمفتاح API الخاص به. يُتحقق من المفتاح لدى المورد قبل حفظه. |
POST | /:storeId/oauth/start | suppliers.manage | بدء ربط مورد يعتمد تسجيل الدخول، مثل AliExpress. يعيد العنوان الذي يُرسل إليه التاجر. |
PUT | /:storeId/:id | suppliers.manage | استبدال بيانات اعتماد الربط. |
POST | /:storeId/:id/test | suppliers.manage | فحص الربط الآن وتسجيل حالته. |
GET | /:storeId/:id/balance | suppliers.view | رصيدك لدى المورّد، إن كان المورّد يُبلغ عنه. |
GET | /:storeId/:id/impact | suppliers.view | ما سيتأثر بإلغاء الربط — المنتجات المرتبطة وطلبات المورد المفتوحة. |
PUT | /:storeId/:id/settings | suppliers.manage | تغيير إعدادات المورد الخاصة. |
PUT | /:storeId/:id/automation | suppliers.manage | تغيير طريقة إرسال الطلبات والحدود. |
PUT | /:storeId/:id/enabled | suppliers.manage | تشغيل الربط أو إيقافه. |
DELETE | /:storeId/:id | suppliers.manage | إلغاء الربط. تُحذف بيانات الاعتماد، وتبقى المنتجات المستوردة ملكًا للمتجر. |
منتجات المورد والاستيراد والروابط
Section titled “منتجات المورد والاستيراد والروابط”| الطريقة | المسار | الصلاحية | ماذا يفعل |
|---|---|---|---|
GET | /:storeId/:id/products | suppliers.import | تصفح كتالوج المورد أو البحث فيه. |
POST | /:storeId/:id/products/resolve-url | suppliers.import | تحويل رابط منتج ملصوق إلى معرّف المنتج لدى المورد. |
GET | /:storeId/:id/products/:supplierProductId | suppliers.import | منتج واحد لدى المورد مع متغيّراته وتكاليفه ومخزونه. |
POST | /:storeId/:id/import/preview | suppliers.import | تسعير المنتجات المختارة بقاعدة التسعير وذكر أي مكررات. لا يُخصم شيء. |
POST | /:storeId/:id/import | suppliers.import | استيراد حتى 50 منتجًا. الاستيراد الكبير يعيد معرّف مهمة لمتابعتها. |
GET | /:storeId/imports/:jobId | suppliers.import | تقدّم استيراد يعمل في الخلفية. |
GET | /:storeId/links | suppliers.view | روابط منتجات المتجر. |
POST | /:storeId/links | suppliers.import | ربط منتج يملكه المتجر بمنتج لدى المورد. |
PUT | /:storeId/links/:linkId | suppliers.import | تغيير متغيّرات الرابط أو قاعدة تسعيره أو مفاتيح المزامنة. |
DELETE | /:storeId/links/:linkId | suppliers.import | إلغاء الربط. يبقى المنتج ملكًا للمتجر. |
POST | /:storeId/links/:linkId/sync | suppliers.import | مزامنة رابط واحد الآن. |
طلبات المورد
Section titled “طلبات المورد”| الطريقة | المسار | الصلاحية | ماذا يفعل |
|---|---|---|---|
GET | /:storeId/orders | suppliers.view | طلبات المورد، الأحدث أولًا، مصفّاة ومقسّمة إلى صفحات بمؤشّر. حقول الاستعلام مذكورة أسفل الجدول. |
GET | /:storeId/orders/:supplierOrderId | suppliers.view | طلب مورد واحد مع سجله. |
POST | /:storeId/orders/:orderId/groups/:groupKey/submit | suppliers.orders.manage | إرسال جزء واحد من الطلب إلى مورده الآن. |
POST | /:storeId/orders/:supplierOrderId/retry | suppliers.orders.manage | إعادة محاولة طلب مورد في الانتظار أو متوقف أو فاشل. |
POST | /:storeId/orders/:supplierOrderId/pay | suppliers.orders.manage | دفع طلب مورد أُنشئ ولم يُدفع. |
POST | /:storeId/orders/:supplierOrderId/cancel | suppliers.orders.manage | سحب الطلب لدى المورد، إن كان المورد ما زال يسمح بذلك. |
POST | /:storeId/orders/:orderId/groups/:groupKey/fulfil-manually | suppliers.orders.manage | تولي جزء ليشحنه المتجر بنفسه. |
تقبل القائمة حقول الاستعلام هذه — status, needsReview, integrationId, orderId, contractModel, cursor, pageSize
تُقسَّم القائمة إلى صفحات بمؤشّر، مثل قوائم المتجر الأخرى، ولا تقبل رقم صفحة. تضم الصفحة 25 صفًا ما لم تطلب حجمًا آخر، ولا تتجاوز 100 صف أبدًا. وكل إجابة صفحة واحدة, الصفوف، ثم كتلة ترقيم فيها المؤشّران التالي والسابق، وهل تتبعها صفوف أخرى، والعدد الإجمالي، وحجم الصفحة —
{ "items": [{ "_id": "SUPPLIER_ORDER_ID", "status": "needsReview" }], "pagination": { "nextCursor": "NEXT_CURSOR", "previousCursor": null, "hasMore": true, "totalCount": 42, "pageSize": 25 }}لقراءة الصفحة التالية، كرّر الاستدعاء بالمرشحات نفسها، مع المؤشّر التالي من الصفحة السابقة في حقل المؤشّر. وتوقّف عندما لا تتبعها صفوف أخرى. واقرأ كل الصفحات قبل أن تتصرّف في الصفوف, فإعادة المحاولة أو الدفع تغيّر القائمة التي يمرّ عليها المؤشّر.
إجراءان يقبلان جسمًا اختياريًا —
submit—{ "payNow": true }— دفع الطلب أيضًا فور إنشائه، إذا كان يمكن الدفع للمورد من الرصيد المالي. الدفع الفوري قرار التاجر نفسه، لذا يُتخطّى التحقق من أن المتسوّق قد دفع — فيُدفع حتى للطلب غير المدفوع أو الطلب بالدفع عند الاستلام، ويُسجَّل هذا القرار في سجل طلب المورد. أما التحقق من الوجهة والمخزون وحدود التكلفة والرصيد المالي فيبقى ساريًا.retry—{ "acceptCost": true }— قبول التكلفة الجديدة للمورد بعد تغيّر السعر. ويُسجَّل ذلك قرارًا للمستدعي.
إضافات على طلبات المتجر
Section titled “إضافات على طلبات المتجر”GET /api/store-orders/:storeId/:id— تضيف تفاصيل الطلب أجزاء الطلب، وتضيف طلبات المورد مع تكاليفها لمن يملك أيضًا صلاحية عرض الموردين.GET /api/store-orders/:storeId?needsAttention=true— يحمل كل طلب في القائمة ملخصًا لأجزائه، وتقبل القائمة مرشحًا للطلبات التي فيها جزء يحتاج إلى مراجعة.
الكائنات
Section titled “الكائنات”ربط المورد
Section titled “ربط المورد”supplierKey— أي مورد، باسمه في الكتالوج.mode— اختبار أو مباشر.enabled— هل الربط مُشغَّل.hasCredentials— هل بيانات الاعتماد محفوظة. أما البيانات نفسها فلا تُعاد أبدًا.automation— طريقة إرسال الطلبات والحدود التي توقفها.health— نتيجة آخر فحص.isCircuitOpen,circuitOpenUntil— الربط متوقف مؤقتًا بعد أخطاء متكررة، حتى ذلك الوقت.lastWebhookAt— متى أرسل المورد آخر إشعار.webhookUrl— العنوان الذي يرسل إليه المورد إشعاراته، ويظهر في قائمة عمليات الربط. ويكون فارغًا حين لا يُضبط عنوان عام.
رابط المنتج
Section titled “رابط المنتج”productId,supplierProductId— منتج المتجر ومنتج المورد المرتبط به.variants[]— كل متغيّر في المتجر مرتبط بمتغيّر لدى المورد، مع تكلفته ومخزونه.priceRule— كيف يُحسب سعر المتجر من التكلفة.sync— الحقول التي يحق للمزامنة التي تتم كل ساعة تغييرها.lastSyncAt,lastSyncError— آخر مزامنة، وسبب فشلها إن فشلت.
طلب المورد
Section titled “طلب المورد”status— أين وصل طلب المورد. يسرد الجدول أدناه كل القيم.reviewReason,reviewMessage— سبب توقفه، كسبب واحد من قائمة مغلقة، وكلام المورد بعد حذف أي معلومات حساسة.retryable— هل قد تنجح إعادة المحاولة دون تغيير أي شيء.supplierOrderNumber— رقمنا، يُرسل إلى المورد رقمًا لطلبه. ولا يتغير بين محاولات الإعادة للمحاولة نفسها.supplierOrderId,supplierStatus— معرّف المورد وحالته، كما يكتبها المورد.costs,payment— ما يتقاضاه المورد، وهل دفعه المتجر.shipping— شركة الشحن ورقم التتبع بعد أن يشحن المورد.attempt,events[]— رقم هذه المحاولة، وسجلها.destination,destinationRedacted— عنوان التوصيل، لمن يُسمح له برؤية بيانات العملاء فقط. وإلا فيُحذف، ويُشير إلى ذلك حقل مخصص (flag).
dropshipping.developer.objects.paymentValuesList
في طلب المتجر
Section titled “في طلب المتجر”fulfilmentGroups[]— أجزاء الطلب — جزء لمنتجات المتجر نفسه وجزء لكل ربط مورد — ولكل جزء حالته ومنتجاته وشحنته.fulfilmentSummary— عدد الأجزاء، وكم منها تم شحنه أو توصيله.supplierOrders[]— طلبات الموردين الخاصة بهذه الأجزاء، لمن يُسمح له برؤية الموردين.
الحالات والأسباب
Section titled “الحالات والأسباب”حالات أجزاء الطلب
Section titled “حالات أجزاء الطلب”يتقدّم الطلب بسرعة أبطأ أجزائه, فلا يصبح «تم الشحن» إلا بعد شحن جميع أجزائه، ولا يصبح «تم التوصيل» إلا بعد توصيلها جميعًا.
| القيمة | المعنى | ما يمكن للبرنامج فعله |
|---|---|---|
pending | لم يبدأ بعد. | لا شيء — انتظر. |
processing | قيد التجهيز، لدى المتجر أو المورد. | لا شيء — انتظر. |
shipped | سُلِّم إلى شركة الشحن. | اقرأ التتبع من شحنة الجزء. |
delivered | تم التوصيل. حالة نهائية. | لا شيء — انتظر. |
cancelled | ملغى. حالة نهائية. | لا شيء — انتظر. |
حالات طلب المورد
Section titled “حالات طلب المورد”| القيمة | المعنى | ما يمكن للبرنامج فعله |
|---|---|---|
queued | في انتظار الإرسال. | لا شيء — انتظر. |
needsReview | متوقف مع سبب. يحتاج إلى شخص أو إلى تغيير في المدخلات. | اعرضه على شخص. ولا تُعِد المحاولة إلا بعد تغيّر السبب. |
submitted | أُنشئ لدى المورد، ولم يُقبل ويُدفع بعد. | ادفعه، إن كان المتجر يدفع يدويًا. |
confirmed | قُبل ودُفع لدى المورد. | لا شيء — انتظر. |
processing | قيد التجهيز لدى المورد. | لا شيء — انتظر. |
shipped | شحنه المورد، مع رقم تتبع. | لا شيء — انتظر. |
delivered | تم التوصيل. حالة نهائية. | لا شيء — انتظر. |
cancelled | أُلغي. حالة نهائية. | لا شيء — انتظر. |
failed | خطأ مؤقت، مثل انتهاء المهلة. تعيد المهمة المحاولة تلقائيًا. | أعد المحاولة مرة واحدة إذا توقفت المحاولات التلقائية. |
أسباب المراجعة
Section titled “أسباب المراجعة”يحمل طلب المورّد المتوقف سببًا واحدًا فقط من هذه الأسباب. والعمود الثاني هو القيمة التي يضبطها API لكل سبب.
| القيمة | retryable | المعنى | ما يمكن للبرنامج فعله |
|---|---|---|---|
insufficientBalance | false | لا يكفي رصيد المتجر لدى المورّد لتغطية الطلب. | أبلغ شخصًا. وأعد المحاولة بعد شحن الرصيد. |
variantUnavailable | false | لم يعد المورد يوفّر أحد المتغيّرات. | لا شيء دون تدخّل شخص. |
destinationUnsupported | false | المورد لا يوصل إلى هناك، أو أن المتجر استثنى الدولة. | لا شيء دون تدخّل شخص. |
costAboveLimit | false | التكلفة أعلى من حد وضعه المتجر. | أعد المحاولة بقرار من شخص فقط. |
costChanged | false | تغيّر سعر المورد منذ الاستيراد. | أعد المحاولة مع قبول التكلفة الجديدة، بقرار من شخص فقط. |
customerPaymentPending | false | لم يدفع المتسوّق إلكترونيًا. | أرسله عندما يقرر المتجر ذلك. |
customerPaymentNotSettled | false | تم تفويض الدفع لكنه لم يُسوَّ بعد. | أعد المحاولة بعد تسوية الدفع. |
connectionUnhealthy | true | لم يستجب المورد، أو أن الربط متوقف مؤقتًا. | أعد المحاولة لاحقًا. |
supplierRefused | true | رفض المورد الطلب. | اقرأ الرسالة. وأعد المحاولة بعد معالجة السبب. |
connectionMissing | false | الربط متوقف أو محذوف، أو أن Posty5 أوقف المورد. | لا شيء؛ يلزم تدخّل بشري. |
supplierAlreadyShipped | false | جاء الإلغاء بعد أن شحن المورد. | لا شيء — عامِله كمرتجع. |
testMode | false | ربط تجريبي بمورد لا يوفّر بيئة اختبار. لم يُقدَّم أي طلب. | لا شيء حتى يعمل الربط في الوضع الفعلي. |
customerCaptureFailed | false | الوعد بالبيع — دُفع للمورد، وفشل تحصيل المبلغ من المتسوّق. | أبلغ شخصًا فورًا. |
عنوان إشعارات المورد
Section titled “عنوان إشعارات المورد”POST /api/store-suppliers/webhook/:supplierKey/:integrationIdالموردون الذين يرسلون إشعارات يستدعون هذا العنوان للإبلاغ عن حالة الطلب والتتبع والمخزون.
يعثر Posty5 على الربط من العنوان ويتحقق من الرسالة ببيانات اعتماد ذلك الربط. كل رفض يتلقى الإجابة 400 نفسها، و503 حين لا يستطيع Posty5 الحسم، فيعيد المورد الإرسال. الإشعار لا يفعل أكثر من دفع Posty5 إلى قراءة الطلب من المورد، ولا يحرّك بنفسه مالًا ولا مخزونًا ولا حالة أبدًا.
منع التكرار وإعادة المحاولة
Section titled “منع التكرار وإعادة المحاولة”يُحمى طلب المورد من التكرار بثلاث طرق.
- مهمة واحدة لكل جزء من الطلب، أيًّا كان مُطلقها —
- مفتاح فريد لكل محاولة، يُرسل إلى المورد رقمًا لطلبه. وقبل الإنشاء يسأل Posty5 المورد هل هذا الرقم موجود، فيُعثر على الإنشاء الذي انتهت مهلته بعد نجاحه ولا يُكرَّر.
- قبل الدفع يقرأ Posty5 حالة الطلب لدى المورد. والطلب المدفوع هناك يُسجَّل ولا يُدفع مرة ثانية.
ماذا يعني ذلك لبرنامجك
Section titled “ماذا يعني ذلك لبرنامجك”- استدعاء الإرسال مرتين ينتج طلب مورد واحدًا.
- dropshipping.developer.idem.rules.retryWhen
- الطلب المتوقف لا يُحل من تلقاء نفسه. يحتاج إلى تدخّل شخص، أو إلى تغيير في المدخلات.
- لمتابعة الطلب، اقرأ طلب المورد من جديد. ولا تستدعِ الإرسال في حلقة.
متى تُرسل الطلبات
Section titled “متى تُرسل الطلبات”في المستويات التلقائية، يُرسل جزء المورد مرة واحدة، عندما يصبح الطلب مؤكدًا — بتأكيد عضو في الفريق أو بدفع إلكتروني.
يتطلب الدفع التلقائي للمورد أن تكون دفعة المتسوّق مدفوعة بتأكيد مزوّد الدفع. والطلب بلا دفع إلكتروني ينتظر ما لم يسمح الربط بالطلبات غير المدفوعة.
في الوعد بالبيع، يبدأ الإرسال بعد تفويض دفعة المتسوّق، ويُحصَّل المبلغ من المتسوّق عندما يقبل المورد.
عرض طلبات المورد التي تنتظر المراجعة —
curl "https://api.posty5.com/api/store-suppliers/STORE_ID/orders?needsReview=true" \ -H "X-API-Key: YOUR_API_KEY"الاستجابة صفحة واحدة من طلبات المورّد. ويبدو الصف المتوقف بسبب انخفاض الرصيد المالي هكذا —
{ "_id": "SUPPLIER_ORDER_ID", "orderNumber": "1042", "fulfilmentGroupKey": "GROUP_KEY", "supplierKey": "cjdropshipping", "attempt": 1, "status": "needsReview", "reviewReason": "insufficientBalance", "reviewMessage": "Balance is insufficient", "retryable": false, "supplierOrderNumber": "SUPPLIER_ORDER_NUMBER", "payment": { "status": "unpaid" }}الاستدعاء نفسه من TypeScript —
const response = await fetch( `https://api.posty5.com/api/store-suppliers/${storeId}/orders?needsReview=true`, { headers: { "X-API-Key": process.env.POSTY5_API_KEY! } },);const { result } = await response.json();// result.items: the supplier orders on this page// result.pagination.nextCursor: send it back as `cursor` while result.pagination.hasMoreومن C# —
using var http = new HttpClient { BaseAddress = new Uri("https://api.posty5.com") };http.DefaultRequestHeaders.Add("X-API-Key", Environment.GetEnvironmentVariable("POSTY5_API_KEY"));var json = await http.GetStringAsync($"/api/store-suppliers/{storeId}/orders?needsReview=true");// { "result": { "items": [...], "pagination": { "nextCursor": "...", "hasMore": true, ... } } }// Send pagination.nextCursor back as &cursor= while pagination.hasMore is true.حزم SDK وn8n
Section titled “حزم SDK وn8n”تتضمن كلٌّ من حزمتي المتجر لـ JavaScript و.NET عميلًا للموردين يغطي كل المجموعات أعلاه — الكتالوج، وعمليات الربط، ومنتجات المورد، والاستيراد، والروابط، وطلبات المورد. وعندما يتوقف طلب المورد للمراجعة، تُطلق عمليات الإرسال وإعادة المحاولة والدفع خطأً بدلًا من إرجاع نتيجة، فاقرأ طلب المورد مجددًا لمعرفة السبب.
- npm —
@posty5/store4.3.0—store.suppliers - NuGet —
Posty5.Store3.2.0—store.Suppliers
لم يُنشر أيٌّ من هذين الإصدارين بعد. وحتى يُنشرا، استدعِ المسارات أعلاه مباشرة.
من TypeScript، أعد محاولة كل طلب مورد توقّف لأن سعر المورد تغيّر، مع قبول التكلفة الجديدة —
import { HttpClient } from "@posty5/core";import { IStoreSupplierOrder, StoreClient } from "@posty5/store";
const store = new StoreClient(new HttpClient({ apiKey: process.env.POSTY5_API_KEY }));
// Read every page first: a retry changes the list the cursor walks.const paused: IStoreSupplierOrder[] = [];let cursor: string | undefined;do { const page = await store.suppliers.listSupplierOrders(storeId, { needsReview: true, cursor, pageSize: 100 }); paused.push(...page.items); cursor = page.pagination.hasMore ? page.pagination.nextCursor ?? undefined : undefined;} while (cursor);
for (const supplierOrder of paused) { if (supplierOrder.reviewReason === "costChanged") { await store.suppliers.retry(storeId, supplierOrder._id, { acceptCost: true }); }}ومن C# —
using Posty5.Core.Configuration;using Posty5.Core.Http;using Posty5.Core.Models;using Posty5.Store;using Posty5.Store.Models;
var http = new Posty5HttpClient(new Posty5Options { ApiKey = Environment.GetEnvironmentVariable("POSTY5_API_KEY") });var store = new StoreClient(http);
// Read every page first: a retry changes the list the cursor walks.var paused = new List<StoreSupplierOrder>();string? cursor = null;do{ var page = await store.Suppliers.ListSupplierOrdersAsync(storeId, new SupplierOrderSearchParams { NeedsReview = true }, new PaginationParams { Cursor = cursor, PageSize = 100 }); if (page == null) break; paused.AddRange(page.Items); cursor = page.Pagination.HasMore ? page.Pagination.NextCursor : null;} while (cursor != null);
foreach (var supplierOrder in paused){ if (supplierOrder.ReviewReason == "costChanged") await store.Suppliers.RetryAsync(storeId, supplierOrder.Id!, acceptCost: true);}تغطي عقدة متجر Posty5 في n8n (الإصدار 4.4.0 من حزمة n8n) الموردين، ومنتجات المورد، وروابط المنتجات، وطلبات المورد، وأجزاء الطلبات، والطلبات. ولم تُنشر بعد هي أيضًا.