MAS4GAMES

للمطورين · الإصدار v1

واجهة Mas4games البرمجية للموزعين

بِع منتجاتنا تلقائيًا في موقعك أو تطبيقك أو لوحتك. تُدفع الطلبات من رصيدك فورًا وتصلك الأكواد خلال ثوانٍ، وكل خطوة واضحة وموثّقة وقابلة للاختبار.

عنوان API

Base URL
https://api.mas4games.com/v1
في هذه الصفحة

البدء السريع

أرسل طلبك الأول في ثلاث خطوات.

  1. 1

    احصل على مفاتيحك

    يُنشئ فريق الدعم لحسابك مفتاح اختبار (m4gc_test_…) ومفتاحًا حيًّا (m4gc_live_…)، ولكلٍّ منهما سرّ توقيع للإشعارات (whsec_…).

  2. 2

    جرّب في بيئة الاختبار

    بمفتاح الاختبار تحصل على الكتالوج والأسعار الحقيقية، أما الطلبات فتُسلَّم بأكواد وهمية دون أي حركة في المال أو المخزون.

  3. 3

    انتقل إلى التشغيل الحي

    شغّل الشيفرة نفسها بالمفتاح الحي. تُدفع الطلبات من رصيدك، وتصل الأكواد الحقيقية عبر GET /orders/{id} وعبر الإشعار.

الطلب
curl https://api.mas4games.com/v1/me \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY"
الرد
{
  "object": "account",
  "id": 18452,
  "name": "Örnek Bayi",
  "email": "[email protected]",
  "email_verified": true,
  "customer_type": "Bayi",
  "created_at": "2024-03-12T09:41:00Z",
  "currency": "TRY",
  "currency_decimals": 2,
  "balances": [
    { "amount": 1245075, "currency": "TRY", "decimals": 2 }
  ],
  "key": {
    "mode": "live",
    "created_at": "2026-11-06T08:00:00Z",
    "allowed_ips": ["203.0.113.10/32"],
    "webhook_url": "https://bayi.example.com/webhooks/mas4games"
  }
}

المصادقة

أرسل مفتاحك السري في ترويسة Authorization مع كل طلب:

HTTP
Authorization: Bearer m4gc_live_YOUR_SECRET_KEY
  • بداية المفتاح تدل على بيئته: m4gc_live_ للطلبات الحقيقية، وm4gc_test_ لبيئة الاختبار. وطلبات البيئتين منفصلة.
  • احفظ المفتاح على خادمك فقط، ولا تضعه في متصفح أو تطبيق جوال أو مستودع شيفرة.
  • يمكننا عند طلبك قصر مفتاحك على عناوين IP لخوادمك، فيُرفض أي طلب من عنوان آخر برمز 401.
  • إذا تسرّب مفتاح فاطلب تجديده فورًا: يتوقف القديم لحظة إصدار الجديد. ويُجدَّد معه سرّ توقيع الإشعارات ويُحذف عنوان الإشعارات، فحدّده من جديد بالمفتاح الجديد عبر PUT /webhook.

بيئة الاختبار

الطلبات بمفتاح الاختبار تستخدم الكتالوج والأسعار والقواعد الحقيقية، أما الطلبات فمحاكاة: لا يُخصم رصيد ولا يتغير مخزون.

منتجات الأكواد تُسلَّم فورًا بأكواد وهمية موسومة بوضوح: TEST-7F3A-91C2-0D44.

بمفتاح الاختبار يعرض GET /me رصيدًا وهميًا واحدًا بعملة المفتاح: 1000000 بأصغر وحداتها (أي 10,000.00 في عملة ذات منزلتين عشريتين)، ولا يتغير أبدًا. ويعيد GET /balance/transactions قائمة فارغة.

لتجربة الأخطاء والحالات، ابدأ حقل reference في الطلب هكذا:

referenceالمعنى وما يُفعل
test_insufficient_balance…يُرفض الطلب برمز 402 insufficient_balance.
test_cancelled…تعود الأسطر ملغاة (cancelled).
test_processing…تبقى الأسطر قيد المعالجة (processing) لتجربة نقطة الإلغاء.

تُرسل الإشعارات لطلبات الاختبار أيضًا، ويكون حقل mode في الأحداث test.

يضع مفتاح الاختبار 500 طلب اختبار على الأكثر في 24 ساعة؛ وما زاد يُردّ عليه في POST /orders برمز 429 rate_limited، وتخبرك Retry-After بعدد الثواني الباقية حتى يُتمّ أقدمُ طلب اختبار لك في آخر 24 ساعة يومًا كاملًا فيتّسع لطلب آخر. ويجوز عندئذٍ أن تعيد إرسال Idempotency-Key رُفض على هذا النحو.

الطلبات والردود

