SHAMGATE · API REFERENCE

الدليل الكامل للواجهة البرمجية

كل ما يحتاجه المطوّر لسحب سجلات الحوالات، عرض الأرصدة، البحث برقم العملية، والتحقق بالمبلغ — مع شرح واضح لكل قيمة تُستبدل في الطلب.

ما الذي يُستبدل في الطلب؟

في كل مثال ستجد قيماً بين أقواس أو بصيغة واضحة. استبدلها بقيمك الحقيقية قبل التشغيل:

YOUR_KEY
مفتاح الـ API

من لوحة التحكم — Live يبدأ بـ sk_live_ أو Test بـ sk_test_.

YOUR_ADDR
عنوان حساب شام كاش

الحساب المرتبط في لوحة التحكم (account_address). مثال: عنوان hex بطول 32 حرفاً.

TRAN_ID
رقم العملية

رقم الحوالة الظاهر في تطبيق شام كاش (tran_id). هذا ما يضعه الزبون بعد الدفع.

AMOUNT
المبلغ المتوقع

المبلغ الذي يجب أن تطابقه الحوالة (مثل 5000). عند الاختلاف يرجع amount_match: false.

القاعدة: أي نص داخل المثال بلون التمييز أو بصيغة YOUR_… / TRAN_ID / AMOUNT هو Placeholder — لا تتركه كما هو في الإنتاج.

المصادقة

أرسل المفتاح بإحدى الطريقتين (الترويسة أفضل):

X-Api-Key: YOUR_KEY
أو ?api_key=YOUR_KEY

العنوان الأساسي: /api/v1

الحدالقيمة
Live60 طلب / دقيقة
Sandbox30 طلب / دقيقة
صلاحياتread:logs · verify:tx · write:transfers · فواتير اختيارية

أسلوب المسارات (Query vs REST)

البوابة تدعم نمطين معاً — نفس النتيجة. استخدم REST للتكاملات الجديدة؛ الـ Query يبقى للتوافق:

القديمة (Query)الجديدة (REST)
GET /api/v1?resource=statusGET /api/v1/status
…resource=accounts&action=listGET /api/v1/accounts
…action=logsGET /api/v1/transactions?type=incoming&account_address=…
…action=outgoing_logsGET /api/v1/transactions?type=outgoing&account_address=…
…action=find_tx&tx=…GET /api/v1/transactions/{tx}?account_address=…
…action=verify_tx&amount=…GET /api/v1/transactions/{tx}?account_address=…&amount=…
…action=balancesGET /api/v1/balances?account_address=…
أو GET /api/v1/accounts/{addr}/balances
—POST /api/v1/transfers · /api/v1/invoices (REST أصلاً)
بديل مضمّن بالمحفظة: GET /api/v1/accounts/{accountAddress}/transactions و…/transactions/{txId}.

سحب سجل الحوالات بالكامل

GET /api/v1?resource=shamcash&action=logs&account_address=YOUR_ADDR

ما يُستبدل هنا

بدائل الإجراء: outgoing_logs · all_logs

الطلب · Request
الاستجابة · Response

البحث برقم العملية

GET /api/v1?resource=shamcash&action=find_tx&account_address=YOUR_ADDR&tx=TRAN_ID

ما يُستبدل في هذا الطلب

في الطلبيستبدل بـمثال
account_addressعنوان حسابك المرتبطc89da6…43c0
txرقم العملية من شام كاش12345678
api_key / X-Api-Keyمفتاح الـ APIsk_live_…
إذا وُجدت العملية: found: true + كائن transaction. إذا لم تُوجد: found: false.
الطلب · Request
الاستجابة · Response

التحقق برقم العملية + المبلغ

GET /api/v1?resource=shamcash&action=verify_tx&account_address=YOUR_ADDR&tx=TRAN_ID&amount=AMOUNT

ما يُستبدل هنا

Placeholderالمعنى
YOUR_ADDRحساب الاستلام المرتبط
TRAN_IDرقم العملية الذي أدخله الزبون
AMOUNTالمبلغ المطلوب تطابقه (مثل سعر الطلب)
YOUR_KEYمفتاح API بصلاحية verify:tx
عند التطابق: matched: true. عند اختلاف المبلغ: amount_match: false مع expected و actual. منع إعادة استخدام نفس العملية يترك لتطبيق التاجر.
الطلب · Request
الاستجابة · Response

