تخطَّ إلى المحتوى

واجهة API للدروبشيبنغ

للمطورين الذين يؤتمتون متجرًا يملكونه أو يعملون فيه، عبر REST API أو حزم Posty5 البرمجية أو n8n. لا يستدعي المتسوّقون ولا الموردون هذه المسارات. وإن كنت تدير المتجر يدويًا، فدليل التاجر هو الصفحة المناسبة لك. افتح دليل التاجر


يحمل كل طلب مفتاح API الخاص بك في هذه الترويسة —

Terminal window
X-API-Key: YOUR_API_KEY

أنشئ مفتاحًا من لوحة تحكم Posty5، في إعدادات الحساب، ضمن مفاتيح API. مفاتيح API متاحة لحسابات المطورين.

كل مسار أدناه يعمل على متجر واحد ويتحقق من صلاحية المتجر المذكورة بجانبه. يجب أن يكون صاحب المفتاح مالك المتجر أو عضوًا في فريقه يملك تلك الصلاحية.

عندما لا تتضمن خطة مالك المتجر الدروبشيبنغ (Pro أو أعلى)، تُرفض هذه المسارات — ربط مورّد (بمفتاح API أو بتسجيل الدخول)، واستبدال بيانات اعتماده، وتفعيل الربط، وتغيير أتمتته، وتصفّح منتجات المورّد، وجلب منتج واحد من المورّد، وتحليل رابط منتج، ومعاينة الاستيراد أو تنفيذه، وإنشاء رابط منتج، وإرسال طلب المورّد أو إعادة محاولته أو دفعه. خطة المالك هي التي تحدد، لا خطة عضو فريق العمل الذي يستدعي المسار. أما بقية المسارات فتبقى متاحة على أي خطة، فيستطيع المتجر الذي نزل عن Pro أن يقرأ ما لديه، ويوقف الربط، ويغيّر إعداداته، ويختبره أو يلغي ربطه، ويعدّل روابط المنتجات أو يزامنها أو يحذفها، ويلغي طلب المورّد أو ينفّذه يدويًا.


  • dropshipping.developer.base.hostAt
  • dropshipping.developer.base.prefixIs
  • dropshipping.developer.base.docsAt

المسارات أدناه نسبية إلى بادئة الموردين. المعامل الأول دائمًا هو معرّف المتجر، والمعرّف الذي يليه هو ربط المورد.

الطريقةالمسارالصلاحيةماذا يفعل
GET/:storeId/cataloguesuppliers.viewالموردون الذين يستطيع هذا المتجر ربطهم، وما يستطيعه كل منهم.
GET/:storeIdsuppliers.viewعمليات ربط الموردين في المتجر، مع حالتها وإعدادات الأتمتة. لا تُعاد بيانات الاعتماد أبدًا.
POST/:storeIdsuppliers.manageربط مورد بمفتاح API الخاص به. يُتحقق من المفتاح لدى المورد قبل حفظه.
POST/:storeId/oauth/startsuppliers.manageبدء ربط مورد يعتمد تسجيل الدخول، مثل AliExpress. يعيد العنوان الذي يُرسل إليه التاجر.
PUT/:storeId/:idsuppliers.manageاستبدال بيانات اعتماد الربط.
POST/:storeId/:id/testsuppliers.manageفحص الربط الآن وتسجيل حالته.
GET/:storeId/:id/balancesuppliers.viewرصيدك لدى المورّد، إن كان المورّد يُبلغ عنه.
GET/:storeId/:id/impactsuppliers.viewما سيتأثر بإلغاء الربط — المنتجات المرتبطة وطلبات المورد المفتوحة.
PUT/:storeId/:id/settingssuppliers.manageتغيير إعدادات المورد الخاصة.
PUT/:storeId/:id/automationsuppliers.manageتغيير طريقة إرسال الطلبات والحدود.
PUT/:storeId/:id/enabledsuppliers.manageتشغيل الربط أو إيقافه.
DELETE/:storeId/:idsuppliers.manageإلغاء الربط. تُحذف بيانات الاعتماد، وتبقى المنتجات المستوردة ملكًا للمتجر.

منتجات المورد والاستيراد والروابط

