نظرة عامة
أرسل طلبات شحن الألعاب من نظامك وتابع كل طلب حتى حالته النهائية. تُدفع الطلبات مسبقًا من رصيدك، فلا يوجد ائتمان ولا يصبح الرصيد سالبًا.
- الرابط الأساسي:
https://thenexus.store/api/reseller/v1 - يوافق فريقنا على الوصول إلى API بعد الموافقة على حساب الموزع. ولا يتم ذلك تلقائيًا أبدًا.
- لا توجد بيئة تجريبية (sandbox). كل دفعة طلب حقيقي يُدفع من رصيدك، فابدأ بطلب صغير واحد.
خطوات البدء
- أنشئ حساب موزع. لا تحتاج إلى كود شريك. يراجعه فريقنا.
- اشحن رصيدك بالدولار من قسم المحفظة في لوحتك. التحويلات البنكية مقبولة بالدولار أو اليورو إلى حساب بنكي أوروبي، أو إلى حساب بنكي مصري.
- اطلب الوصول إلى API من قسم API في لوحتك. بعد الموافقة أنشئ مفتاحًا من هناك. يظهر المفتاح مرة واحدة.
- تحقق من الاتصال بـ GET /account، واقرأ أسعارك بـ GET /products، ثم أرسل دفعة صغيرة بـ POST /batches.
- اختياري: حدّد رابط webhook لتصلك تحديثات الطلبات دون استعلام متكرر.
curl https://thenexus.store/api/reseller/v1/account \
-H 'X-Nexus-API-Key: nxr_your_key_here' المصادقة
أرسل مفتاحك في الترويسة X-Nexus-API-Key مع كل طلب. يبدأ المفتاح بـ nxr_ ثم 48 حرفًا ست عشريًا. نحفظ hash فقط، فلا يمكن عرض المفتاح المفقود مرة أخرى: ألغه وأنشئ مفتاحًا جديدًا.
- صلاحيات كل مفتاح: products.read وbatches.create وbatches.read.
- حتى 5 مفاتيح فعّالة لكل حساب. ينتهي المفتاح بعد 1 إلى 730 يومًا، و365 افتراضيًا.
- يتحقق كل طلب من أن الحساب والوصول إلى API ما زالا معتمدين.
قواعد عامة
- JSON في الطلب وفي الرد، UTF-8. الحد الأقصى لحجم الطلب 256 كيلوبايت.
- المبالغ أرقام عشرية بالجنيه المصري، عملة المتجر. ويعيد GET /account وGET /balance وGET /products أيضًا القيمة بالدولار في حقول *_usd: الرصيد يُقرَّب للأسفل إلى السنت، والأسعار للأعلى.
- يحمل كل رد X-Request-ID. اذكره عند التواصل مع الدعم.
- لا تتضمن الردود أسماء الموردين ولا التكلفة.
الكتالوج
GET/api/reseller/v1/productsproducts.read
المنتجات النشطة بسعرك. المنتج الذي ليس له سعر آمن للموزعين لا يظهر. إذا كانت manual_fulfilment تساوي true فإن فريقنا يسلّمه يدويًا. تكون stock تساوي null إذا لم تكن محسوبة. الصفحات: per_page افتراضيًا 100.
{
"products": [
{"id": "3f2c0d4e-...", "title": "Example top-up pack", "category": "topup",
"retail_price": 100.00, "reseller_price": 97.00,
"retail_price_usd": 2.00, "reseller_price_usd": 1.94,
"currency": "EGP", "stock": null, "manual_fulfilment": false}
],
"page": 1, "per_page": 100, "has_more": false, "currency": "EGP"
} الرصيد والحساب
GET/api/reseller/v1/balanceproducts.read
{"balance": 1250.50, "balance_usd": 25.01, "currency": "EGP", "discount_percent": 3} GET/api/reseller/v1/accountproducts.read
{"account": {"tier": "starter", "discount_percent": 3, "balance": 1250.50, "balance_usd": 25.01,
"currency": "EGP", "scopes": ["products.read", "batches.create", "batches.read"],
"rate_limit_per_hour": 120, "key_expires_at": "2027-11-07 10:00:00"}} الأرقام أعلاه للتوضيح فقط.
إرسال الطلبات
POST/api/reseller/v1/batchesbatches.create
تحمل الدفعة من 1 إلى 50 عنصرًا وتُدفع من رصيدك فورًا. الترويسة Idempotency-Key إلزامية (من 8 إلى 100 حرف: حروف وأرقام و . _ : -). وللطلب حقل واحد هو items.
| الحقل | القاعدة |
|---|---|
client_ref | إلزامي. مرجعك الخاص، من 1 إلى 100 حرف (حروف وأرقام و . _ : -)، وفريد داخل الدفعة. |
product_id | إلزامي. معرّف المنتج من GET /products. |
quantity | من 1 إلى 1000، والافتراضي 1. |
delivery | كائن يحمل بيانات اللاعب التي يحتاجها المنتج (انظر بيانات اللاعب). |
curl -X POST https://thenexus.store/api/reseller/v1/batches \
-H 'X-Nexus-API-Key: nxr_your_key_here' \
-H 'Idempotency-Key: order-1042-try-1' \
-H 'Content-Type: application/json' \
-d '{"items":[{"client_ref":"order-1042","product_id":"3f2c0d4e-...","quantity":1,"delivery":{"game_id":"123456789"}}]}' HTTP 201
{
"batch_code": "NXB-A1B2C3D4E5", "status": "completed", "item_count": 1,
"total": 97.00, "currency": "EGP",
"items": [{"client_ref": "order-1042", "order_code": "NX-...", "state": "processing",
"unit_price": 97.00, "total": 97.00, "manual_fulfilment": false}]
} تعني القيمة completed في status أن الدفعة قُبلت ودُفعت، وليس أن كل العناصر سُلّمت. تابع كل عنصر بحالته.
GET/api/reseller/v1/batchesbatches.read
دفعاتك من الأحدث: batch_code وstatus وitem_count وtotal وcurrency وcreated_at. الصفحات: per_page افتراضيًا 50.
GET/api/reseller/v1/batches/{batch_code}batches.read
دفعة واحدة مع عناصرها: client_ref وproduct_id وquantity وunit_price وtotal وorder_code وstate وmanual_fulfilment، ومعها error_code وerror_message إذا فشل عنصر.
بيانات اللاعب
ضع ما يحتاجه المنتج داخل delivery. هذه هي المفاتيح الشائعة، وبعض المنتجات تأخذ مفاتيح أخرى تُذكر مع المنتج. المفاتيح غير المعروفة تُرفض بـ HTTP 422.
| المفتاح | الاستخدام |
|---|---|
game_id | معرّف اللاعب أو الحساب داخل اللعبة، حتى 120 حرفًا. |
server | السيرفر أو المنطقة إن وُجدت في اللعبة، حتى 50 حرفًا. |
region | المنطقة إذا طلبها المنتج، حتى 50 حرفًا. |
provider_fields | كائن بحقول نصية إضافية يحتاجها بعض الشحن، كل حقل حتى 200 حرف. |
لا يستطيع API التحقق من معرّف اللاعب قبل الطلب، ولا يوجد endpoint للتحقق حاليًا. المنتجات التي تحتاج تسجيل دخول المشتري إلى حساب اللعبة تُرفض بالرمز interactive_login_required. وإذا تعذّر تسليم الطلب ينتقل إلى failed ويعود المبلغ كاملًا إلى رصيدك.
حالة الطلب
GET/api/reseller/v1/ordersbatches.read
طلباتك من الأحدث. اختياري: state (إحدى الحالات أدناه) وlimit (من 1 إلى 100، والافتراضي 50). هذه القائمة بلا صفحات.
GET/api/reseller/v1/orders/{order_code}batches.read
{"order": {"order_code": "NX-...", "client_ref": "order-1042", "product": "Example top-up pack",
"quantity": 1, "total": 97.00, "currency": "EGP", "state": "delivered",
"manual_fulfilment": false, "refunded_to_balance": false,
"created_at": "2026-11-01 10:00:00", "updated_at": "2026-11-01 10:02:10"}} | state | المعنى |
|---|---|
pending | تم القبول. يسلّم فريقنا هذا المنتج يدويًا، فلا يكون تلقائيًا. |
processing | تم الدفع من رصيدك، ويجري التسليم تلقائيًا. |
delivered | تم التسليم. حالة نهائية. |
failed | تعذّر التسليم. أُعيد المبلغ كاملًا إلى رصيدك مرة واحدة. |
refunded | ردّه الفريق. عاد المبلغ إلى رصيدك. |
تعيد الطلبات الفاشلة والمردودة المبلغ إلى رصيدك مرة واحدة فقط، كسطر جديد في سجل الرصيد. ولا يُعدَّل السجل القديم أبدًا.
تقسيم الصفحات
يقبل GET /products وGET /batches المعاملين page (من 1) وper_page (من 1 إلى 100) ويعيدان page وper_page وhas_more. اطلب الصفحة التالية ما دامت has_more تساوي true.
curl 'https://thenexus.store/api/reseller/v1/batches?page=2&per_page=25' -H 'X-Nexus-API-Key: nxr_your_key_here' Idempotency
أرسل Idempotency-Key فريدًا مع كل دفعة. إرسال المفتاح نفسه بالطلب نفسه يعيد الدفعة المحفوظة بـ HTTP 200 مع الترويسة Idempotent-Replayed: true، ولا يخصم مرتين. يحمل الرد المكرر إجماليات الدفعة دون العناصر: اقرأها بـ GET /batches/{batch_code}. والمفتاح نفسه مع طلب مختلف يُرفض بالرمز idempotency_key_mismatch.
بعد أي انقطاع كرّر الطلب نفسه بالمفتاح نفسه. واستخدم مفتاحًا جديدًا لدفعة جديدة فقط.
Webhooks والتوقيع
حدّد endpoint بـ HTTPS من قسم API في لوحتك، ويظهر الـ signing secret مرة واحدة. تُرسل الـ webhooks فقط ما دام الوصول إلى API معتمدًا. يجب أن يكون العنوان HTTPS عامًا على المنفذ 443، ولا تُتبع إعادات التوجيه.
| الحدث | متى |
|---|---|
order.pending | طلب ينتظر فريقنا. |
order.processing | طلب يجري تسليمه تلقائيًا. |
order.delivered | تم تسليم طلب. |
order.failed | فشل طلب وعاد المبلغ إلى رصيدك. |
order.refunded | ردّ الفريق طلبًا إلى رصيدك. |
batch.completed | قُبلت دفعة ودُفعت. يُرسل مرة واحدة دون إعادة. |
كل طلب هو POST يحمل X-Nexus-Event وX-Nexus-Signature بالشكل t=<unix>,v1=<hex>. التوقيع هو HMAC-SHA256 للنص "<t>.<raw body>" باستخدام secret الخاص بك. قارن بوقت ثابت وارفض أي timestamp أقدم من 5 دقائق.
{"id": "...", "event": "order.failed", "created_at": "2026-11-01T10:05:00+00:00",
"data": {"order_code": "NX-...", "client_ref": "order-1042", "state": "failed",
"total": 97.0, "currency": "EGP", "manual_fulfilment": false, "credited_to_balance": true}} // PHP
$parts = [];
foreach (explode(',', $_SERVER['HTTP_X_NEXUS_SIGNATURE'] ?? '') as $p) { [$k, $v] = array_pad(explode('=', $p, 2), 2, ''); $parts[$k] = $v; }
$raw = file_get_contents('php://input');
$ok = isset($parts['t'], $parts['v1'])
&& abs(time() - (int)$parts['t']) <= 300
&& hash_equals(hash_hmac('sha256', $parts['t'] . '.' . $raw, $secret), $parts['v1']); أجب بأي status من 2xx خلال 4 ثوانٍ. يُرسل كل حدث طلب حتى 6 مرات بفواصل متزايدة إلى أن تجيب بـ 2xx. يتغير id مع كل محاولة، لذا أزل التكرار باستخدام order_code مع state. الـ webhooks وسيلة مساعدة، وتبقى endpoints الطلبات هي المرجع دائمًا.
الأخطاء
تأتي الأخطاء بصيغة JSON مع رسالة error وrequest_id. وكثير منها يحمل code يمكن للبرامج قراءته.
{"error": "Insufficient reseller wallet balance", "request_id": "..."} | HTTP | المعنى |
|---|---|
400 | رصيد المحفظة غير كافٍ. اشحن رصيدك ثم أرسل الدفعة من جديد بـ Idempotency-Key جديد. |
401 | invalid_api_key: المفتاح ناقص أو خاطئ أو ملغى أو منتهي، أو لم يعد الحساب أو الوصول إلى API معتمدًا. |
403 | suspended أو scope_denied: الحساب موقوف، أو المفتاح لا يملك الصلاحية التي يحتاجها هذا الـ endpoint. |
404 | الطلب أو الدفعة غير موجودين في حسابك. المنتج غير المعروف أو غير النشط داخل دفعة يعيد 409، والمعرّف غير الصحيح يعيد 422. |
409 | لا يمكن بيع المنتج للموزعين حاليًا. قيمة code إحدى: delivery_method_not_allowed أو delivery_region_unavailable أو interactive_login_required أو reseller_price_unavailable، أو غير موجودة (غير متاح أو نفد). لا يُخصم أي مبلغ. |
413 | body_too_large: حجم الطلب أكبر من 256 كيلوبايت. |
422 | خطأ في البيانات. من الرموز: idempotency_key_required وidempotency_key_invalid وidempotency_key_mismatch. |
429 | rate_limited: طلبات كثيرة لهذا المفتاح، أو مفاتيح خاطئة كثيرة من عنوان واحد. انتظر عدد الثواني في Retry-After. |
حدود الاستخدام
يسمح كل مفتاح بـ 120 طلبًا في الساعة افتراضيًا، ويمكن للفريق تحديد قيمة أخرى لكل مفتاح. وهناك حد قصير في الدقيقة يساوي سدس الحد بالساعة (10 على الأقل و120 على الأكثر). تحمل الردود الناجحة X-RateLimit-Limit. وبعد الحد يُرجَع HTTP 429 مع Retry-After.
أمثلة الكود
curl
curl https://thenexus.store/api/reseller/v1/products?per_page=100 \
-H 'X-Nexus-API-Key: nxr_your_key_here' Node.js
const res = await fetch('https://thenexus.store/api/reseller/v1/batches', {
method: 'POST',
headers: {
'X-Nexus-API-Key': process.env.NEXUS_KEY,
'Idempotency-Key': 'order-1042-try-1',
'Content-Type': 'application/json',
},
body: JSON.stringify({ items: [{ client_ref: 'order-1042', product_id: PRODUCT_ID, quantity: 1, delivery: { game_id: '123456789' } }] }),
});
if (res.status === 429) await new Promise(r => setTimeout(r, Number(res.headers.get('retry-after') || 1) * 1000));
console.log(res.status, await res.json()); Python
import os, time, requests
r = requests.post('https://thenexus.store/api/reseller/v1/batches',
headers={'X-Nexus-API-Key': os.environ['NEXUS_KEY'], 'Idempotency-Key': 'order-1042-try-1'},
json={'items': [{'client_ref': 'order-1042', 'product_id': PRODUCT_ID, 'quantity': 1, 'delivery': {'game_id': '123456789'}}]},
timeout=30)
if r.status_code == 429:
time.sleep(int(r.headers.get('Retry-After', 1)))
print(r.status_code, r.json()) التحقق من توقيع webhook (Node.js)
const crypto = require('crypto');
function verify(secret, header, rawBody, now = Date.now() / 1000) {
const m = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(header || '');
if (!m || Math.abs(now - Number(m[1])) > 300) return false;
const want = crypto.createHmac('sha256', secret).update(m[1] + '.' + rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(want), Buffer.from(m[2]));
} OpenAPI
وصف قابل للقراءة آليًا لهذه الـ endpoints، يقدّمه API نفسه: /api/reseller/v1/openapi.json
سجل التغييرات
انتقل هذا التوثيق إلى /resellers/docs. وأصبح ملف OpenAPI مطابقًا للكود: GET /orders يقبل state وlimit، ونقص الرصيد يعيد HTTP 400.
حالات الطلب مع GET /orders وGET /orders/{order_code}، وGET /balance وGET /account وقائمة GET /batches، وترويسة Idempotent-Replayed وملف OpenAPI. وتعود الطلبات الفاشلة والمردودة إلى الرصيد مرة واحدة.
Webhooks موقّعة. وأصبح الوصول إلى API موافقة مستقلة عن الحساب.
الإصدار الأول: GET /products وPOST /batches.
أسئلة عن API؟ افتح تذكرة من قسم الدعم في لوحتك.