عرض الرصيد الكامل · balances

استعلام واحد يرجع أرصدة المحفظة المرتبطة بالعملات الثلاث: SYP · USD · EUR.

GET /api/v1?resource=shamcash&action=balances&account_address=YOUR_ADDR

ما يُستبدل هنا

في الطلبيستبدل بـمثال
account_addressعنوان حسابك المرتبطc89da6…43c0
api_key / X-Api-Keyمفتاح الـ APIsk_live_…
صلاحية read:logs. الاستجابة دائماً تتضمّن الثلاث عملات — إن لم يكن للحساب رصيد بعملة ما تكون قيمتها 0. الحقل totals ملخّص سريع بنفس القيم.
الطلب · Request
الاستجابة · Response

التحويلات عبر شام كاش

أرسل حوالة من محفظة مرتبطة إلى عنوان شام كاش آخر. الصلاحية write:transfers اختيارية وغير مفعّلة افتراضياً — فعّلها من لوحة التحكم قبل الاستخدام.

تحذير: على مفتاح Live يتم خصم رصيد حقيقي من المحفظة المرتبطة. اختبر أولاً بمفتاح sk_test_.

التحقق من المستلم قبل التحويل

POST /api/v1/transfers/resolve
Header: X-Api-Key: YOUR_KEY
Content-Type: application/json
{
  "account_address": "YOUR_ADDR",
  "address": "PEER_ADDR"
}
الطلب · Request
الاستجابة · Response

تنفيذ التحويل + ملاحظة اختيارية

POST /api/v1/transfers
Header: X-Api-Key: YOUR_KEY
Content-Type: application/json
{
  "account_address": "YOUR_ADDR",
  "to": "PEER_ADDR",
  "amount": 1000,
  "currency": "SYP",
  "note": "طلب #99",
  "pin": "OPTIONAL_PIN",
  "unique_key": "OPTIONAL_UUID"
}
الحقلمطلوب؟المعنى
account_addressنعممحفظتك المرتبطة (المرسل)
toنعمعنوان المستلم في شام كاش
amountنعمالمبلغ (> 0)
currencyلاSYP (افتراضي) أو USD أو EUR
noteلاملاحظة اختيارية تظهر للمستلم في تطبيق شام كاش (مثل ملاحظة التحويل داخل التطبيق) — حتى 250 حرفاً. يُقبل أيضاً notes. اتركه فارغاً أو احذفه إن لم تحتاجه.
pinإن لزمPIN التحويل إن كان مفعّلاً على الحساب
unique_keyلامفتاح منع التكرار — يُولَّد تلقائياً (UUID) إن لم تُرسله
ملاحظة الحوالة · note: نفس الحقل الاختياري في شام كاش عند إرسال تحويل. تُمرَّر كما هي للمستلم وتُرجع في استجابة التحويل ضمن data.note.

منع التكرار · unique_key

الطلب · Request
الاستجابة · Response

تأكيد التحويل بالإيميل (اختياري)

من لوحة التحكم يمكن تفعيل تأكيد التحويل بالإيميل لأي حساب شام كاش مرتبط. عند التفعيل: التحويل الحقيقي (Live) لا يُنفَّذ فوراً — تُرسل البوابة رمزاً من 6 أرقام إلى بريد صاحب الحساب، ولا يكتمل التحويل إلا بعد إدخال الرمز.

ملاحظة: Sandbox (sk_test_) يتجاوز التأكيد. التأكيد يطبَّق على Live فقط وللحسابات التي فعّلت الخيار.

1) طلب التحويل — إن كان التأكيد مفعّلاً

POST /api/v1/transfers

نفس جسم التحويل العادي. الاستجابة تكون HTTP 202:

