NinjaBuy Business API
عنوان URL الأساسي
كل مسار في هذا الموقع يقع تحت عنوان URL أساسي واحد. تطبيق Shopify وكل ما تبنيه يستدعيان المسارات نفسها، فكل ما يفعله التطبيق يستطيع كودك فعله أيضًا.
https://www.ninjabuy.com/api/v1
تفضّل سؤال مساعد ذكاء اصطناعي؟ الحساب نفسه يعمل عبر MCP على https://www.ninjabuy.com/mcp: مساعدو الذكاء الاصطناعي (MCP).
- الاستيراداترابط تُدخله، وتكلفة بيعه كاملة تظهر لك.
- المنتجاتما تبيعه، وأين يُعرض.
- المتغيّراتكل خيار، مربوط بـ SKU البائع.
- مستويات المخزونما يمكنك بيعه الآن.
- قواعد المزامنةما يحدث حين يغيّر بائع سعرًا.
- الطلباتبيعة نشتريها ونفحصها ونشحنها.
- أوامر التنفيذالبنود التي تغادر في طرد واحد.
- الشحناتطرود في طريقها، مع التتبّع.
- الرصيدالمال الذي تُدفع منه الطلبات.
- نقاط نهاية webhookإلى أين نرسل الأحداث.
curl "https://www.ninjabuy.com/api/v1/balance" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11"المصادقة
أرسل مفتاح API كـ bearer token مع كل طلب. تبدأ المفاتيح بـ nb_. خلال الفترة التجريبية يصدرها فريقنا: بعد إعداد حساب Business نرسل كل مفتاح مرة واحدة، عبر قناة تختارها، بالنطاقات التي طلبتها. اطلب منا إلغاء مفتاح فيتوقف عن العمل من الطلب التالي.
احفظ المفاتيح على خادمك. المفتاح في متصفح أو تطبيق أو مستودع عام يمكن لأي أحد قراءته، ويمكنه إنفاق رصيدك.
التطبيق الذي يعمل نيابة عن بائعين آخرين على NinjaBuy يستخدم OAuth 2.1 بدلًا من ذلك: تسجيل عميل ديناميكي، وتدفق رمز التفويض مع PKCE (S256)، وشاشة موافقة البائع نفسه. رمز الوصول يوضع في الترويسة نفسها ويعمل على المسارات نفسها. رموز الوصول تدوم ساعة، ورموز التحديث تجددها لمدة سبعة أيام. ويتصل مساعدو الذكاء الاصطناعي بالطريقة نفسها (MCP).
products:readالنطاق- قراءة الاستيرادات والمنتجات والمتغيّرات وقواعد المزامنة.
products:writeالنطاق- استيراد المنتجات وتعديلها وإرسالها وحذفها، وتغيير قواعد المزامنة.
inventory:readالنطاق- قراءة مستويات المخزون.
orders:readالنطاق- قراءة الطلبات وأوامر التنفيذ والشحنات.
orders:writeالنطاق- إنشاء الطلبات وتعليقها والإفراج عنها وإلغاؤها. يُنفق من رصيدك.
balance:readالنطاق- قراءة الرصيد ومعاملاته.
webhooks:writeالنطاق- إدارة نقاط نهاية webhook.
أي استدعاء خارج نطاقات المفتاح يُرجع 403 insufficient-scope ويذكر النطاق المطلوب.
Authorization: Bearer nb_7Qk2...vX9eHTTP/2 401
{
"type": "https://www.ninjabuy.com/api/v1/problems/unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "The API key is missing, wrong, expired or revoked.",
"request_id": "req_7Hq2Lw9c"
}الإصدارات
يحمل المسار الإصدار الرئيسي، /v1. وداخله، تغيّر الإصدارات المؤرخة الحقول والسلوك. ثبّت الإصدار الذي بنيت عليه بترويسة NinjaBuy-Version؛ وكل رد يذكر الإصدار الذي استخدمه في الترويسة نفسها.
2026-11 هو الإصدار الحالي، وهو إصدار تجريبي: قد تتغير الأسماء والحقول قبل اعتماده إصدارًا مستقرًا. كل تغيير مذكور في سجل التغييرات، ونُبلغ كل حامل مفتاح بالبريد الإلكتروني قبل أي تغيير قد يعطّل عمله.
داخل الإصدار الواحد لا نفعل إلا الإضافة: مسارات جديدة، ومعاملات اختيارية جديدة، وحقول جديدة في الردود، وأنواع أحداث جديدة. ابنِ عميلك ليتجاهل الحقول التي لا يعرفها.
GET /api/v1/orders
NinjaBuy-Version: 2026-11
HTTP/2 200
NinjaBuy-Version: 2026-11الطلبات والردود
- أرسل JSON مع
Content-Type: application/json؛ الردود JSON بترميز UTF-8. الأخطاءapplication/problem+json. - المبلغ كائن فيه نص عشري وعملة:
{ "amount": "264.20", "currency": "CNY" }. ما يتقاضاه NinjaBuy بـ CN¥، وأسعار بيعك بعملة متجرك. - المعرّفات نصوص ببادئة تدل على نوعها (
prd_وord_وshp_). تعامل معها كقيم معتمة. - الأوقات بصيغة ISO 8601 بتوقيت UTC. والدول برموز ISO من حرفين.
- كل رد يحمل ترويسة
X-Request-Id، وكل خطأ يحمل المعرّف نفسه فيrequest_id. اذكره حين تراسلنا.
{
"id": "ord_3n7q",
"created_at": "2026-11-01T09:14:02Z",
"total": { "amount": "264.20", "currency": "CNY" },
"suggested_price": { "amount": "49.99", "currency": "USD" }
}ترقيم الصفحات
القوائم تُرجع الأحدث أولًا، في data وhas_more وcursor. أرسل ذلك الـ cursor مجددًا للصفحة التالية ما دام has_more يساوي true. الـ cursor لا يعمل إلا مع عوامل التصفية التي جاء منها.
limitinteger- من 1 إلى 100. القيمة 25 إن لم تُحدَّد.
cursorstring- cursor الصفحة السابقة. اتركه فارغًا للصفحة الأولى.
curl "https://www.ninjabuy.com/api/v1/orders?limit=25&cursor=c_2v9kq" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11"HTTP/2 200 OK
{
"data": [
{ "id": "ord_3n7q", "status": "checked" },
{ "id": "ord_3n6z", "status": "shipped" }
],
"has_more": true,
"cursor": "c_1q4ea"
}حدود المعدّل
الحدود لكل حساب، تتشاركها كل مفاتيحه ورموز OAuth واتصال MCP. كل رد يوضح موقفك في ترويستي IETF RateLimit-Policy وRateLimit، والرفض هو 429 rate-limited مع Retry-After بالثواني.
| النافذة | ما يُحتسب |
|---|---|
| "create-links";q=30;w=60 | الاستدعاءات التي تقرأ صفحة منتج من المنصة: إنشاء استيراد أو تحديثه، وإرسال منتج. 30 في الدقيقة، مشتركة مع links API وMCP. |
| "default";q=120;w=60 | كل الاستدعاءات الأخرى. 120 في الدقيقة. |
HTTP/2 429
Content-Type: application/problem+json
Retry-After: 12
RateLimit-Policy: "create-links";q=30;w=60
RateLimit: "create-links";r=0;t=12
{
"type": "https://www.ninjabuy.com/api/v1/problems/rate-limited",
"title": "Too many requests",
"status": 429,
"detail": "Try again in 12 seconds.",
"request_id": "req_7Hq2Lw9c"
}Idempotency
أرسل Idempotency-Key (من 1 إلى 255 حرف ASCII قابلًا للطباعة؛ والـ UUID مثالي) مع أي POST، فلا تستطيع إعادة المحاولة بعد انتهاء المهلة إنشاء طلب ثانٍ. لمدة 24 ساعة، المفتاح نفسه على المسار نفسه بالنص نفسه يُرجع الرد الأول مجددًا بايتًا ببايت، مع Idempotent-Replayed: true، دون تنفيذ جديد ودون احتسابه من أي حد.
- المفتاح نفسه بنص أو مسار مختلف:
422 idempotency-key-reused. - الطلب الأول ما زال قيد التنفيذ:
409 idempotency-key-in-progress، معRetry-After. - رفض تجاوز الحد ليس إجابة: يبقى المفتاح متاحًا، فإعادة المحاولة بعد
Retry-Afterتنفّذ الطلب.
تحمل الطلبات أيضًا external_id الخاص بك: الطلب الثاني بالقيمة نفسها يُرفض بـ 409 duplicate-order، أيًّا كان المفتاح الذي أُرسل به.
POST /api/v1/orders
Idempotency-Key: 4f0c2b4e-9d1a-4e0f-b0a8-5d1d3c7e2f61
HTTP/2 201
Idempotent-Replayed: true
X-Request-Id: req_7Hq2Lw9cالأخطاء
الأخطاء بصيغة problem JSON (RFC 9457): type عنوان URL ثابت تبني عليه منطقك، وtitle يسمّيه، وdetail يشرح هذه الحالة بكلمات يمكنك عرضها، وrequest_id يحدد موضعها في سجلاتنا. النص الذي يفشل في التحقق يضيف errors، لكل منها pointer بصيغة JSON يشير إلى الحقل.
| الحالة | النوع | متى |
|---|---|---|
| 400 | bad-json | النص ليس JSON. |
| 400 | bad-body | حقل مفقود أو خاطئ، ويشير إليه errors[]. |
| 400 | bad-idempotency-key | Idempotency-Key فارغ، أو طويل جدًا، أو ليس ASCII قابلًا للطباعة. |
| 401 | unauthorized | المفتاح أو الرمز مفقود أو خاطئ أو منتهي الصلاحية أو ملغى. |
| 403 | insufficient-scope | المفتاح يفتقد النطاق الذي يحتاجه المسار. |
| 404 | not-found | لا يوجد كائن كهذا في هذا الحساب. معرّفات حساب آخر تُرجع الرد نفسه. |
| 405 | method-not-allowed | المسار موجود، لكن ليس بهذه الطريقة؛ تذكر Allow الطرق التي يقبلها. |
| 409 | duplicate-order | يوجد طلب بهذا external_id، ويذكره order. |
| 409 | idempotency-key-in-progress | الطلب الأول بهذا المفتاح ما زال قيد التنفيذ. |
| 409 | invalid-state | لا يستطيع الكائن فعل ذلك الآن، مثل إلغاء طلب مشحون. |
| 415 | unsupported-media-type | النص ليس application/json. |
| 422 | idempotency-key-reused | استُخدم المفتاح لطلب مختلف. |
| 422 | unprocessable | JSON صالح لا نستطيع التصرف بناءً عليه: رابط غير مقروء، أو متغيّر نافد. يوضح detail أيهما. |
| 429 | rate-limited | استدعاءات كثيرة جدًا في النافذة. انتظر Retry-After ثانية. |
| 500 | internal-error | الخطأ من جهتنا. أعد المحاولة بـ Idempotency-Key نفسه. |
| 503 | service-unavailable | لم نستطع التحقق من المفتاح أو الوصول إلى متجر الآن. أعد المحاولة بعد Retry-After. |
HTTP/2 400
{
"type": "https://www.ninjabuy.com/api/v1/problems/bad-body",
"title": "Invalid request body",
"status": 400,
"detail": "1 field is invalid.",
"request_id": "req_7Hq2Lw9c",
"errors": [
{
"pointer": "/ship_to/country",
"detail": "Must be a two-letter country code."
}
]
}