كل ما يحتاجه المطوّر لسحب سجلات الحوالات، عرض الأرصدة، البحث برقم العملية، والتحقق بالمبلغ — مع شرح واضح لكل قيمة تُستبدل في الطلب.
في كل مثال ستجد قيماً بين أقواس أو بصيغة واضحة. استبدلها بقيمك الحقيقية قبل التشغيل:
من لوحة التحكم — Live يبدأ بـ sk_live_ أو Test بـ sk_test_.
الحساب المرتبط في لوحة التحكم (account_address). مثال: عنوان hex بطول 32 حرفاً.
رقم الحوالة الظاهر في تطبيق شام كاش (tran_id). هذا ما يضعه الزبون بعد الدفع.
المبلغ الذي يجب أن تطابقه الحوالة (مثل 5000). عند الاختلاف يرجع amount_match: false.
أرسل المفتاح بإحدى الطريقتين (الترويسة أفضل):
العنوان الأساسي: /api/v1
| الحد | القيمة |
|---|---|
| Live | 60 طلب / دقيقة |
| Sandbox | 30 طلب / دقيقة |
| صلاحيات | read:logs · verify:tx · write:transfers · فواتير اختيارية |
البوابة تدعم نمطين معاً — نفس النتيجة. استخدم REST للتكاملات الجديدة؛ الـ Query يبقى للتوافق:
| القديمة (Query) | الجديدة (REST) |
|---|---|
| GET /api/v1?resource=status | GET /api/v1/status |
| …resource=accounts&action=list | GET /api/v1/accounts |
| …action=logs | GET /api/v1/transactions?type=incoming&account_address=… |
| …action=outgoing_logs | GET /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=balances | GET /api/v1/balances?account_address=… أو GET /api/v1/accounts/{addr}/balances |
| — | POST /api/v1/transfers · /api/v1/invoices (REST أصلاً) |
بدائل الإجراء: outgoing_logs · all_logs
| في الطلب | يستبدل بـ | مثال |
|---|---|---|
| account_address | عنوان حسابك المرتبط | c89da6…43c0 |
| tx | رقم العملية من شام كاش | 12345678 |
| api_key / X-Api-Key | مفتاح الـ API | sk_live_… |
| Placeholder | المعنى |
|---|---|
| YOUR_ADDR | حساب الاستلام المرتبط |
| TRAN_ID | رقم العملية الذي أدخله الزبون |
| AMOUNT | المبلغ المطلوب تطابقه (مثل سعر الطلب) |
| YOUR_KEY | مفتاح API بصلاحية verify:tx |
استعلام واحد يرجع أرصدة المحفظة المرتبطة بالعملات الثلاث: SYP · USD · EUR.
| في الطلب | يستبدل بـ | مثال |
|---|---|---|
| account_address | عنوان حسابك المرتبط | c89da6…43c0 |
| api_key / X-Api-Key | مفتاح الـ API | sk_live_… |
أرسل حوالة من محفظة مرتبطة إلى عنوان شام كاش آخر. الصلاحية write:transfers اختيارية وغير مفعّلة افتراضياً — فعّلها من لوحة التحكم قبل الاستخدام.
تحذير: على مفتاح Live يتم خصم رصيد حقيقي من المحفظة المرتبطة. اختبر أولاً بمفتاح sk_test_.
{
"account_address": "YOUR_ADDR",
"address": "PEER_ADDR"
}
{
"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) إن لم تُرسله |
من لوحة التحكم يمكن تفعيل تأكيد التحويل بالإيميل لأي حساب شام كاش مرتبط. عند التفعيل: التحويل الحقيقي (Live) لا يُنفَّذ فوراً — تُرسل البوابة رمزاً من 6 أرقام إلى بريد صاحب الحساب، ولا يكتمل التحويل إلا بعد إدخال الرمز.
ملاحظة: Sandbox (sk_test_) يتجاوز التأكيد. التأكيد يطبَّق على Live فقط وللحسابات التي فعّلت الخيار.
نفس جسم التحويل العادي. الاستجابة تكون 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"
}
}
{
"challenge_id": "tch_…",
"code": "123456"
}
| الحقل | مطلوب؟ | المعنى |
|---|---|---|
| challenge_id | نعم | من استجابة 202 |
| code | نعم | رمز 6 أرقام من الإيميل (يُقبل أيضاً confirm_code) |
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);
}بمفتاح sk_test_ جرّب بدون شام كاش:
تذكير: Sandbox لا يلمس شام كاش الحقيقي. Live يخصم/يقرأ من المحفظة المرتبطة فعلياً.
فعّله من لوحة التحكم. التدفق الموصى به: البوت ينشئ فاتورة مع webhook_url → الزبون يدفع → بوابتنا تطابق الحوالة تلقائياً وترسل invoice.paid → البوت يسلّم بدون رقم عملية من الزبون.
مهم جداً: لا تستخدم نفس رابط الفواتير كـ webhook عام في لوحة «Webhooks». خصّص webhook_url لكل فاتورة (أو لمسار invoice في بوتك)، واترك الـ webhook العام لـ transaction.incoming فقط إن احتجته.
حوالة شام كاش الواردة لا تحمل اسم الزبون ولا رقم فاتورة — فقط: المحفظة + العملة + المبلغ + الوقت + tran_id. لذلك تطابق البوابة الفاتورة هكذا:
إذا وُجدت عدة فواتير معلّقة بنفس المبلغ على نفس المحفظة، تُربط الحوالة بـأقدم فاتورة مطابقة — وقد لا تكون فاتورة الزبون الصحيح.
| unique_amount | نفس المبلغ لعدة فواتير معلّقة؟ | المطابقة آمنة لكل زبون؟ |
|---|---|---|
| true (موصى به) | المبلغ يُعدَّل تلقائياً ليصبح فريداً | نعم — كل فاتورة لها مبلغها |
| false / غير مُرسل | نعم، نفس الرقم حرفياً | غير مضمون إن تزامنت عدة فواتير بنفس المبلغ |
أمان إضافي: اختيارياً من اللوحة «رفض الحوالات التي فيها ملاحظة» — يرفض فقط إذا خانة الملاحظة في تحويل شام كاش الوارد غير فارغة. حقل note عند إنشاء الفاتورة (ملاحظة البوت/الطلب) لا يمنع المطابقة. الهامش الزمني للمطابقة: دقيقتان قبل إنشاء الفاتورة.
إذا رجعت 403 FORBIDDEN_SCOPE: من لوحة التحكم فعّل نظام الفواتير ثم فعّل صلاحيات الفواتير على مفتاح الـ API.
{
"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).
الجسم يتضمن الفاتورة المدفوعة مع tran_id وmatch_reason والحوالة. عند انتهاء المدة تُرسل invoice.expired تلقائياً. إعادة المحاولة نفس سياسة الـ Webhooks العامة أدناه.
بمفتاح sk_test_:
| 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 فقط) |
حقول التقسيم داخل 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 فقط |
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 | أُلغيت |
من اللوحة فعّل الرابط. عند حوالة واردة جديدة نرسل transaction.incoming. أحداث الفواتير (invoice.paid / invoice.expired) تذهب إلى webhook_url الخاص بالفاتورة.
مهم: استخدم الجسم الخام (raw body) كما وصل — لا تعيد تنسيق JSON قبل حساب التوقيع. لا تربط رابط الفواتير كـ webhook عام لتجنّب خلط الأحداث. عالج Idempotency-Key / id عندك حتى لا تكرر التسليم عند إعادة المحاولة.
ارفض الطلب إذا انحرف الوقت أكثر من ~5 دقائق، أو إذا فشل مطابقة v1.
إذا كان سيرفرك متوقفاً أو رجع غير 2xx، تُعاد المحاولة تلقائياً من صندوق الصادر (outbox):
| البند | القيمة |
|---|---|
| أقصى محاولات | 8 (بعدها الحالة dead) |
| مهلة الطلب الواحد | 8 ثوانٍ (timeout) |
| نجاح | HTTP 200–299 فقط · بدون اتباع redirects |
| الفواصل بين المحاولات | 30ث → 60ث → 2د → 5د → 15د → 30د → 60د → 2س |
يرجع صندوق الصادر (outbox: pending / processing / delivered / dead) + آخر المحاولات + نسخة من سياسة الإعادة.
يعيد جدولة تسليم dead (أو pending) من الصفر. مفيد بعد إصلاح سيرفرك.
{
"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"
}
}
}{
"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" }
}
}
}| HTTP | code | المعنى |
|---|---|---|
| 401 | MISSING_API_KEY / INVALID_API_KEY | مفتاح ناقص أو خاطئ |
| 402 | SUBSCRIPTION_REQUIRED | اشتراك منتهي |
| 403 | FORBIDDEN_SCOPE | المفتاح بلا صلاحية المسار |
| 429 | RATE_LIMITED | تجاوز الحد |
| 409 | UNIQUE_AMOUNT_FAILED | تعذر توليد مبلغ فاتورة فريد |
| 409 | IDEMPOTENCY_KEY_CONFLICT | unique_key مستخدم لطلب تحويل مختلف |
| 502 | UPSTREAM_ERROR | خطأ من شام كاش |