{
{
  "success": false,
  "code": "TRANSFER_CONFIRMATION_REQUIRED",
  "error": "يتطلب التحويل تأكيداً برمز أُرسل إلى بريدك",
  "data": {
    "challenge_id": "tch_…",
    "expires_in": 600,
    "email_hint": "no***@gmail.com",
    "account_address": "YOUR_ADDR",
    "to": "PEER_ADDR",
    "amount": 1000,
    "currency": "SYP",
    "next": "POST /api/v1/transfers/confirm مع challenge_id و code"
  }
}

2) تأكيد الرمز وتنفيذ التحويل

POST /api/v1/transfers/confirm
Header: X-Api-Key: YOUR_KEY
Content-Type: application/json
{
  "challenge_id": "tch_…",
  "code": "123456"
}
الحقلمطلوب؟المعنى
challenge_idنعممن استجابة 202
codeنعمرمز 6 أرقام من الإيميل (يُقبل أيضاً confirm_code)
الرمز صالح 10 دقائق · حد أقصى 5 محاولات خاطئة. بعد النجاح تُرجع نفس استجابة التحويل الناجح (201) مع tran_id.
مثال Node.js · تأكيد
const axios = require('axios');

// 1) طلب التحويل
const first = await axios.post('BASE/api/v1/transfers', {
  account_address: 'YOUR_ADDR',
  to: 'PEER_ADDR',
  amount: 1000,
  currency: 'SYP',
  note: 'طلب #99'
}, { headers: { 'X-Api-Key': 'YOUR_KEY' }, validateStatus: () => true });

if (first.status === 202 && first.data.code === 'TRANSFER_CONFIRMATION_REQUIRED') {
  const code = '123456'; // من الإيميل
  const { data } = await axios.post('BASE/api/v1/transfers/confirm', {
    challenge_id: first.data.data.challenge_id,
    code
  }, { headers: { 'X-Api-Key': 'YOUR_KEY' } });
  console.log(data);
}

Sandbox

بمفتاح sk_test_ جرّب بدون شام كاش:

تذكير: Sandbox لا يلمس شام كاش الحقيقي. Live يخصم/يقرأ من المحفظة المرتبطة فعلياً.

نظام الفواتير (اختياري)

فعّله من لوحة التحكم. التدفق الموصى به: البوت ينشئ فاتورة مع webhook_url → الزبون يدفع → بوابتنا تطابق الحوالة تلقائياً وترسل invoice.paid → البوت يسلّم بدون رقم عملية من الزبون.

مهم جداً: لا تستخدم نفس رابط الفواتير كـ webhook عام في لوحة «Webhooks». خصّص webhook_url لكل فاتورة (أو لمسار invoice في بوتك)، واترك الـ webhook العام لـ transaction.incoming فقط إن احتجته.

كيف تتم المطابقة؟ ولماذا المبلغ الفريد؟

حوالة شام كاش الواردة لا تحمل اسم الزبون ولا رقم فاتورة — فقط: المحفظة + العملة + المبلغ + الوقت + tran_id. لذلك تطابق البوابة الفاتورة هكذا:

إذا وُجدت عدة فواتير معلّقة بنفس المبلغ على نفس المحفظة، تُربط الحوالة بـأقدم فاتورة مطابقة — وقد لا تكون فاتورة الزبون الصحيح.

الحل الموصى به للبوتات: unique_amount: true
عند الإنشاء تخصّص البوابة مبلغاً فريداً بين الفواتير المعلّقة لنفس المستخدم والعملة:
  • الخطوة: 1 لـ SYP · 0.01 لـ USD/EUR
  • مثال: طلبت 1 USD وهناك فاتورة معلّقة بـ 1 → تصبح الجديدة 1.01 ثم 1.02…
  • حد أقصى ~500 محاولة؛ عند الفشل: 409 UNIQUE_AMOUNT_FAILED
  • الاستجابة تحتوي amount (المطلوب دفعه) وbase_amount (ما طلبته أصلاً)