تتبع الواجهة أعراف REST وتستخدم الأشكال نفسها في كل مكان.

  • المتون بصيغة JSON وأسماء الحقول بنمط snake_case. الرد الناجح هو المورد نفسه، ورد الخطأ كائن error.
  • المبالغ أعداد صحيحة بأصغر وحدة: {"amount": 41990, "currency": "TRY"} تعني 419.90 ليرة. لا تُستخدم الكسور أبدًا فلا أخطاء تقريب. وعدد المنازل العشرية في currency_decimals ضمن GET /me.
  • التواريخ بتوقيت UTC وبصيغة ISO-8601: 2026-11-06T08:12:40Z.
  • تعيد القوائم object: "list" وdata وhas_more وnext_cursor. للصفحة التالية أرسل next_cursor في cursor؛ وقيمة limit من 1 إلى 200 (افتراضيًا 50).
  • لكل رد ترويسة X-Request-Id؛ أرفقها حين تراسل الدعم.
  • يُسمح لكل مفتاح بـ120 طلبًا في الدقيقة. المتبقي في X-RateLimit-Remaining، وما زاد يُردّ برمز 429 مع Retry-After. ولبعض الطلبات حدود خاصة بها: POST /webhook/test ثلاثون مرة في الساعة لكل مفتاح، وطلبات مفتاح الاختبار 500 في 24 ساعة (وكلاهما يُردّ برمز 429 rate_limited مع Retry-After).

أمان إعادة الإرسال (Idempotency)

استخدم ترويسة Idempotency-Key في طلبات POST لتعيد إرسال الطلب بأمان إذا انقطع الاتصال.

  • أنشئ قيمة فريدة (مثل UUID) لكل عملية جديدة. الطلب الثاني بالمفتاح نفسه لا ينشئ طلبًا جديدًا، بل يعيد الرد الأول كما هو مع ترويسة Idempotent-Replayed: true.
  • تُحفظ المفاتيح 24 ساعة. المفتاح نفسه بمتن مختلف يعيد 422 idempotency_key_reused، وما دام الطلب الأول جاريًا يعيد 409 request_in_progress.
  • حقل reference في الطلب فريد أيضًا: الطلب الثاني بالمرجع نفسه يعيد 409 duplicate_reference، ويذكر الخطأ في order_id الطلبَ الأول.
HTTP
Idempotency-Key: 4f9c1d2e-8a7b-4c3d-9e1f-2a3b4c5d6e7f

الأخطاء

تأتي الأخطاء برمز HTTP الصحيح وبرمز ثابت في code. ابنِ منطقك على code لا على نص الرسالة، ويشير param إلى الحقل المعني.

HTTP
HTTP/1.1 402 Payment Required
X-Request-Id: req_8c4f2a1e9b7d6c5a4b3e2f1d

{
  "error": {
    "type": "balance_error",
    "code": "insufficient_balance",
    "message": "Your balance in this currency does not cover the order.",
    "request_id": "req_8c4f2a1e9b7d6c5a4b3e2f1d"
  }
}
422 JSON
{
  "error": {
    "type": "order_error",
    "code": "field_invalid",
    "message": "\"playerId\" is missing or not valid for this product (see its type, min_length, max_length and options).",
    "param": "items[0].fields.playerId",
    "request_id": "req_0b1c2d3e4f5a6b7c8d9e0f1a"
  }
}
الرمزHTTPالمعنى وما يُفعل
invalid_api_key401المفتاح مفقود أو خاطئ أو موقوف أو غير مسموح به من عنوان IP هذا.
rate_limited429تجاوزت حد الطلبات: 120 طلبًا في الدقيقة لكل مفتاح، أو 30 تجربة إشعار في الساعة، أو 500 طلب في 24 ساعة بمفتاح الاختبار. وفي الحالات الثلاث تخبرك Retry-After بعدد الثواني التي تنتظرها.
route_not_found404لا توجد نقطة اتصال بهذا العنوان؛ راجع العنوان.
invalid_json400المتن ليس JSON صالحًا.
body_too_large413المتن أكبر من 256 كيلوبايت.
parameter_missing400معامل إلزامي مفقود (يذكره param).
parameter_invalid400قيمة أحد المعاملات غير صالحة (يذكره param).
field_unknown400أُرسل حقل لا يطلبه المنتج؛ راجع قائمة fields للمنتج.
field_invalid422حقل مفقود أو مخالف لقواعده (type وmin_length وmax_length وoptions).
product_not_found404المنتج غير موجود أو غير معروض لك للبيع.
product_unavailable409المنتج غير معروض للبيع الآن.
out_of_stock409المخزون لا يكفي لهذه الكمية.
quantity_out_of_range422الكمية خارج حدّي min_quantity وmax_quantity للمنتج.
outside_sale_hours422لا يُباع المنتج في هذه الساعة (sale_hours).
daily_limit_reached422بلغت حد الشراء اليومي لهذا المنتج.
spending_limit_reached422بلغت حد المبلغ أو الحد اليومي للدفع من الرصيد.
insufficient_balance402رصيدك لا يغطي الطلب؛ اشحن رصيدك.
account_restricted403لا يستطيع حسابك شراء هذا المنتج.
email_unverified403البريد الإلكتروني للحساب غير مؤكد.
billing_details_required422يلزم لهذا الطلب بيانات الفوترة (رقم الهوية أو الرقم الضريبي).
balance_payment_unavailable403الدفع من الرصيد بهذه العملة غير متاح لحسابك.
duplicate_reference409يوجد طلب بهذا المرجع من قبل (order_id).
idempotency_key_reused422استُخدم Idempotency-Key مع طلب مختلف.
request_in_progress409الطلب الأول بهذا Idempotency-Key ما زال جاريًا؛ أعد المحاولة بعد قليل.
order_not_found404الطلب غير موجود أو ليس لك.
item_not_found404لا يوجد هذا السطر في الطلب.
order_not_cancellable409لا يمكن إلغاء الطلب أو الأسطر المذكورة، وتبيّن الرسالة السبب: سطر مُسلَّم أو ملغى من قبل أو يُشترى له من مورّد؛ أو طلب مترابط الأسطر (قسيمة أو حزمة أو سعر «اشترِ معًا» أو هدية) أُريد إلغاء بعضه فقط أو فيه سطر مُسلَّم؛ أو طلب قيد مراجعة الدفع أو يتولاه فريقنا.
webhook_not_set409حدّد عنوان الإشعارات أولًا.
order_failed422تعذّر إنشاء الطلب؛ راسل الدعم مع request_id.
maintenance503المتجر في صيانة؛ أعد المحاولة بعد قليل.
service_unavailable503الخدمة لا تستجيب مؤقتًا؛ أعد المحاولة.
internal_error500حدث خطأ غير متوقع من جهتنا؛ راسل الدعم مع request_id. عند إعادة محاولة طلب أرسل Idempotency-Key نفسه.