Section titled “منتجات المورد والاستيراد والروابط”
الطريقةالمسارالصلاحيةماذا يفعل
GET/:storeId/:id/productssuppliers.importتصفح كتالوج المورد أو البحث فيه.
POST/:storeId/:id/products/resolve-urlsuppliers.importتحويل رابط منتج ملصوق إلى معرّف المنتج لدى المورد.
GET/:storeId/:id/products/:supplierProductIdsuppliers.importمنتج واحد لدى المورد مع متغيّراته وتكاليفه ومخزونه.
POST/:storeId/:id/import/previewsuppliers.importتسعير المنتجات المختارة بقاعدة التسعير وذكر أي مكررات. لا يُخصم شيء.
POST/:storeId/:id/importsuppliers.importاستيراد حتى 50 منتجًا. الاستيراد الكبير يعيد معرّف مهمة لمتابعتها.
GET/:storeId/imports/:jobIdsuppliers.importتقدّم استيراد يعمل في الخلفية.
GET/:storeId/linkssuppliers.viewروابط منتجات المتجر.
POST/:storeId/linkssuppliers.importربط منتج يملكه المتجر بمنتج لدى المورد.
PUT/:storeId/links/:linkIdsuppliers.importتغيير متغيّرات الرابط أو قاعدة تسعيره أو مفاتيح المزامنة.
DELETE/:storeId/links/:linkIdsuppliers.importإلغاء الربط. يبقى المنتج ملكًا للمتجر.
POST/:storeId/links/:linkId/syncsuppliers.importمزامنة رابط واحد الآن.
الطريقةالمسارالصلاحيةماذا يفعل
GET/:storeId/orderssuppliers.viewطلبات المورد، الأحدث أولًا، مصفّاة ومقسّمة إلى صفحات بمؤشّر. حقول الاستعلام مذكورة أسفل الجدول.
GET/:storeId/orders/:supplierOrderIdsuppliers.viewطلب مورد واحد مع سجله.
POST/:storeId/orders/:orderId/groups/:groupKey/submitsuppliers.orders.manageإرسال جزء واحد من الطلب إلى مورده الآن.
POST/:storeId/orders/:supplierOrderId/retrysuppliers.orders.manageإعادة محاولة طلب مورد في الانتظار أو متوقف أو فاشل.
POST/:storeId/orders/:supplierOrderId/paysuppliers.orders.manageدفع طلب مورد أُنشئ ولم يُدفع.
POST/:storeId/orders/:supplierOrderId/cancelsuppliers.orders.manageسحب الطلب لدى المورد، إن كان المورد ما زال يسمح بذلك.
POST/:storeId/orders/:orderId/groups/:groupKey/fulfil-manuallysuppliers.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 — يحمل كل طلب في القائمة ملخصًا لأجزائه، وتقبل القائمة مرشحًا للطلبات التي فيها جزء يحتاج إلى مراجعة.

  • supplierKey — أي مورد، باسمه في الكتالوج.
  • mode — اختبار أو مباشر.
  • enabled — هل الربط مُشغَّل.
  • hasCredentials — هل بيانات الاعتماد محفوظة. أما البيانات نفسها فلا تُعاد أبدًا.
  • automation — طريقة إرسال الطلبات والحدود التي توقفها.
  • health — نتيجة آخر فحص.
  • isCircuitOpen, circuitOpenUntil — الربط متوقف مؤقتًا بعد أخطاء متكررة، حتى ذلك الوقت.
  • lastWebhookAt — متى أرسل المورد آخر إشعار.
  • webhookUrl — العنوان الذي يرسل إليه المورد إشعاراته، ويظهر في قائمة عمليات الربط. ويكون فارغًا حين لا يُضبط عنوان عام.
  • productId, supplierProductId — منتج المتجر ومنتج المورد المرتبط به.
  • variants[] — كل متغيّر في المتجر مرتبط بمتغيّر لدى المورد، مع تكلفته ومخزونه.
  • priceRule — كيف يُحسب سعر المتجر من التكلفة.
  • sync — الحقول التي يحق للمزامنة التي تتم كل ساعة تغييرها.
  • lastSyncAt, lastSyncError — آخر مزامنة، وسبب فشلها إن فشلت.
  • status — أين وصل طلب المورد. يسرد الجدول أدناه كل القيم.
  • reviewReason, reviewMessage — سبب توقفه، كسبب واحد من قائمة مغلقة، وكلام المورد بعد حذف أي معلومات حساسة.
  • retryable — هل قد تنجح إعادة المحاولة دون تغيير أي شيء.
  • supplierOrderNumber — رقمنا، يُرسل إلى المورد رقمًا لطلبه. ولا يتغير بين محاولات الإعادة للمحاولة نفسها.
  • supplierOrderId, supplierStatus — معرّف المورد وحالته، كما يكتبها المورد.
  • costs, payment — ما يتقاضاه المورد، وهل دفعه المتجر.
  • shipping — شركة الشحن ورقم التتبع بعد أن يشحن المورد.
  • attempt, events[] — رقم هذه المحاولة، وسجلها.
  • destination, destinationRedacted — عنوان التوصيل، لمن يُسمح له برؤية بيانات العملاء فقط. وإلا فيُحذف، ويُشير إلى ذلك حقل مخصص (flag).