اعرض للزبون دائماً data.amount وليس المبلغ الأصلي فقط.
unique_amountنفس المبلغ لعدة فواتير معلّقة؟المطابقة آمنة لكل زبون؟
true (موصى به)المبلغ يُعدَّل تلقائياً ليصبح فريداًنعم — كل فاتورة لها مبلغها
false / غير مُرسلنعم، نفس الرقم حرفياًغير مضمون إن تزامنت عدة فواتير بنفس المبلغ
أمان إضافي: اختيارياً من اللوحة «رفض الحوالات التي فيها ملاحظة» — يرفض فقط إذا خانة الملاحظة في تحويل شام كاش الوارد غير فارغة. حقل note عند إنشاء الفاتورة (ملاحظة البوت/الطلب) لا يمنع المطابقة. الهامش الزمني للمطابقة: دقيقتان قبل إنشاء الفاتورة.

الصلاحيات

إذا رجعت 403 FORBIDDEN_SCOPE: من لوحة التحكم فعّل نظام الفواتير ثم فعّل صلاحيات الفواتير على مفتاح الـ API.

1) إنشاء فاتورة

POST /api/v1/invoices
Header: X-Api-Key: YOUR_KEY
Content-Type: application/json
{
  "amount": 5000,
  "currency": "SYP",
  "account_address": "YOUR_ADDR",
  "webhook_url": "https://your-bot.com/hooks/invoice",
  "expires_in_minutes": 30,
  "unique_amount": true,
  "metadata": { "order_id": "ORD-99" },
  "note": "اشتراك شهري"
}

expires_in_minutes: بين 5 و 1440 (افتراضي 30).

الاستجابة · Response

2) إشعار الدفع

POST webhook_url
X-ShamCash-Event: invoice.paid
X-ShamCash-Signature: t=UNIX,v1=HMAC

الجسم يتضمن الفاتورة المدفوعة مع tran_id وmatch_reason والحوالة. عند انتهاء المدة تُرسل invoice.expired تلقائياً. إعادة المحاولة نفس سياسة الـ Webhooks العامة أدناه.

3) Sandbox للفواتير

بمفتاح sk_test_:

  1. أنشئ فاتورة: POST /api/v1/invoices
  2. حاكِ الدفع: POST /api/v1/invoices/{invoice_number}/simulate-pay
  3. يصلك invoice.paid على webhook_url

مسارات أخرى

Methodالمسارالوصف
GET/api/v1/invoicesقائمة (?status=&account_address=&page=&limit=)
GET/api/v1/invoices/{invoice_number}فاتورة واحدة
DELETE/api/v1/invoices/{invoice_number}إلغاء pending
POST/api/v1/invoices/{invoice_number}/simulate-payدفع تجريبي (Sandbox فقط)

قائمة الفواتير · التقسيم (Pagination)

GET /api/v1/invoices?status=pending&page=1&limit=20

حقول التقسيم داخل data، ونسخة احترافية أيضاً داخل meta.pagination:

{
{
  "success": true,
  "data": {
    "items": [ /* فواتير */ ],
    "total": 42,
    "page": 1,
    "pages": 3,
    "limit": 20
  },
  "meta": {
    "request_id": "req_…",
    "mode": "live",
    "pagination": {
      "page": 1,
      "pages": 3,
      "total": 42,
      "limit": 20
    }
  }
}
الحقلالمعنى
itemsمصفوفة الفواتير في الصفحة الحالية
totalإجمالي العناصر المطابقة للفلاتر
pageالصفحة الحالية
pagesعدد الصفحات الكلي
limitحجم الصفحة المستخدم
meta.paginationنفس أرقام التقسيم بشكل موحّد للمستهلكين الذين يقرأون meta فقط

مثال Node.js — إنشاء

const axios = require('axios');

const { data } = await axios.post('BASE/api/v1/invoices', {
  amount: 5000,
  currency: 'SYP',
  account_address: 'YOUR_ADDR',
  webhook_url: 'https://your-bot.com/hooks/invoice',
  unique_amount: true,
  metadata: { order_id: 'ORD-99' }
}, { headers: { 'X-Api-Key': 'YOUR_KEY' } });

console.log(data.data.invoice_number, data.data.amount, data.data.base_amount);
// أخبر الزبون يدفع المبلغ الظاهر في data.data.amount (قد يختلف عن base_amount)

حالات الفاتورة

statusالمعنى
pendingبانتظار الدفع
paidتم الدفع والمطابقة
expiredانتهت المدة (+ webhook invoice.expired)
cancelledأُلغيت

Webhooks

من اللوحة فعّل الرابط. عند حوالة واردة جديدة نرسل transaction.incoming. أحداث الفواتير (invoice.paid / invoice.expired) تذهب إلى webhook_url الخاص بالفاتورة.

X-ShamCash-Event: transaction.incoming
X-ShamGate-Event: transaction.incoming
X-ShamCash-Signature: t=UNIX,v1=HMAC_HEX
X-ShamGate-Signature: t=UNIX,v1=HMAC_HEX
Idempotency-Key: evt_…
Content-Type: application/json
مهم: استخدم الجسم الخام (raw body) كما وصل — لا تعيد تنسيق JSON قبل حساب التوقيع. لا تربط رابط الفواتير كـ webhook عام لتجنّب خلط الأحداث. عالج Idempotency-Key / id عندك حتى لا تكرر التسليم عند إعادة المحاولة.

معادلة التوقيع

v1 = HMAC_SHA256(secret, t + '.' + rawBody)
Header = t={unix},v1={hex}

ارفض الطلب إذا انحرف الوقت أكثر من ~5 دقائق، أو إذا فشل مطابقة v1.

إعادة المحاولة عند الفشل (Retry Policy)

إذا كان سيرفرك متوقفاً أو رجع غير 2xx، تُعاد المحاولة تلقائياً من صندوق الصادر (outbox):

البندالقيمة
أقصى محاولات8 (بعدها الحالة dead)
مهلة الطلب الواحد8 ثوانٍ (timeout)
نجاحHTTP 200–299 فقط · بدون اتباع redirects
الفواصل بين المحاولات30ث → 60ث → 2د → 5د → 15د → 30د → 60د → 2س
نفس السياسة تنطبق على transaction.incoming وأحداث الفواتير. ارجع 2xx بسرعة ثم عالج داخلياً؛ لا تعتمد على إعادة الطلب لإعادة المنطق الثقيل بدون idempotency.

مراقبة التسليم وإعادة الجدولة

GET /api/v1/webhooks/deliveries?limit=20&status=dead

يرجع صندوق الصادر (outbox: pending / processing / delivered / dead) + آخر المحاولات + نسخة من سياسة الإعادة.

POST /api/v1/webhooks/deliveries/{job_id}/retry

يعيد جدولة تسليم dead (أو pending) من الصفر. مفيد بعد إصلاح سيرفرك.

مثال جسم · transaction.incoming

{
  "id": "evt_…",
  "type": "transaction.incoming",
  "created_at": "2026-09-22T12:00:00.000Z",
  "mode": "live",
  "data": {
    "account_address": "YOUR_ADDR",
    "transaction": {
      "tran_id": "184627893",
      "amount": 5000,
      "currency": "SYP",
      "note": "",
      "type": "incoming"
    }
  }
}

مثال جسم · invoice.paid

{
  "id": "evt_…",
  "type": "invoice.paid",
  "created_at": "2026-09-22T12:01:00.000Z",
  "mode": "live",
  "data": {
    "invoice": {
      "invoice_number": "INV-…",
      "status": "paid",
      "amount": 1.01,
      "base_amount": 1,
      "currency": "USD",
      "tran_id": "184627893",
      "metadata": { "order_id": "ORD-99" }
    }
  }
}

التحقق عملياً — Node.js

التحقق عملياً — PHP

رموز الأخطاء

HTTPcodeالمعنى
401MISSING_API_KEY / INVALID_API_KEYمفتاح ناقص أو خاطئ
402SUBSCRIPTION_REQUIREDاشتراك منتهي
403FORBIDDEN_SCOPEالمفتاح بلا صلاحية المسار
429RATE_LIMITEDتجاوز الحد
409UNIQUE_AMOUNT_FAILEDتعذر توليد مبلغ فاتورة فريد
409IDEMPOTENCY_KEY_CONFLICTunique_key مستخدم لطلب تحويل مختلف
502UPSTREAM_ERRORخطأ من شام كاش
شكل خطأ عام
← رجوع إلى الصفحة الرئيسية