دورة حياة الطلب

يتكون الطلب من أسطر، لكل سطر حالته، وحالة الطلب تُستخلص من أسطره.

حالات السطر

processing
التسليم جارٍ. تُسلَّم معظم منتجات الأكواد خلال ثوانٍ، وقد يستغرق الشحن بالمعرّف بضع دقائق.
delivered
مُسلَّم. الأكواد في codes، وdelivery_note هو ملاحظة التسليم (مثل رقم عملية الشحن بالمعرّف)، أو null. في بيئة الاختبار يحصل الشحن بالمعرّف على ملاحظة مثل TEST-TX-….
cancelled
ملغى، وعاد مبلغه إلى رصيدك (cancel_reason).

حالات الطلب

processing
سطر واحد على الأقل قيد المعالجة.
completed
سُلّمت كل الأسطر.
partially_completed
سُلّم بعض الأسطر وأُلغي الباقي.
cancelled
أُلغيت كل الأسطر.

حفاظًا على أمانك لا تظهر الأكواد إلا في رد GET /orders/{id} وفي الإشعارات؛ أما في ردَّي إنشاء الطلب والقائمة فتكون codes فارغة (null)، ويذكر codes_count عددها.

نقاط الاتصال

كل العناوين تحت عنوان API.

الحساب

بيانات الحساب

GET/v1/me

يعيد حسابك وأرصدتك وبيانات المفتاح المستخدم (بيئته وعناوين IP المسموحة وعنوان الإشعارات). وبمفتاح الاختبار يكون الرصيد هو الرصيد الوهمي لبيئة الاختبار (1000000 بعملة المفتاح).

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
الطلب
curl https://api.mas4games.com/v1/me \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY"
الرد
{
  "object": "account",
  "id": 18452,
  "name": "Örnek Bayi",
  "email": "[email protected]",
  "email_verified": true,
  "customer_type": "Bayi",
  "created_at": "2024-03-12T09:41:00Z",
  "currency": "TRY",
  "currency_decimals": 2,
  "balances": [
    { "amount": 1245075, "currency": "TRY", "decimals": 2 }
  ],
  "key": {
    "mode": "live",
    "created_at": "2026-11-06T08:00:00Z",
    "allowed_ips": ["203.0.113.10/32"],
    "webhook_url": "https://bayi.example.com/webhooks/mas4games"
  }
}

الأخطاء المحتملة:invalid_api_keyrate_limited

الكتالوج

قائمة التصنيفات

GET/v1/categories

يعيد التصنيفات المتاحة لك. ترتبط التصنيفات الفرعية بأصلها عبر parent_id.

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
الطلب
curl https://api.mas4games.com/v1/categories \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY"
الرد
{
  "object": "list",
  "data": [
    { "id": 3, "slug": "pubg-mobile", "name": "PUBG Mobile", "parent_id": null, "image_url": "https://www.mas4games.com/uploads/catalog/pubg.webp" },
    { "id": 5, "slug": "google-play", "name": "Google Play", "parent_id": null, "image_url": "https://www.mas4games.com/uploads/catalog/google-play.webp" }
  ],
  "has_more": false,
  "next_cursor": null
}

الأخطاء المحتملة:invalid_api_keyrate_limited

قائمة المنتجات

GET/v1/products