dropshipping.developer.objects.paymentValuesList

  • fulfilmentGroups[] — أجزاء الطلب — جزء لمنتجات المتجر نفسه وجزء لكل ربط مورد — ولكل جزء حالته ومنتجاته وشحنته.
  • fulfilmentSummary — عدد الأجزاء، وكم منها تم شحنه أو توصيله.
  • supplierOrders[] — طلبات الموردين الخاصة بهذه الأجزاء، لمن يُسمح له برؤية الموردين.

يتقدّم الطلب بسرعة أبطأ أجزائه, فلا يصبح «تم الشحن» إلا بعد شحن جميع أجزائه، ولا يصبح «تم التوصيل» إلا بعد توصيلها جميعًا.

القيمةالمعنىما يمكن للبرنامج فعله
pendingلم يبدأ بعد.لا شيء — انتظر.
processingقيد التجهيز، لدى المتجر أو المورد.لا شيء — انتظر.
shippedسُلِّم إلى شركة الشحن.اقرأ التتبع من شحنة الجزء.
deliveredتم التوصيل. حالة نهائية.لا شيء — انتظر.
cancelledملغى. حالة نهائية.لا شيء — انتظر.
القيمةالمعنىما يمكن للبرنامج فعله
queuedفي انتظار الإرسال.لا شيء — انتظر.
needsReviewمتوقف مع سبب. يحتاج إلى شخص أو إلى تغيير في المدخلات.اعرضه على شخص. ولا تُعِد المحاولة إلا بعد تغيّر السبب.
submittedأُنشئ لدى المورد، ولم يُقبل ويُدفع بعد.ادفعه، إن كان المتجر يدفع يدويًا.
confirmedقُبل ودُفع لدى المورد.لا شيء — انتظر.
processingقيد التجهيز لدى المورد.لا شيء — انتظر.
shippedشحنه المورد، مع رقم تتبع.لا شيء — انتظر.
deliveredتم التوصيل. حالة نهائية.لا شيء — انتظر.
cancelledأُلغي. حالة نهائية.لا شيء — انتظر.
failedخطأ مؤقت، مثل انتهاء المهلة. تعيد المهمة المحاولة تلقائيًا.أعد المحاولة مرة واحدة إذا توقفت المحاولات التلقائية.

يحمل طلب المورّد المتوقف سببًا واحدًا فقط من هذه الأسباب. والعمود الثاني هو القيمة التي يضبطها API لكل سبب.

القيمةretryableالمعنىما يمكن للبرنامج فعله
insufficientBalancefalseلا يكفي رصيد المتجر لدى المورّد لتغطية الطلب.أبلغ شخصًا. وأعد المحاولة بعد شحن الرصيد.
variantUnavailablefalseلم يعد المورد يوفّر أحد المتغيّرات.لا شيء دون تدخّل شخص.
destinationUnsupportedfalseالمورد لا يوصل إلى هناك، أو أن المتجر استثنى الدولة.لا شيء دون تدخّل شخص.
costAboveLimitfalseالتكلفة أعلى من حد وضعه المتجر.أعد المحاولة بقرار من شخص فقط.
costChangedfalseتغيّر سعر المورد منذ الاستيراد.أعد المحاولة مع قبول التكلفة الجديدة، بقرار من شخص فقط.
customerPaymentPendingfalseلم يدفع المتسوّق إلكترونيًا.أرسله عندما يقرر المتجر ذلك.
customerPaymentNotSettledfalseتم تفويض الدفع لكنه لم يُسوَّ بعد.أعد المحاولة بعد تسوية الدفع.
connectionUnhealthytrueلم يستجب المورد، أو أن الربط متوقف مؤقتًا.أعد المحاولة لاحقًا.
supplierRefusedtrueرفض المورد الطلب.اقرأ الرسالة. وأعد المحاولة بعد معالجة السبب.
connectionMissingfalseالربط متوقف أو محذوف، أو أن Posty5 أوقف المورد.لا شيء؛ يلزم تدخّل بشري.
supplierAlreadyShippedfalseجاء الإلغاء بعد أن شحن المورد.لا شيء — عامِله كمرتجع.
testModefalseربط تجريبي بمورد لا يوفّر بيئة اختبار. لم يُقدَّم أي طلب.لا شيء حتى يعمل الربط في الوضع الفعلي.
customerCaptureFailedfalseالوعد بالبيع — دُفع للمورد، وفشل تحصيل المبلغ من المتسوّق.أبلغ شخصًا فورًا.