يعيد المنتجات المتاحة لك بأسعارك الخاصة مرتبة برقم المنتج. ومع updated_since تحصل فقط على ما تغيّر سعره أو مخزونه أو توفره (تُعالج التغييرات كل خمس دقائق).

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
limitاختياريالاستعلام · integerعدد السجلات في الصفحة، من 1 إلى 200 (افتراضيًا 50)
cursorاختياريالاستعلام · stringقيمة next_cursor من الرد السابق
category_idاختياريالاستعلام · integerمنتجات هذا التصنيف (وتصنيفاته الفرعية) فقط
idsاختياريالاستعلام · stringأرقام منتجات مفصولة بفواصل (200 على الأكثر)
updated_sinceاختياريالاستعلام · date-timeما تغيّر بعد هذا الوقت فقط (ISO-8601)
الطلب
curl https://api.mas4games.com/v1/products?limit=100 \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY"
الرد
{
  "object": "list",
  "data": [
    {
      "object": "product",
      "id": 241,
      "sku": "pubg-mobile-660-uc",
      "name": "PUBG Mobile 660 UC",
      "names": { "tr": "PUBG Mobile 660 UC", "en": "PUBG Mobile 660 UC", "ar": "PUBG Mobile 660 UC" },
      "category": { "id": 3, "name": "PUBG Mobile" },
      "type": "topup",
      "region": "global",
      "price": { "amount": 41990, "currency": "TRY" },
      "list_price": { "amount": 44990, "currency": "TRY" },
      "available": true,
      "stock": null,
      "min_quantity": 1,
      "max_quantity": 10,
      "sale_hours": null,
      "fields": [
        {
          "key": "playerId",
          "labels": { "tr": "Oyuncu ID", "en": "Player ID", "ar": "معرّف اللاعب" },
          "type": "digits",
          "required": true,
          "min_length": 5,
          "max_length": 64,
          "options": null
        }
      ],
      "image_url": "https://www.mas4games.com/uploads/catalog/pubg.webp",
      "description": null,
      "updated_at": "2026-11-06T07:55:00Z"
    }
  ],
  "has_more": true,
  "next_cursor": "MjQx"
}

الأخطاء المحتملة:invalid_api_keyrate_limitedparameter_invalid

تفاصيل منتج

GET/v1/products/{id}

يعيد منتجًا واحدًا. تحقّق من سعره وتوفره هنا قبل الطلبات ذات المبالغ الكبيرة.

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
idإلزاميالمسار · integerرقم المنتج
الطلب
curl https://api.mas4games.com/v1/products/241 \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY"
الرد
{
  "object": "product",
  "id": 241,
  "sku": "pubg-mobile-660-uc",
  "name": "PUBG Mobile 660 UC",
  "names": { "tr": "PUBG Mobile 660 UC", "en": "PUBG Mobile 660 UC", "ar": "PUBG Mobile 660 UC" },
  "category": { "id": 3, "name": "PUBG Mobile" },
  "type": "topup",
  "region": "global",
  "price": { "amount": 41990, "currency": "TRY" },
  "list_price": { "amount": 44990, "currency": "TRY" },
  "available": true,
  "stock": null,
  "min_quantity": 1,
  "max_quantity": 10,
  "sale_hours": null,
  "fields": [
    {
      "key": "playerId",
      "labels": { "tr": "Oyuncu ID", "en": "Player ID", "ar": "معرّف اللاعب" },
      "type": "digits",
      "required": true,
      "min_length": 5,
      "max_length": 64,
      "options": null
    }
  ],
  "image_url": "https://www.mas4games.com/uploads/catalog/pubg.webp",
  "description": null,
  "updated_at": "2026-11-06T07:55:00Z"
}

الأخطاء المحتملة:invalid_api_keyrate_limitedproduct_not_found

الطلبات

إنشاء طلب

POST/v1/orders

يدفع الطلب من رصيدك فورًا ويبدأ التسليم، ويعيد الطلب برمز 201. وإذا تعذّر طلب سطر لم يُنشأ أي طلب، ويذكر الخطأ السطر في param. ويضع مفتاح الاختبار 500 طلب اختبار على الأكثر في 24 ساعة (429 rate_limited مع Retry-After).

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
Idempotency-Keyاختياريترويسة · stringقيمة فريدة لهذه العملية (1–255 حرفًا)؛ والقيمة نفسها عند إعادة الإرسال
referenceاختياريالمتن · stringرقم طلبك الخاص؛ فريد لكل مفتاح (1–100 حرف)
itemsإلزاميالمتن · arrayأسطر الطلب (1–20)
items[].product_idإلزاميالمتن · integerرقم المنتج
items[].quantityاختياريالمتن · integerالكمية (افتراضيًا 1، ضمن min_quantity–max_quantity للمنتج)
items[].fieldsاختياريالمتن · objectقيم الحقول الواردة في قائمة fields للمنتج، بمفاتيحها
الطلب
curl -X POST https://api.mas4games.com/v1/orders \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1d2c8e-SIP-10045" \
  -d '{
  "reference": "SIP-10045",
  "items": [
    {
      "product_id": 241,
      "quantity": 1,
      "fields": { "playerId": "5123456789" }
    },
    {
      "product_id": 77,
      "quantity": 2
    }
  ]
}'
الرد
{
  "object": "order",
  "id": "M4G105146",
  "reference": "SIP-10045",
  "mode": "live",
  "source": "api",
  "status": "processing",
  "currency": "TRY",
  "total": { "amount": 61990, "currency": "TRY" },
  "refunded": { "amount": 0, "currency": "TRY" },
  "created_at": "2026-11-06T08:12:40Z",
  "items": [
    {
      "id": 5614,
      "product_id": 241,
      "product_name": "PUBG Mobile 660 UC",
      "quantity": 1,
      "unit_price": { "amount": 41990, "currency": "TRY" },
      "amount": { "amount": 41990, "currency": "TRY" },
      "gift": false,
      "status": "processing",
      "fields": { "playerId": "5123456789" },
      "codes": null,
      "codes_count": 0,
      "delivery_note": null,
      "delivered_at": null,
      "cancel_reason": null
    },
    {
      "id": 5615,
      "product_id": 77,
      "product_name": "Xbox 100 TL Hediye Kartı",
      "quantity": 2,
      "unit_price": { "amount": 10000, "currency": "TRY" },
      "amount": { "amount": 20000, "currency": "TRY" },
      "gift": false,
      "status": "delivered",
      "fields": {},
      "codes": null,
      "codes_count": 2,
      "delivery_note": null,
      "delivered_at": "2026-11-06T08:12:41Z",
      "cancel_reason": null
    }
  ]
}

الأخطاء المحتملة:invalid_api_keyrate_limitedinvalid_jsonparameter_missingparameter_invalidfield_unknownfield_invalidproduct_not_foundproduct_unavailableout_of_stockquantity_out_of_rangeoutside_sale_hoursdaily_limit_reachedspending_limit_reachedinsufficient_balanceaccount_restrictedemail_unverifiedbilling_details_requiredbalance_payment_unavailableduplicate_referenceidempotency_key_reusedrequest_in_progressorder_failedmaintenance

جلب طلب

GET/v1/orders/{id}

يعيد الطلب مع أكواد أسطره المسلَّمة. إن لم تستخدم الإشعارات فتابع التسليم بهذه النقطة.

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
idإلزاميالمسار · stringرقم الطلب (M4G…، وTST… في بيئة الاختبار)
الطلب
curl https://api.mas4games.com/v1/orders/M4G105146 \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY"
الرد
{
  "object": "order",
  "id": "M4G105146",
  "reference": "SIP-10045",
  "mode": "live",
  "source": "api",
  "status": "completed",
  "currency": "TRY",
  "total": { "amount": 61990, "currency": "TRY" },
  "refunded": { "amount": 0, "currency": "TRY" },
  "created_at": "2026-11-06T08:12:40Z",
  "items": [
    {
      "id": 5614,
      "product_id": 241,
      "product_name": "PUBG Mobile 660 UC",
      "quantity": 1,
      "unit_price": { "amount": 41990, "currency": "TRY" },
      "amount": { "amount": 41990, "currency": "TRY" },
      "gift": false,
      "status": "delivered",
      "fields": { "playerId": "5123456789" },
      "codes": [],
      "codes_count": 0,
      "delivery_note": "L8RZvemd2K2d39qfS7",
      "delivered_at": "2026-11-06T08:13:05Z",
      "cancel_reason": null
    },
    {
      "id": 5615,
      "product_id": 77,
      "product_name": "Xbox 100 TL Hediye Kartı",
      "quantity": 2,
      "unit_price": { "amount": 10000, "currency": "TRY" },
      "amount": { "amount": 20000, "currency": "TRY" },
      "gift": false,
      "status": "delivered",
      "fields": {},
      "codes": ["XB1A-7KQ2-PL9D-3M2X", "XB1A-8LR3-QM0E-4N3Y"],
      "codes_count": 2,
      "delivery_note": null,
      "delivered_at": "2026-11-06T08:12:41Z",
      "cancel_reason": null
    }
  ]
}

الأخطاء المحتملة:invalid_api_keyrate_limitedorder_not_found

قائمة الطلبات

GET/v1/orders

يعيد طلباتك من الأحدث إلى الأقدم (وتظهر طلباتك من الموقع أيضًا مع source: store). ولا تظهر الأكواد في القائمة.

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
limitاختياريالاستعلام · integerعدد السجلات في الصفحة، من 1 إلى 200 (افتراضيًا 50)
cursorاختياريالاستعلام · stringقيمة next_cursor من الرد السابق
statusاختياريالاستعلام · stringprocessing أو completed أو partially_completed أو cancelled
referenceاختياريالاستعلام · stringالطلب المرسل بهذا المرجع
created_afterاختياريالاستعلام · date-timeما أُنشئ في هذا الوقت أو بعده
created_beforeاختياريالاستعلام · date-timeما أُنشئ قبل هذا الوقت
الطلب
curl "https://api.mas4games.com/v1/orders?status=completed&created_after=2026-11-01T00:00:00Z&limit=50" \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY"
الرد
{
  "object": "list",
  "data": [
    { "object": "order", "id": "M4G105146", "reference": "SIP-10045", "status": "completed", "…": "…" }
  ],
  "has_more": false,
  "next_cursor": null
}