POST /api/store-suppliers/webhook/:supplierKey/:integrationId

الموردون الذين يرسلون إشعارات يستدعون هذا العنوان للإبلاغ عن حالة الطلب والتتبع والمخزون.

يعثر Posty5 على الربط من العنوان ويتحقق من الرسالة ببيانات اعتماد ذلك الربط. كل رفض يتلقى الإجابة 400 نفسها، و503 حين لا يستطيع Posty5 الحسم، فيعيد المورد الإرسال. الإشعار لا يفعل أكثر من دفع Posty5 إلى قراءة الطلب من المورد، ولا يحرّك بنفسه مالًا ولا مخزونًا ولا حالة أبدًا.


منع التكرار وإعادة المحاولة

Section titled “منع التكرار وإعادة المحاولة”

يُحمى طلب المورد من التكرار بثلاث طرق.

  • مهمة واحدة لكل جزء من الطلب، أيًّا كان مُطلقها —
  • مفتاح فريد لكل محاولة، يُرسل إلى المورد رقمًا لطلبه. وقبل الإنشاء يسأل Posty5 المورد هل هذا الرقم موجود، فيُعثر على الإنشاء الذي انتهت مهلته بعد نجاحه ولا يُكرَّر.
  • قبل الدفع يقرأ Posty5 حالة الطلب لدى المورد. والطلب المدفوع هناك يُسجَّل ولا يُدفع مرة ثانية.
  • استدعاء الإرسال مرتين ينتج طلب مورد واحدًا.
  • dropshipping.developer.idem.rules.retryWhen
  • الطلب المتوقف لا يُحل من تلقاء نفسه. يحتاج إلى تدخّل شخص، أو إلى تغيير في المدخلات.
  • لمتابعة الطلب، اقرأ طلب المورد من جديد. ولا تستدعِ الإرسال في حلقة.

في المستويات التلقائية، يُرسل جزء المورد مرة واحدة، عندما يصبح الطلب مؤكدًا — بتأكيد عضو في الفريق أو بدفع إلكتروني.

يتطلب الدفع التلقائي للمورد أن تكون دفعة المتسوّق مدفوعة بتأكيد مزوّد الدفع. والطلب بلا دفع إلكتروني ينتظر ما لم يسمح الربط بالطلبات غير المدفوعة.

في الوعد بالبيع، يبدأ الإرسال بعد تفويض دفعة المتسوّق، ويُحصَّل المبلغ من المتسوّق عندما يقبل المورد.


عرض طلبات المورد التي تنتظر المراجعة —

Terminal window
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.

تتضمن كلٌّ من حزمتي المتجر لـ JavaScript و.NET عميلًا للموردين يغطي كل المجموعات أعلاه — الكتالوج، وعمليات الربط، ومنتجات المورد، والاستيراد، والروابط، وطلبات المورد. وعندما يتوقف طلب المورد للمراجعة، تُطلق عمليات الإرسال وإعادة المحاولة والدفع خطأً بدلًا من إرجاع نتيجة، فاقرأ طلب المورد مجددًا لمعرفة السبب.

  • npm — @posty5/store 4.3.0 — store.suppliers
  • NuGet — Posty5.Store 3.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) الموردين، ومنتجات المورد، وروابط المنتجات، وطلبات المورد، وأجزاء الطلبات، والطلبات. ولم تُنشر بعد هي أيضًا.