الأخطاء المحتملة:invalid_api_keyrate_limitedparameter_invalid

إلغاء طلب

POST/v1/orders/{id}/cancel

يلغي الأسطر التي لم تُسلَّم بعد ويعيد مبالغها إلى رصيدك فورًا. وإذا لم تُرسل items أُلغي كل سطر قابل للإلغاء. أما الطلب المترابط الأسطر (قسيمة على الطلب، أو منتج ضمن حزمة، أو سعر «اشترِ معًا»، أو سطر هدية أو السطر الذي استحقها) فيُلغى كله أو لا يُلغى: لا ترسل items (أو أرسل أسطره كلها)؛ فذِكر بعضها فقط، أو وجود سطر منها مُسلَّم أو يُشترى له من مورّد، يُردّ عليه برمز 409 order_not_cancellable مع رسالة تبيّن السبب. ولا تُلغى عبر الواجهة أبدًا الطلبات قيد مراجعة الدفع أو التي يتولاها فريقنا: راسل الدعم. وتبقى بقية الطلبات تُلغى سطرًا سطرًا. ولا يُلغى إلا ما دُفع من رصيدك (وطلبات الواجهة كلها كذلك).

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
Idempotency-Keyاختياريترويسة · stringقيمة فريدة لهذه العملية (1–255 حرفًا)؛ والقيمة نفسها عند إعادة الإرسال
idإلزاميالمسار · stringرقم الطلب (M4G…، وTST… في بيئة الاختبار)
itemsاختياريالمتن · arrayأرقام الأسطر المراد إلغاؤها؛ وبدونها كل سطر قابل للإلغاء (وفي الطلب المترابط الأسطر: كلها أو لا شيء). وتُرفض القائمة الفارغة بالخطأ parameter_invalid
reasonاختياريالمتن · stringسبب الإلغاء (200 حرف على الأكثر)
الطلب
curl -X POST https://api.mas4games.com/v1/orders/M4G105146/cancel \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cancel-M4G105146" \
  -d '{ "items": [5614], "reason": "Customer changed their mind" }'
الرد
{
  "object": "order",
  "id": "M4G105146",
  "status": "partially_completed",
  "refunded": { "amount": 41990, "currency": "TRY" },
  "items": [
    { "id": 5614, "status": "cancelled", "cancel_reason": "Customer changed their mind", "…": "…" },
    { "id": 5615, "status": "delivered", "…": "…" }
  ]
}

الأخطاء المحتملة:invalid_api_keyrate_limitedinvalid_jsonparameter_invalidorder_not_founditem_not_foundorder_not_cancellableidempotency_key_reusedrequest_in_progress

الرصيد

حركات الرصيد

GET/v1/balance/transactions

يعيد حركات رصيدك (المشتريات والمرتجعات والشحن) من الأحدث إلى الأقدم، للمطابقة. وبمفتاح الاختبار تكون القائمة فارغة دائمًا، فبيئة الاختبار لا تحرّك مالًا.

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
limitاختياريالاستعلام · integerعدد السجلات في الصفحة، من 1 إلى 200 (افتراضيًا 50)
cursorاختياريالاستعلام · stringقيمة next_cursor من الرد السابق
currencyاختياريالاستعلام · stringالعملة (افتراضيًا عملة مفتاحك)
الطلب
curl "https://api.mas4games.com/v1/balance/transactions?limit=20" \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY"
الرد
{
  "object": "list",
  "data": [
    {
      "object": "balance_transaction",
      "id": 90211,
      "type": "purchase",
      "amount": { "amount": -61990, "currency": "TRY" },
      "balance_after": { "amount": 1183085, "currency": "TRY" },
      "order_id": "M4G105146",
      "created_at": "2026-11-06T08:12:40Z"
    }
  ],
  "has_more": true,
  "next_cursor": "OTAyMTE"
}

الأخطاء المحتملة:invalid_api_keyrate_limitedparameter_invalid

عنوان الإشعارات

عرض عنوان الإشعارات

GET/v1/webhook

يعيد عنوان الإشعارات المحدد وآخر أحرف سرّ التوقيع.

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
الطلب
curl https://api.mas4games.com/v1/webhook \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY"
الرد
{
  "object": "webhook_endpoint",
  "url": "https://bayi.example.com/webhooks/mas4games",
  "secret_hint": "whsec_…Q3xZ",
  "events": ["order.item.delivered", "order.item.cancelled", "product.updated", "ping"]
}

الأخطاء المحتملة:invalid_api_keyrate_limited

تحديد عنوان الإشعارات

PUT/v1/webhook

يحدد عنوان https الذي تُرسل إليه الأحداث؛ والقيمة null توقف الإشعارات. ويبدأ الإرسال إلى العنوان الجديد فورًا، ولو كان القديم موقوفًا بسبب الإخفاقات.

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
urlإلزاميالمتن · stringعنوان https لا يتجاوز 300 حرف؛ والقيمة null توقف الإشعارات
الطلب
curl -X PUT https://api.mas4games.com/v1/webhook \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://bayi.example.com/webhooks/mas4games" }'

# then send a test event:
curl -X POST https://api.mas4games.com/v1/webhook/test -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY"
الرد
{
  "object": "webhook_endpoint",
  "url": "https://bayi.example.com/webhooks/mas4games",
  "secret_hint": "whsec_…Q3xZ",
  "events": ["order.item.delivered", "order.item.cancelled", "product.updated", "ping"]
}

الأخطاء المحتملة:invalid_api_keyrate_limitedinvalid_jsonparameter_invalid

إرسال حدث تجريبي

POST/v1/webhook/test

يرسل إلى عنوانك حدث ping موقّعًا ويخبرك بالنتيجة؛ استخدمه وأنت تبني المستقبِل. والتجربة الناجحة تستأنف فورًا الإرسال إلى عنوان أوقِف بسبب الإخفاقات. ويُسمح به 30 مرة في الساعة لكل مفتاح على الأكثر، وما زاد يُردّ برمز 429 rate_limited مع Retry-After.

المعاملات

الاسمالموضعالوصف
Authorizationإلزاميترويسة · stringكلمة Bearer ثم مفتاحك السري
الطلب
curl -X POST https://api.mas4games.com/v1/webhook/test \
  -H "Authorization: Bearer m4gc_live_YOUR_SECRET_KEY"
الرد
{
  "object": "webhook_test",
  "event_id": "evt_5d4c3b2a1f0e9d8c7b6a5f4e",
  "delivered": true,
  "response_status": 200,
  "error": null
}

الأخطاء المحتملة:invalid_api_keyrate_limitedwebhook_not_set

الإشعارات (Webhooks)

بدل الاستعلام المتكرر عن الطلبات انتظر الأحداث: عند تسليم سطر أو إلغائه وعند تغيّر منتجاتك نرسل إلى عنوانك طلب POST موقّعًا.

الأحداثالمعنى وما يُفعل
order.item.deliveredسُلّم سطر من الطلب؛ data.order هو الطلب كاملًا مع الأكواد، وdata.item_id هو السطر.
order.item.cancelledأُلغي سطر من الطلب وعاد مبلغه إلى رصيدك.
product.updatedالمنتجات التي تغيّر سعرها أو مخزونها أو توفرها (كل خمس دقائق، حتى 100 في المرة)؛ والمنتج المسحوب من البيع يأتي مع status: removed.
pingالحدث التجريبي المرسل عبر POST /webhook/test.
order.item.delivered
POST /webhooks/mas4games HTTP/1.1
Host: bayi.example.com
Content-Type: application/json
Mas4games-Signature: t=1793952765,v1=5f0b3c…e91a
Mas4games-Event-Id: evt_2c1a9f0e8b7d6c5a4b3e2f1d
Mas4games-Event-Type: order.item.delivered

{
  "id": "evt_2c1a9f0e8b7d6c5a4b3e2f1d",
  "object": "event",
  "type": "order.item.delivered",
  "mode": "live",
  "api_version": "v1",
  "created_at": "2026-11-06T08:12:45Z",
  "data": {
    "item_id": 5615,
    "order": {
      "object": "order",
      "id": "M4G105146",
      "reference": "SIP-10045",
      "status": "processing",
      "items": [
        { "id": 5615, "status": "delivered", "codes": ["XB1A-7KQ2-PL9D-3M2X", "XB1A-8LR3-QM0E-4N3Y"], "delivery_note": null, "…": "…" }
      ],
      "…": "…"
    }
  }
}
product.updated
{
  "id": "evt_9a8b7c6d5e4f3a2b1c0d9e8f",
  "object": "event",
  "type": "product.updated",
  "mode": "live",
  "api_version": "v1",
  "created_at": "2026-11-06T09:00:00Z",
  "data": {
    "products": [
      { "object": "product", "id": 241, "price": { "amount": 40990, "currency": "TRY" }, "available": true, "stock": null, "…": "…" },
      { "object": "product", "id": 312, "sku": "old-product", "available": false, "status": "removed" }
    ]
  }
}

التحقق من التوقيع

لكل طلب ترويسة Mas4games-Signature: t=1793952765,v1=5f0b3c…. وv1 هو HMAC-SHA256 بسرّك whsec_ للمتن الخام مسبوقًا بالوقت ونقطة (t.body).

  1. 1اقرأ المتن الخام قبل تحويله إلى JSON.
  2. 2استخرج t وv1 من الترويسة، واحسب HMAC-SHA256(السر، t + "." + المتن).
  3. 3قارن الناتج بـ v1 مقارنة ثابتة الزمن، وتحقق أن t لا يبعد عن الآن أكثر من 300 ثانية.
  4. 4إن لم يتطابق فأجب برمز 400 ولا تعالج الحدث.
import crypto from "node:crypto";
import express from "express";

const app = express();
// The signature is over the raw body: read it before any JSON parsing.
app.post("/webhooks/mas4games", express.raw({ type: "application/json" }), (req, res) => {
  const header = req.get("Mas4games-Signature") ?? "";
  const parts = Object.fromEntries(header.split(",").map((p) => p.trim().split("=")));
  const t = Number(parts.t);
  const expected = crypto.createHmac("sha256", process.env.MAS4GAMES_WEBHOOK_SECRET)
    .update(`${t}.${req.body.toString("utf8")}`).digest("hex");
  const ok = parts.v1 && parts.v1.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected)) &&
    Math.abs(Date.now() / 1000 - t) <= 300;
  if (!ok) return res.status(400).end();

  const event = JSON.parse(req.body.toString("utf8"));
  if (alreadyHandled(event.id)) return res.status(200).end(); // the same event can arrive twice
  queue(event); // handle it after answering
  res.status(200).end();
});

أكّد استلام الحدث برمز 2xx في غضون 8 ثوانٍ ثم أنجز العمل بعده: فالطلب الذي يستغرق أكثر من ذلك يُعدّ فاشلًا، ولا يُقرأ متن ردّك. وأي رد آخر يُعاد إرساله بعد 1 و5 و15 دقيقة، ثم كل ساعة وكل ست ساعات (12 مرة على الأكثر).

إذا أخفق عنوانك 3 مرات متتالية أُوقف الإرسال إليه 5 دقائق، وتتضاعف المدة مع كل إخفاق جديد حتى ساعة على الأكثر، وتنتظر أحداثك في أثناء ذلك. ويُستأنف الإرسال فورًا بتحديد عنوان جديد (PUT /webhook) أو بتجربة ناجحة عبر POST /webhook/test.

قد يصل الحدث نفسه أكثر من مرة، وقد تُبلَّغ أسطر الطلب سطرًا سطرًا على عدة دفعات (وطلبات الاختبار كذلك)؛ ويبقى معرّف الحدث هو نفسه في كل إرسال، فاحفظ المعرّفات وتجاهل التكرار. ولا يُضمن الترتيب؛ وللحالة الدقيقة استخدم GET /orders/{id}.

حدّد عنوانك بنفسك عبر PUT /webhook؛ ويُصدر سرّ التوقيع مع مفتاحك. وعند تجديد المفتاح يُحذف العنوان، فحدّده من جديد بالمفتاح الجديد.

ممارسات جيدة

  • أضف Idempotency-Key جديدًا إلى كل طلب POST، وعند انتهاء المهلة أعد الإرسال بالمفتاح نفسه.
  • أعطِ كل طلب مرجعك الخاص (reference)، فتعرف دائمًا هل أُنشئ الطلب أم لا.
  • استخدم الإشعارات، وتحقق مما فاتك عبر GET /orders/{id}.
  • اجلب الكتالوج كاملًا مرة واحدة، ثم حدّثه عبر updated_since أو product.updated.
  • جرّب المسار كله (بما فيه الأخطاء) بمفتاح الاختبار أولًا، ثم انتقل إلى التشغيل الحي.
  • احفظ المفتاح وسرّ الإشعارات على الخادم فقط، في متغيرات البيئة.

المساعدة

إذا تعثّرت في نقطة ما فراسل فريق الدعم؛ وإذا أرفقت قيمة X-Request-Id من الرد ورمز الخطأ ساعدناك أسرع.

ملاحظات الإصدار

  • 6 تشرين الثاني/نوفمبر 2026 (تحديث 2): أصبح delivery_note يحمل ملاحظة التسليم نفسها (مثل رقم عملية الشحن بالمعرّف؛ وTEST-TX-… في بيئة الاختبار)، أو null. وأُزيلت القيمة الثابتة topup_completed: يدل status: delivered مع codes_count: 0 على اكتمال الشحن بالمعرّف.
  • 6 تشرين الثاني/نوفمبر 2026 (تحديث): يعرض GET /me بمفتاح الاختبار رصيدًا تجريبيًا وتكون حركات رصيده فارغة؛ ويُلغى الطلب المترابط الأسطر كله أو لا يُلغى، ولا تُلغى عبر الواجهة الطلبات قيد المراجعة أو التي يتولاها فريقنا؛ وحدود برمز 429 مع Retry-After لطلبات الاختبار (500 في 24 ساعة) وتجارب الإشعارات (30 في الساعة)؛ وتنتهي مهلة طلبات الإشعارات بعد 8 ثوانٍ ويُوقف مؤقتًا العنوان الذي يتكرر إخفاقه؛ وتجديد المفتاح يحذف عنوان إشعاراته.
  • v1 (6 تشرين الثاني/نوفمبر 2026): الإصدار الأول. الحساب والكتالوج والطلبات والإلغاء وحركات الرصيد والإشعارات الموقّعة وIdempotency-Key وبيئة الاختبار.