تخطي للذهاب إلى المحتوى

التوثيق — الإصدار v1

المصادقة

كل نداء يحمل أربع ترويسات (توقيع الإصدار ٢). التوقيع على خمسة أسطر يفصل بينها محرف سطرٍ جديد واحد (LF، \n): "v2\n{timestamp}\n{METHOD}\n{path?query}\n{raw_body}" بخوارزمية HMAC-SHA256 وسرّك: السطر الأوّل v2 حرفيًّا، والطريقة بحروف كبيرة، والمسار كما يُرسَل حرفيًّا (بترميز %XX) ومعه ? والاستعلام إن وُجد (بلا ? إن لم يوجد)، والجسم أخيرًا كما يُرسَل (فارغ لطلب GET، بلا سطرٍ بعده). ونافذة القبول ٣٠٠ ثانية — فاضبط ساعة خادمك، فهي أكثر أسباب فشل التوقيع.

X-Syriana-Key:               sy_live_xxxxxxxxxxxx
X-Syriana-Timestamp:         1756000000
X-Syriana-Signature-Version: 2
X-Syriana-Signature:         hex(hmac_sha256(secret,
    "v2\n1756000000\nGET\n/api/v1/products?page=2\n" + body))
  • التوقيع يُستعمل مرّة واحدة: إعادة إرسال الطلب الموقَّع نفسه تُرفض بـreplayed_request — حتى GET. طلبان متطابقان في الثانية نفسها يتطابق توقيعهما، فوقّع كلًّا بختمه أو غيّر الاستعلام. وطلب الكتابة بـIdempotency-Key لا يُستثنى: عند إعادة المحاولة وقّعه من جديد بختمٍ جديد وأبقِ المفتاح نفسه، فتأتيك الإجابة المحفوظة ولا يُنفَّذ مرّتين.
  • توقيع طلبٍ لا يصلح لمسارٍ آخر ولا لاستعلامٍ آخر ولا لطريقةٍ أخرى.
  • الإصدار ١ ("{timestamp}.{raw_body}" بلا ترويسة الإصدار) ما زال مقبولًا لكنّه متقادم: لا يغطّي المسار ولا الاستعلام، وقد يُفرض الإصدار ٢ على تطبيقك فيُرفض الأوّل بـsignature_v2_required. انتقل إليه الآن.
مثال كامل — أوّل نداء
KEY="sy_test_xxx"; SECRET="xxx"
METHOD="GET"; TARGET="/api/v1/products?page=1"   # path + ?query exactly as sent
BODY=''
TS=$(date +%s)
SIG=$(printf 'v2\n%s\n%s\n%s\n%s' "$TS" "$METHOD" "$TARGET" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -r | cut -d' ' -f1)

curl -s -X "$METHOD" "https://syriana.store$TARGET" \
  -H "X-Syriana-Key: $KEY" \
  -H "X-Syriana-Timestamp: $TS" \
  -H "X-Syriana-Signature-Version: 2" \
  -H "X-Syriana-Signature: $SIG"
الخطأ الأكثر تكراراً: توقيع نصّ ثمّ إرسال نصّ آخر. وقّع على البايتات نفسها التي ستُرسل — لا تُعِد تحويل الكائن إلى JSON بعد التوقيع، فترتيب المفاتيح أو ترميز الحروف العربية قد يختلف فيسقط التوقيع وأنت تراه صحيحاً. والأمر نفسه في المسار والاستعلام: ابنِ نصّ الاستعلام مرّة (ورمّز الحروف العربية في المسار بنفسك) وأرسل النصّ نفسه، لا قاموسًا تعيد مكتبتك ترميزه.

شكل الردّ

ثابت لا يتغيّر: النجاح دائماً data وmeta، والفشل دائماً error. الحقول تُضاف ولا تُحذف، فما تبنيه اليوم يبقى يعمل.

{"data": {...}, "meta": {"version": "v1", "page": 1, "total": 201}}
{"error": {"code": "missing_scope", "message": "..."}}

كيف تقبض على موقعك أنت

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

  1. اربط مزوّدك مرّة واحدة في مدفوعاتي — بدون حساب مزوّد فعّال يُرفض إنشاء أي رابط، لأننا لا نُحصّل نيابةً عنك.
  2. أنشئ تطبيقاً في تطبيقاتي، وامنحه payments:write وpayments:read، وحدّد وسائل الدفع المسموحة له إن أردت تضييقها.
  3. ناد POST /api/v1/payment_links عند كل طلب، وحوّل العميل إلى url في الردّ.
  4. سلّم عند وصول payment.paid إلى رابط الإشعارات، لا عند عودة العميل إلى موقعك — العميل قد يغلق الصفحة، والإشعار يصل على أي حال.
إنشاء رابط وتحويل العميل إليه
BODY='{"title":"اشتراك سنوي","amount":250,"currency":"SAR","mode":"once","methods":["stripe"],"reference":"ORDER-1042"}'
TS=$(date +%s)
SIG=$(printf 'v2\n%s\n%s\n%s\n%s' "$TS" POST /api/v1/payment_links "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -r | cut -d' ' -f1)

curl -s -X POST "https://syriana.store/api/v1/payment_links" \
  -H "X-Syriana-Key: $KEY" -H "X-Syriana-Timestamp: $TS" \
  -H "X-Syriana-Signature-Version: 2" -H "X-Syriana-Signature: $SIG" \
  -H "Content-Type: application/json" -d "$BODY"

أيّ الطرق تظهر لعميلك

الظاهر هو تقاطع ثلاث قوائم، والفارغ منها يعني «لا تضييق»: ما فعّلته في مدفوعاتي ∩ ما سمحت به لهذا التطبيق ∩ ما طلبته في methods. فإذا لم يظهر زرّ توقّعته، فالسبب إحدى الثلاث — ونقطة GET /api/v1/payment_links/{link_id} تُعيد methods فعلياً، فاقرأها بدل التخمين.

التحقّق من الإشعار

كل إشعار موقّع بسرّ الويب‑هوك الخاص بتطبيقك على "{timestamp}.{raw_body}" (الإشعار لا يحمل مسارًا يخصّك، فلا إصدار ثانيًا له). تحقّق من التوقيع قبل أن تُسلّم شيئاً، ولا تثق بجسم الطلب وحده — وتذكّر أن الإشعار قد يصل أكثر من مرّة، فاجعل تسليمك يحتمل التكرار.

تحقّق من توقيع الإشعار
# ليست عملية سطر أوامر: التحقّق يجري في خادمك.
# القاعدة واحدة في كل لغة —
#   expected = hmac_sha256(webhook_secret, timestamp + "." + raw_body)
# ثم قارنه بترويسة X-Syriana-Signature بمقارنة ثابتة الزمن.

جرّب قبل أن تبيع

مفتاحك التجريبي يُنشئ روابط تجريبية فقط — البيئة يقرّرها المفتاح لا جسم الطلب، فلا يمكن لخطأ في الإعداد أن يقبض مالاً حقيقياً وأنت تختبر.

فاتورة كاملة على صفحة الدفع

أرسل مع POST /api/v1/payment_links تفاصيل الفاتورة، فيراها عميلك قبل أن يدفع: بياناته، وبياناتك، والبنود، والضريبة، والاستحقاق. كلّها اختياريّة — وما لا ترسله لا يظهر.

الحقلما هو
customer{name, email, phone} — عميلك.
seller{name, email, phone, address, vat, cr} — أنت (الرقم الضريبيّ والسجلّ التجاريّ اختياريّان).
lines[{label, qty, total}] حتى ١٠٠ بند.
subtotal + taxمجموعهما يجب أن يساوي amount — وإلّا يُرفض الطلب، لأنّ فاتورةً لا تُجمع صحيحاً تُحرجك أمام عميلك.
invoiceNo · dueDateرقم فاتورتك وتاريخ استحقاقها (YYYY-MM-DD).
successUrlhttps فقط: يُعاد إليه عميلك بعد نجاح الدفع.

الصفحة بالعربية افتراضاً؛ أضف ?lang=en إلى الرابط لعميلٍ لا يقرأ العربية.

{
  "title": "اشتراك سنوي",
  "amount": 115, "currency": "USD", "reference": "ORD-1042",
  "customer": {"name": "سامي", "email": "sami@example.com"},
  "seller": {"name": "متجري", "vat": "300000000000003"},
  "lines": [{"label": "اشتراك سنوي", "qty": 1, "total": 100}],
  "subtotal": 100, "tax": 15,
  "invoiceNo": "INV-2026-0042", "dueDate": "2026-10-01",
  "successUrl": "https://mystore.com/thanks"
}

بعد أن يدفع عميلك

  1. يرى صفحة شكرٍ واضحة على صفحة الدفع نفسها، والفاتورة تتحوّل إلى «مدفوعة».
  2. إن أرسلت successUrl نعيده إليه بعد ٥ ثوانٍ، ومعه ?pay_link=…&reference=…&invoice=… لتعرف أيّ طلب.
  3. يصل خادمك payment.paid — وهذا وحده دليل الدفع. العودة إلى successUrl قد لا تحدث (يغلق العميل الصفحة)، وقد يزوّرها أيّ أحد بكتابة الرابط بيده. سلّم عند الإشعار، لا عند العودة.

الدفع بالمحافظ (شام كاش) يُتابَع آليّاً كل ٥ دقائق: ما يُدفع يُقيَّد ويصلك إشعاره حتى لو أغلق العميل الصفحة، وما تنتهي مهلته يُغلق وحده — لا شيء يبقى «بانتظار الدفع» إلى الأبد.

صفحة الدفع باسمك

  • شعارك ولونك وسطر أسفل الصفحة: من تبويب «صفحة الدفع» في صفحة تطبيقك، أو بنداء POST /api/v1/pay_page (صلاحيّة branding:write).
  • اسمك بدل اسمنا (العلامة البيضاء): صفحتك تقول «مدفوعات آمنة — اسم متجرك» بدل «عبر Syriana». تأتي مع باقتَي Store وEnterprise، وتعمل ما دامت الباقة فعّالة.
  • نطاقك مثل pay.yourstore.com: أضفه، ثمّ ضع عند مزوّد نطاقك سجلّ CNAME من الاسم إلى connect.sy-ft.net. على Cloudflare اجعله DNS only (السحابة رماديّة). نفحصه كل دقيقة ونُصدر شهادة HTTPS، ولا نقول «يعمل ✅» إلّا بعد أن نفتح صفحةً عليه فعلاً. بعدها كل روابطك تُفتح عليه، وعودة العميل من المزوّد تعود إليه.
POST /api/v1/pay_page          {"colour": "#0f766e", "footer": "خدمة العملاء 0999 000 000"}
POST /api/v1/pay_page/domains  {"host": "pay.mystore.com"}
GET  /api/v1/pay_page          → domains[0].state: waiting → active

الاسترجاع — يدويّ بقرار

لا نُخرج مالاً من حسابك بنداءٍ آليّ. إذا أردت إرجاع مبلغ لعميلك: أرجِعه أنت من حسابك لدى المزوّد (لوحة Stripe أو فواتيرك أو غيرها، أو بالتحويل في شام كاش)، ثمّ قيّده عندنا — من «مدفوعاتي» بزرّ «سجّل استرجاعاً»، أو من نظامك:

POST /api/v1/payments/{reference}/refund
{"alreadyDone": true, "amount": 20, "reason": "مقاس خاطئ"}

صلاحيّة payments:refund. بدون alreadyDone الردّ manual_only. كاملاً أو جزءاً؛ وIdempotency-Key يمنع تقييده مرّتين. يصلك payment.refunded عند الكامل وpayment.partially_refunded عند الجزئيّ.

رسومنا وأرقامك

المال يصل إلى حسابك أنت لدى مزوّدك كاملاً؛ رسومنا تُحسب على كل دفعة ناجحة (fee في الإشعار) وتُجمع شهريّاً: تُخصم من رصيد محفظتك إن كفى، وإلّا تصلك بها فاتورة. لا رسوم على ما استُرجع. GET /api/v1/payments/summary يعطيك في نداء واحد: كم بعت، كم أرجعت، كم رسوماً مستحقّة وكم دُفعت، وصافيك — لكل عملة على حدة.

نقاط النهاية

التحقّق

GET /api/v1/ping توقيع فقط
هل مفتاحي وتوقيعي صحيحان؟
أوّل نداء يجب أن تجرّبه. يعيد وقت الخادم — قارنه بوقتك، فاختلاف الساعة أكثر سبب لفشل التوقيع.
يعيد: {"ok": true, "time": "...", "sandbox": true}
GET /api/v1/me توقيع فقط
من أنا وما صلاحياتي
إن جاءك 403 من نقطة أخرى، فهذه تخبرك أي صلاحية ينقصك قبل أن تسأل الدعم.
يعيد: {"app": "...", "scopes": [...], "wallet": {...}}

الكتالوج

GET /api/v1/products catalog:read
المنتجات المنشورة بسعر التاجر
معاملات: page · page_size (حتى ٢٠٠) · search · audience (individual/business/enterprise/mixed) · category (رقم الفئة، يشمل الفروع) · currency (عملة عرض استرشادية).
يعيد: قائمة منتجات، كلٌّ برمز sku ثابت وصورة وفئاته وسعرك أنت. مع currency يُضاف كائن display — والسعر الأصلي يبقى هو المعتمد للخصم.
GET /api/v1/categories catalog:read
فئات المتجر مع عدد منتجات كلٍّ منها
الفئات كما يراها المتسوّق على متجرنا. العدد يشمل كل ما تحت الفئة من فروع. الفئات الفارغة لا تُعاد.
يعيد: [{"id": 5, "name": "...", "parent_id": 2, "product_count": 38}]
GET /api/v1/products/{sku} catalog:read
تفاصيل منتج واحد
يقبل SY-123 أو 123. يضيف الوصف والسمات وتاريخ آخر تعديل.
يعيد: كائن منتج مفصّل.
GET /api/v1/products/changes catalog:read
ما تغيّر فقط منذ وقت معيّن
المعامل since إلزامي بصيغة ISO. يشمل ما أُلغي نشره عمداً — يجب أن تعرف متى تتوقّف عن البيع، لا متى تبدأ فقط.
يعيد: قائمة منتجات مفصّلة مرتّبة بتاريخ التعديل.

المحفظة

GET /api/v1/wallet wallet:read
الرصيد والشروط
الحقل spendable هو ما تستطيع إنفاقه فعلاً الآن — لا تحسبه بنفسك من الرصيد والسقف.
يعيد: {"balance": .., "spendable": .., "mode": "prepaid"}
GET /api/v1/wallet/entries wallet:read
دفتر الحركات
كل شحن وخصم واسترداد بترتيب زمني عكسي. أساس أي مطابقة.
يعيد: قائمة حركات بالرصيد بعد كلٍّ منها.
GET /api/v1/wallet/topup-methods wallet:read
وسائل الشحن المتاحة لك
تختلف من تاجر لآخر. max_topup_now هو أكبر شحنة لن يرفضها سقف الرصيد.
يعيد: قائمة وسائل بحدودها.
POST /api/v1/wallet/topup wallet:write
افتح شحنة واحصل على رابط دفعها
الجسم: {"amount": 50, "provider": "fawaterk"}. الحدّ الأدنى ٥ دولار، والأقصى ما يبقى تحت سقف رصيدك. لا نستقبل أي بيانات بطاقة — تُدفع على صفحة المتجر نفسها.
يعيد: 201 مع pay_url — افتحه في المتصفّح لإتمام الدفع.
GET /api/v1/wallet/topups wallet:read
شحناتك وحالتها
شحنة بحالة draft لم تُدفع بعد؛ تُلغى تلقائياً بعد ٤٨ ساعة.
يعيد: قائمة شحنات.

الطلبات

POST /api/v1/customers/record orders:write
سجّل عميلك لديك (لا لدينا)
الجسم: {"external_ref", "name", "email", "phone", "source"}. العميل يُربط بك وحدك ويُعدّ طلباته. لا يدخل أي حملة تسويقية لنا، ولا يُخلط بعملائنا.
يعيد: 201 عند أول تسجيل، و200 مع عدّاد الطلبات بعدها.
POST /api/v1/notify/licence orders:write
أرسل المفتاح إلى عميلك بالواتساب أو البريد باسم متجرك
الجسم: {"customer_email", "codes": [...], "store_name", "product_name", "order_ref", "customer_name", "order_url", "reply_to", "customer_phone"}. أرسِل «customer_phone» ليصل المفتاح على واتساب من رقمك أنت — تُحاسبك ميتا مباشرة ولا نأخذ شيئاً من محفظتك. إن لم تكن ربطت رقمك أو رفضت ميتا القالب، يذهب المفتاح بالبريد ولا يضيع أبداً. اسم المرسل اسم متجرك، والعنوان عنواننا الموثّق — الإرسال من نطاقك يسقط في السبام. الردّ يذهب إلى «reply_to» إن أرسلتَه.
يعيد: 202 مع «channel» (whatsapp أو email) وعدد الأكواد. وعند السقوط إلى البريد يحمل «whatsapp_skipped» السبب.
POST /api/v1/orders orders:write
اشترِ تراخيص
ترويسة Idempotency-Key إلزامية. الجسم: {"items": [{"sku": "SY-123", "quantity": 2}], "reference": "رقمك", "customer": {"ref": "معرّفه لديك", "name": "...", "phone": "...", "email": "...", "source": "salla"}}. يُخصم الرصيد ثم تُصدر التراخيص في معاملة واحدة: إمّا الاثنان أو لا شيء. «customer.ref» إلزامي: بدونه لا يُعرف من يملك الترخيص، ولا يمكن تحذيرك من مشترٍ لاحقاً. البقيّة اختيارية لكن الهاتف هو ما تُبنى عليه إشارات المخاطر. ويُفحَص المشتري في شبكة الحماية تلقائياً مع كل طلب، وتُحفظ النتيجة على صفّه فتراها في «عملائي» وفي تبويب «عملاء هذا التطبيق» بلا استعلام إضافي يُحتسب عليك.
يعيد: 201 مع order_id والتراخيص، أو 402 لعدم كفاية الرصيد، أو 409 لتضارب مفتاح التكرار.
GET /api/v1/orders orders:read
طلباتك عبر الواجهة
مقسّمة صفحات، الأحدث أولاً.
يعيد: قائمة طلبات مختصرة.
GET /api/v1/orders/{order_id} orders:read
تفاصيل طلب
طلب لا يخصّك يعيد 404 لا 403 — حتى لا يصير الردّ نفسه وسيلة لاستكشاف طلبات غيرك.
يعيد: الطلب بأصنافه وتراخيصه.
GET /api/v1/orders/{order_id}/licenses licenses:read
مفاتيح طلب
ترخيص حالته pending لا مفتاح له بعد (منتج يُجهَّز يدوياً أو مخزون مفاتيح فارغ). يحمل عندئذٍ available_by (الموعد الأقصى) و availability_note (النصّ الذي نقوله لعملائنا أنفسنا) — اعرضهما لعميلك. ويصلك إشعار license.delivered لحظة توفّره. العدد المتبقّي في meta.pending.
يعيد: قائمة تراخيص بحالة كلٍّ منها.

التجّار

POST /api/v1/merchants/provision merchants:provision
أنشئ حساب تاجر تلقائياً عند تثبيت تطبيقك
لوحدات الوصل وحدها (سلة، ووردبريس). الجسم: {"external_ref": "رقم المتجر عندك", "name": "...", "email": "..."}. مُتكرِّر الاستدعاء بأمان: نفس external_ref يعيد نفس الحساب ولا يُنشئ ثانياً. الحساب المُنشأ للقراءة فقط؛ الشراء يحتاج محفظة ممولة وهوية موثّقة، والتوثيق يمنح الصلاحيات المالية تلقائياً.
يعيد: 201 مع key_id والسرّ (مرّة واحدة) و verify_url، أو 200 بلا سرّ إن كان الحساب موجوداً.

القنوات

POST /api/v1/channels/report merchants:provision
حالة متجر متصل عبر جسر
يرسله الجسر دورياً: حالة الربط · عملة المتجر ونسبته · عدد المنتجات المستورَدة · الطلبات الناجحة والفاشلة. الحقول المرسَلة وحدها تُحدَّث، فلا يمحو تقريرٌ ناقص عدّاداً.
يعيد: {"recorded": true}

روابط الدفع

POST /api/v1/payment_links payments:write
أنشئ رابط دفع باسمك ترسله لعميلك
تفاصيل الفاتورة (اختياريّة، تظهر لعميلك في صفحة الدفع): customer {name, email, phone} · seller {name, email, phone, address, vat, cr} · lines [{label, qty, total}] (حتى ١٠٠) · subtotal + tax (يجب أن يساويا amount) · dueDate (YYYY-MM-DD) · invoiceNo · successUrl (https: يُعاد إليه الدافع بعد نجاح الدفع ومعه pay_link وreference وinvoice — تحقّق من الدفع بالويب‑هوك لا بالعودة وحدها) · lang (ar أو en: لغة صفحة الدفع لعميلك، تسبق لغة متصفّحه). ثم: الجسم: title (اسم المنتج أو الخدمة) · amount · currency · mode (once/reusable) · methods (قائمة مزوّدين مسموحين، فارغة تعني كل ما فعّلته) · reference (مرجعك الداخلي). البيئة لا تُرسَل: المفتاح الذي وقّعت به هو الذي يقرّرها، فمفتاح تجريبي لا يستطيع إنشاء رابط يقبض مالاً حقيقياً. ويُرفض الإنشاء إن لم تكن قد ربطت حساباً لدى مزوّد — نحن لا نُحصّل إلى حسابنا نيابةً عنك. أرسل ترويسة Idempotency-Key (اختيارية) لتضمن أنّ إعادة المحاولة بعد انقطاع تُعيد الرابط نفسه لا رابطاً ثانياً. installments (اختياري): {count, interval_months, down_payment_pct, total_price} يضيف لصفحة الدفع زرّ «ادفع بالتقسيط» بشروطك.
يعيد: {"id": 12, "url": "https://…/pay/xyz", "state": "active", "methods": ["stripe", "paytabs"]}
GET /api/v1/payment_links payments:read
روابطك في هذه البيئة
معاملات: page · page_size · state (draft/active/used/disabled). لا تظهر روابط بيئة أخرى مهما كان.
يعيد: قائمة روابط بنفس شكل الإنشاء، مع paid_count.
GET /api/v1/payment_links/{link_id} payments:read
حالة رابط واحد ومدفوعاته
يضيف payments: كل نيّة دفع على الرابط بحالتها ومزوّدها ووقتها. رابط ليس لك يعيد not_found لا 403 — لئلّا يصير الردّ نفسه تأكيداً بأن الرقم موجود.
يعيد: {"id": 12, …, "payments": [{"state": "paid", …}]}
POST /api/v1/payment_links/{link_id}/disable payments:write
أوقف رابطاً
يمنع أي دفعة جديدة. الدفعات التي تمّت تبقى كما هي — الإيقاف ليس استرجاعاً.
يعيد: الرابط بحالته الجديدة disabled.

المدفوعات والاسترجاع

GET /api/v1/payments payments:read
كل دفعة وصلتك (أو حاولت) على روابطك
معاملات: page · page_size · state (pending/paid/failed/cancelled/refunded) · link_id. لكل دفعة: reference (مرجعنا — استعمله في الاسترجاع) · amount · currency · fee (رسومنا) · net (صافيك) · refunded · refundable · provider · linkId · linkReference (مرجعك الذي أرسلته عند الإنشاء) · invoiceNo · createdAt. المفتاح التجريبي يرى الدفعات التجريبية وحدها.
يعيد: [{"reference": "PAY-…", "state": "paid", "amount": 50, "fee": 0.5, "net": 49.5, "refundable": 50, …}]
GET /api/v1/payments/summary payments:read
أرقامك: مبيعات، استرجاع، رسوم، صافي
لكل عملة على حدة (لا نجمع دولاراً مع ليرة): sales/gross (كل الوقت) · salesThisMonth/grossThisMonth · refunds/refunded · feesDue (رسوم لم تُحصَّل بعد — تُخصم من محفظتك أوّل الشهر إن كفى رصيدها، وإلّا تصلك بها فاتورة) · feesSettled · net · pending. وwhiteLabel: هل صفحة الدفع تحمل اسمك (حسب باقتك).
يعيد: {"currencies": [{"currency": "USD", "gross": 1200, "net": 1188, …}], "whiteLabel": false}
GET /api/v1/payments/{reference} payments:read
دفعة واحدة بتفاصيلها
يضيف customer (من الفاتورة إن أرسلتها) · refunds (كل استرجاع بمبلغه وحالته وقناته: api عبر المزوّد أو manual سجّلته أنت) · attempts (كل محاولة دفع بمزوّدها ونتيجتها).
يعيد: {"reference": "PAY-…", …, "refunds": [...], "attempts": [...]}
POST /api/v1/payments/{reference}/refund payments:refund
سجّل استرجاعاً أرجعته لعميلك — كاملاً أو جزءاً منه
الاسترجاع عندنا يدويّ بقرار: أنت تُرجع المال لعميلك من حسابك لدى المزوّد (لا نُخرج مالاً من حسابك بنداء آليّ)، ثمّ تقيّده هنا لتبقى أرقامك وأرقامنا صحيحة. الجسم: alreadyDone: true (إلزاميّ — بدونه الردّ manual_only) · amount (اختياري — بدونه كل المتبقّي) · reason. أرسل Idempotency-Key: إعادة النداء بالمفتاح نفسه لا تقيّده مرّتين. الكامل يُطلق payment.refunded والجزئيّ payment.partially_refunded. لا رسوم علينا على المبلغ المُسترجَع.
يعيد: الدفعة بتفاصيلها بعد الاسترجاع (201).

صفحة الدفع باسمك

GET /api/v1/pay_page payments:read
كيف تبدو صفحة دفعك الآن
colour · footer · hasLogo · whiteLabel (اسمك بدل اسمنا — من باقتك Store/Enterprise، لا يُضبط بنداء) · dns (السجلّ المطلوب لربط نطاقك) · domains (كل نطاق بحالته: waiting بانتظار السجلّ، checking، active يعمل، failed ومعه السبب).
يعيد: {"colour": "#1f6feb", "whiteLabel": true, "dns": {"type": "CNAME", "target": "connect.sy-ft.net"}, "domains": [...]}
POST /api/v1/pay_page branding:write
شعارك ولونك على صفحة الدفع
الجسم (أيّها شئت): colour (#rrggbb) · footer (سطر حتى ١٢٠ حرفاً، مثل رقم خدمة العملاء) · logo (PNG/JPG/WebP بـbase64 حتى ٢ ميغا؛ null يحذفه). يظهر فوراً على كل روابطك.
يعيد: الصفحة بعد التعديل، بشكل GET /api/v1/pay_page.
POST /api/v1/pay_page/domains branding:write
اربط نطاقك (pay.yourstore.com)
الجسم: host. ثم أضف عند مزوّد نطاقك سجلّ CNAME من الاسم إلى dns.target (وعلى Cloudflare اجعله DNS only — السحابة رماديّة). نفحصه كل دقيقة، ونُصدر شهادة HTTPS، ولا يصير active إلّا بعد أن نفتح صفحةً عليه فعلاً. بعدها روابطك تُفتح عليه، والعودة من المزوّد تعود إليه. حتى ٥ نطاقات.
يعيد: الصفحة بعد الإضافة (201).
POST /api/v1/pay_page/domains/{domain_id}/check branding:write
افحص نطاقك الآن
يعيده إلى الطابور فيُفحص خلال دقيقة — بعد أن تعدّل سجلّ DNS مثلاً.
يعيد: الصفحة بحالة النطاق waiting.
POST /api/v1/pay_page/domains/{domain_id}/remove branding:write
أزل نطاقاً
روابطك تعود إلى نطاقنا فوراً. الروابط نفسها لا تتغيّر.
يعيد: الصفحة بعد الإزالة.

التقسيط

POST /api/v1/installments installments:write
اعرض على عميلك الشراء بالتقسيط — بلا فوائد ولا غرامات
الجسم: customer {ref, name, phone, email} (ref إلزامي، وجوّال أو بريد) · description · cash_price · total_price (اختياري، لا يقلّ عن cash_price ويحتاج أن تسمح شروطك) · down_payment · count (١–٢٤) · interval_months · first_due_date (YYYY-MM-DD) · reference (مرجعك). يُنشئ «عرضاً» ويعيد url: أرسله لعميلك ليوثّق هويّته ويقرأ العقد ويوقّع بنفسه — لا دين قبل توقيعه. تسري شروطك في /my/installments وحدود باقتك؛ الرفض installment_refused والسبب أوّل الرسالة. المفتاح التجريبي يُنشئ عقداً تجريبياً. Idempotency-Key اختيارية.
يعيد: {"id": 7, "reference": "IC-…", "url": "https://…/installment/…", "state": "offered", "schedule": […]}
GET /api/v1/installments installments:read
عقودك في هذه البيئة
معاملات: page · page_size · state (offered/active/completed/cancelled/expired). لا هويّة ولا مستند في أي ردّ.
يعيد: قائمة عقود مع amount_paid و amount_left و days_late.
GET /api/v1/installments/{contract_id} installments:read
عقد واحد بجدول أقساطه
يضيف schedule: كل قسط بموعده ومبلغه وحالته و pay_url لرابط دفعه، و references_confirmed و guarantor_signed.
يعيد: {"id": 7, …, "schedule": [{"due_date": "2026-10-10", "amount": 300.0, "state": "open", "pay_url": "…"}]}
POST /api/v1/installments/{contract_id}/cancel installments:write
ألغِ عرضاً لم يُوقَّع
عقد موقَّع لا يُلغى ولا تُعدَّل مبالغه — العميل وافق على هذه الأرقام بعينها.
يعيد: العقد بحالته cancelled.

حساب المزوّد

GET /api/v1/pay_accounts/providers payments:read
قائمة المزوّدين وحقول كلٍّ منهم — ورسومنا عليك
نفس القائمة التي يستعملها نموذج /my/payments بالحرف — فنموذجك ونموذجنا يطلبان نفس الحقول دائماً، لا يفترقان. و fee: رسومنا الفعليّة عليك من القاعدة الحيّة (نسبة + ثابت، ومثالٌ على ١٠٠) — اعرضها لتاجرك قبل أن يربط شيئًا.
يعيد: {"providers": [{"code": "stripe", "label": "Stripe"}, …], "fields": {"stripe": {"public": "Publishable key", …}}}
GET /api/v1/pay_accounts payments:read
حساباتك لدى مزوّدي الدفع
لا يعيد أيّ سرٍّ أبداً — hasSecret/hasWebhookSecret بوليانيّتان فقط، لأنّ السرّ يُكتَب ولا يُقرأ مطلقاً.
يعيد: قائمة حسابات؛ id · providerCode · env · state · publicKey · hasSecret · webhookUrl.
POST /api/v1/pay_accounts payments:write
اربط حسابك لدى مزوّد دفع (أو حدّثه)
الجسم: providerCode · publicKey · secretKey · webhookSecret · providerMethodId · holderName (للمحافظ كشام كاش: الاسم كما يظهر في تطبيقه) · activate (بوليان، يفعّل الحساب مباشرةً). البيئة لا تُرسَل: كما في /payment_links، المفتاح الذي وقّعت به هو من يقرّرها — مفتاح تجريبي لا يستطيع إنشاء حساب حيّ. وحساب حيّ يُرفض قبل توثيق هويّتك (kyc_required) — تماماً كنموذج الموقع. secretKey فارغ عند التحديث يعني «بلا تغيير» لا محواً: لا نعيد السرّ المخزَّن أبداً فلا نافذة تعرضه لك لتعدّلها.
يعيد: الحساب بحالته — بلا أي سرّ.
POST /api/v1/pay_accounts/{account_id}/qr payments:write
ارفع صورة QR المحفظة (شام كاش)
الجسم: image — base64 أو data URI لصورة PNG/JPEG/WebP حتى ٢ ميغا (حدّ الجسم هنا ٣ ميغا). الدافع يمسحها بدل كتابة عنوان المحفظة بيده، والحساب لا يتفعّل بدونها. للمزوّدين الذين يستعملونها فقط (fields[code].qr في /pay_accounts/providers).
يعيد: الحساب بحالته، وفيه hasQr.
POST /api/v1/pay_accounts/{account_id}/activate payments:write
فعّل حساباً محفوظاً بلا تعديل بياناته
يحتاج مفتاحاً عاماً وسرّاً محفوظَين مسبقاً. env=live يُرفض قبل توثيق الهويّة.
يعيد: الحساب بحالته الجديدة.
GET /api/v1/pay_domains platform:domains
نطاقات صفحات الدفع وحالتها (للمنصّة المشغِّلة)
كل نطاقٍ أضافه تاجر من تبويب «صفحة الدفع»: waiting ينتظر سجلّ DNS، checking قيد الفحص، active يعمل، failed تعذّر. صلاحيّةٌ تُمنح لمنصّتنا وحدها.
يعيد: قائمة {id, host, state, message, checkedAt}.
POST /api/v1/pay_domains/{domain_id}/result platform:domains
اكتب نتيجة فحص نطاق
الجسم: state (waiting | checking | active | failed) · message. active فقط يجعل الدافع يعود إلى هذا النطاق بعد الدفع.
يعيد: {id, host, state}.
POST /api/v1/merchants/branding merchants:provision
هويّة صفحة الدفع لتاجرٍ زوّدتَه
الجسم: external_ref · channel · colour (#rrggbb) · footer · logo (base64 PNG/JPEG/WebP حتى ٢ ميغا، فارغ = امسح) · whiteLabel (بوليان: بلا «مدفوعات آمنة عبر Syriana») · domains (حتى ١٠ نطاقات تُخدَم عليها الصفحة وتعود إليها بعد الدفع). ما لا يُذكر لا يتغيّر. للمنصّة لا للتاجر: العلامة البيضاء قرار الباقة.
يعيد: colour · whiteLabel · hasLogo · domains.
POST /api/v1/merchants/payments merchants:provision
امنح تاجراً زوّدتَه صلاحيّات الدفع
للموصِّلات وحدها. الجسم: external_ref · channel — نفس ما أرسلته عند التزويد. يمنح الحساب الفرعيّ payments:read وpayments:write، ولا ينجح إلّا إن كان تطبيقك نفسه يملكهما: لا يمنح أحدٌ ما لم يُمنَح. آمنٌ للتكرار. والحساب الحيّ يبقى مرفوضاً قبل توثيق هويّة التاجر.
يعيد: {"scopes": [...], "granted": ["payments:read", …]}

توثيق الهويّة

GET /api/v1/kyc توقيع فقط
حالة توثيقك ونموذجه ونتيجة الفحص
يعيد الحالة، والمستندات المرفوعة (بلا محتواها)، وآخر فحص آليّ بندًا بندًا مع نصيحةٍ لكل بندٍ لم يتطابق — ومعها مواصفة النموذج: حقول الفرد، وحقول الشركة، والمستندات المطلوبة لكلٍّ منهما. ارسم نموذجك منها لا من افتراضك.
يعيد: {"state": "submitted", "check": {"lines": [...]}, "form": {...}}
POST /api/v1/kyc/documents توقيع فقط
ارفع مستندًا واحدًا
الجسم: kind · filename · data (Base64) · idType. صور فقط (JPG/PNG/WebP) حتى ٤ ميغابايت — ملفّ PDF يُرفض لأنّ القارئ الآليّ لا يقرؤه. الحدّ الأكبر لهذه النقطة وحدها.
يعيد: الحالة كما في GET /kyc.
POST /api/v1/kyc توقيع فقط
قدّم التوثيق وشغّل الفحص الآليّ
الجسم: subject (individual/company) وحقول هذا النوع وحده. يشترط رفع المستندات المطلوبة أوّلًا. الفحص يقرأ ويقارن، والاعتماد لمراجعٍ بشريّ ما لم يُفعَّل الاعتماد التلقائيّ.
يعيد: الحالة ونتيجة الفحص.
GET /api/v1/merchants/kyc merchants:kyc
طلبات توثيق التجّار الذين زوّدتهم
تجّار قناتك وحدها (channel اختياريّ؛ غير قناتك ٤٠٣). المنتظر أوّلًا. لكلٍّ: البيانات والمستندات (بلا محتواها) ونتيجة الفحص الآليّ بندًا بندًا.
يعيد: [{"ref": "6", "merchant": "…", "waiting": true, "check": {...}}]
GET /api/v1/merchants/kyc/{ref}/documents/{kind} merchants:kyc
صورة مستندٍ لتاجرٍ زوّدته — للمراجعة
لتاجرٍ من قناتك وحدها. تُحفظ الصور مدّة المراجعة فقط ثم تُحذف.
يعيد: {"mime": "image/jpeg", "data": "<base64>"}
POST /api/v1/merchants/kyc/{ref}/decide merchants:kyc
اعتمد توثيق تاجر أو ارفضه
الجسم: channel · decision (approve/reject) · note. الرفض يشترط ملاحظة تقول للتاجر ماذا يصلح. رفض ترقيةٍ إلى شركة لا يُسقط توثيقه كفرد.
يعيد: الحالة بعد القرار.
POST /api/v1/merchants/kyc/{ref}/reset merchants:kyc
نُقلت ملكيّة التاجر — المالك الجديد يوثّق نفسه
الجسم: channel. يعيد التوثيق إلى «مطلوب»، ويحذف صور الهويّة الشخصيّة للمالك السابق (تبقى بصمتها)، ويوقف حسابات الدفع الحيّة حتى يوثّق الجديد ويعيد تفعيلها. مستندات الشركة تبقى.
يعيد: {"state": "requested", "purgedDocuments": 3, "pausedAccounts": 1}

السوق

GET /api/v1/market/listings market:read
ما يعرضه السوق داخل تطبيقاتنا
?platform=salla — المنشور وحده، بطاقة لكل منتج: الاسم والوصف بالإنجليزية وكل لغةٍ مفعّلة مترجمة، وطريقة البيع والسعر والصلاحيات في تلك المنصّة، والباقات التي تشمله.
يعيد: {"ok": true, "listings": [{"key": "setup-service", "kind": "service", "vendor": "syriana", "platforms": {"salla": {"sell": "addon", "addon": "setup", "price": {"kind": "one_time", "amount": 199, "currency": "SAR"}}}}]}

شبكة الحماية

POST /api/v1/risk/check risk:read
هل على هذا المشتري بلاغات؟
الجسم: {"phone": "05…"} أو {"email": "…"} — لمن تملك بياناته أصلاً. يعيد إشاراتٍ لا أحكاماً: كم تاجراً مختلفاً أبلغ، وعن ماذا، ومتى آخر مرّة — ومعها الجانب الإيجابي: مشتريات مكتملة بلا شكوى. لا يعيد اسماً ولا رقماً ولا هويّة أحد، ولا يمكن استعماله لاكتشاف مشترٍ لم تكن تعرفه: المعرّفات محفوظة كبصمات HMAC لا كنصّ. والحكم استشاري — نحن لا نرفض بيعك.
يعيد: {"verdict": "allow|warn|block", "action": "allow|verify|block", "buyer_message": "…", "reporting_merchants": 2, "signals": [...], "clean_orders": 5, "vouches": 1, "identity_verified": false, "advice": "…"} «action» هو ما قرّرتَه أنت في سياستك، و«buyer_message» نصّك أنت الذي يراه مشتريك عند المنع — اعرضه كما هو.
POST /api/v1/risk/report risk:write
أبلغ عن واقعة حدثت لك
الجسم: {"phone" أو "email", "kind": "chargeback|refused_delivery|fake_payment|abuse|other", "evidence": "ما حدث بالتفصيل", "amount": 250}. الدليل إلزامي (٢٠ حرفاً على الأقل) — بلاغ بلا وصف يضرّ بريئاً ولا يحمي أحداً. بلاغك ينتهي بعد سنة، ويمكنك سحبه، ولا يُحتسب لك أكثر من بلاغ واحد من كل نوع على الشخص نفسه. **لا يُبلَّغ إلّا عمّن اشترى منك فعلاً**: يجب أن يكون مسجَّلاً لديك عبر /customers/record أو طلبٍ عبر /orders، وإلّا رُدّ بـ403. هذا ما يمنع أن تصير الشبكة سلاحاً.
يعيد: 201 مع رقم البلاغ وتاريخ انتهائه، أو 409 إن سبق أن أبلغت.
POST /api/v1/risk/vouch risk:write
اشهد أنّ التعامل معه كان سليماً
الجسم: {"phone" أو "email", "note": "اختياري"}. هذا هو باب الخروج من العلامة الحمراء: ثلاثة تجّار باعوا له بعدها ولم يجدوا مشكلة يرجّحون كفّته. ويشترط ما يشترطه البلاغ: أن تكون بعتَ له فعلاً.
يعيد: 201، أو 403 إن لم تكن بينكما معاملة، أو 409 إن سبق أن شهدت.
POST /api/v1/risk/verify risk:write
اطلب من مشترٍ توثيق هويّته
الجسم: {"phone" أو "email"}. يعيد رابطاً ترسله للمشتري. يرفع مستنداته **إلينا لا إليك**، ويصلك بالويب‑هوك «verification.verified» أو «verification.refused» — النتيجة وحدها بلا اسم ولا رقم ولا ملفّ. متجر يجمع صور الهويّات يتحمّل مسؤوليةً لا يستطيع حمايتها، ويُسأل عنها عند أوّل تسريب. الرابط ينتهي خلال ٧٢ ساعة، ولا يُطلب التوثيق إلّا ممّن اشترى منك.
يعيد: 201 مع url وexpires_at، أو already_verified إن كان موثّقاً، أو 403 إن لم تكن بينكما معاملة.

تشات كونكت

POST /api/v1/chat/provision chat:connect
افتح حساب المحادثات لمتجر ثبّت التطبيق
{"external_ref": "رقم المتجر على منصّتك", "store_name", "email", "owner_name", "store_url"}
يعيد: {"ok": true, …} — أو 422 مع «error» حين يرفض الطلب.
POST /api/v1/chat/event chat:connect
حدث اشتراك من المنصّة (تجديد، إلغاء، تغيير باقة)
{"external_ref": "رقم المتجر على منصّتك", "event", "plan_name", "end_date"}
يعيد: {"ok": true, …} — أو 422 مع «error» حين يرفض الطلب.
POST /api/v1/chat/login chat:connect
رابط دخول لمرّة واحدة إلى صندوق المحادثات
{"external_ref": "رقم المتجر على منصّتك"}
يعيد: {"ok": true, …} — أو 422 مع «error» حين يرفض الطلب.
POST /api/v1/chat/send_login chat:connect
أرسل رابط الدخول إلى بريد التاجر
{"external_ref": "رقم المتجر على منصّتك", "email"}
يعيد: {"ok": true, …} — أو 422 مع «error» حين يرفض الطلب.
POST /api/v1/chat/status chat:connect
حالة الحساب والباقة والاستهلاك
{"external_ref": "رقم المتجر على منصّتك"}
يعيد: {"ok": true, …} — أو 422 مع «error» حين يرفض الطلب.
POST /api/v1/chat/rename chat:connect
غيّر اسم الحساب
{"external_ref": "رقم المتجر على منصّتك", "name"}
يعيد: {"ok": true, …} — أو 422 مع «error» حين يرفض الطلب.
POST /api/v1/chat/addon chat:connect
إضافة اشتُريت أو جُدّدت أو أُلغيت
{"external_ref": "رقم المتجر على منصّتك", "event", "slug", "quantity", "subscription_id"}
يعيد: {"ok": true, …} — أو 422 مع «error» حين يرفض الطلب.
POST /api/v1/chat/addons_due chat:connect
الإضافات المستحقّة التجديد
{}
يعيد: {"ok": true, …} — أو 422 مع «error» حين يرفض الطلب.
POST /api/v1/chat/addon_renew_failed chat:connect
تعذّر تجديد إضافة
{"external_ref": "رقم المتجر على منصّتك", "subscription_id", "reason"}
يعيد: {"ok": true, …} — أو 422 مع «error» حين يرفض الطلب.
POST /api/v1/chat/help_request chat:connect
اطلب من فريقنا ضبط التطبيق معك
{"external_ref": "رقم المتجر على منصّتك", "phone", "source"}
يعيد: {"ok": true, …} — أو 422 مع «error» حين يرفض الطلب.

التفعيل بالهاتف

POST /api/v1/activation/cid activation:cid
رمز التأكيد (CID) من أرقام IID
أرسل {"iid": "9 مجموعات أرقام"} كما تظهر في شاشة التفعيل بالهاتف لـ Windows أو Office. يُخصم سعر الخدمة من محفظتك عند النجاح فقط؛ الأرقام غير الصالحة لا تُخصم. إن كانت الخدمة متوقفة مؤقتاً يعود ok=false وerror=waiting ولا يُخصم شيء.
يعيد: {"ok": true, "cid": "111111 222222 ... 888888", "charged": 0.25, "request_id": 42}

الدومينات

GET /api/v1/domains/check domains:read
توفّر الدومين وسعره
name=mystore وtlds=com,net (اختياري) وyears=1. السعر بالدولار = تكلفة المورّد + رسوم الخدمة.
يعيد: {"ok": true, "currency": "USD", "results": [{"domain": "mystore.com", "available": true, "price": 16.12}]}
POST /api/v1/domains domains:write
تسجيل دومين من المحفظة
{"domain": "mystore.com", "years": 1} — يُسجَّل باسم صاحب الحساب مع حماية الخصوصية، ويُخصم من المحفظة. إن رفض المورّد يُردّ المبلغ تلقائياً. بمفتاح الاختبار: يُنفَّذ فعلاً على بيئة المورّد التجريبية بمال وهمي لا يمسّ محفظتك (20 طلباً يومياً، وتُحذف بعد 7 أيام).
يعيد: {"ok": true, "domain": "mystore.com", "years": 1, "charged": 16.12}
POST /api/v1/domains/<name>/renew domains:write
تجديد دومين
{"years": 1} — يُخصم من المحفظة.
يعيد: {"ok": true, "expires": "2028-09-26"}
POST /api/v1/domains/<name>/nameservers domains:write
تغيير خوادم الأسماء
{"nameservers": ["ns1.x.com", "ns2.x.com"]}
يعيد: {"ok": true}
POST /api/v1/domains/transfer domains:write
نقل دومين إلينا
{"domain": "x.com", "auth_code": "…"} — يُخصم من المحفظة.
يعيد: {"ok": true}
GET /api/v1/domains/suggest domains:read
اقتراح أسماء متاحة
q=وصف النشاط أو رابط الموقع/الصفحة — نعيد أسماء متاحة فعلاً بأسعارها وما فهمناه عن النشاط.
يعيد: {"ok": true, "about": "محل طباعة…", "results": [{"domain": "syrprint.com", "price": 15.84}]}
GET /api/v1/domains/<name>/dns domains:read
سجلات DNS
كل سجلات A وAAAA وCNAME وMX وTXT على الدومين.
يعيد: {"ok": true, "records": [{"type": "A", "host": "@", "value": "1.2.3.4"}]}
POST /api/v1/domains/<name>/dns domains:write
إضافة سجل DNS
{"type": "A", "host": "www", "value": "1.2.3.4"} — وMX مع priority.
يعيد: {"ok": true}
POST /api/v1/domains/<name>/dns/delete domains:write
حذف سجل DNS
{"type": "A", "host": "www", "value": "1.2.3.4"}
يعيد: {"ok": true}
POST /api/v1/domains/<name>/forward domains:write
توجيه الدومين لرابط
{"url": "https://instagram.com/x", "mask": false} أو {"off": true}
يعيد: {"ok": true}
GET /api/v1/domains domains:read
دومينات حسابك
قائمة الدومينات المسجّلة لحسابك.
يعيد: {"ok": true, "domains": []}

بريد الأعمال

GET /api/v1/mail/plans mail:read
خطط البريد وأسعارها
السعر لكل صندوق شهرياً بالدولار (شامل رسوم الخدمة).
يعيد: {"ok": true, "plans": [{"id": "1762", "name": "Professional", "months": [1,3,6,12]}]}
POST /api/v1/mail mail:write
طلب بريد لدومين
{"domain": "mystore.com", "plan": "1762", "months": 12, "mailboxes": 3} — يُخصم من المحفظة. بمفتاح الاختبار: يُنفَّذ فعلاً على بيئة المورّد التجريبية بمال وهمي لا يمسّ محفظتك (20 طلباً يومياً، وتُحذف بعد 7 أيام).
يعيد: {"ok": true, "account": {"id": 7, "state": "pending"}}
GET /api/v1/mail mail:read
حسابات البريد
كل حسابات البريد في حسابك وحالتها وتاريخ انتهائها.
يعيد: {"ok": true, "accounts": []}
POST /api/v1/mail/<id>/login mail:write
رابط دخول مباشر
رابط لمرة واحدة إلى لوحة البريد.
يعيد: {"ok": true, "url": "https://…"}
POST /api/v1/mail/<id>/renew mail:write
تجديد البريد
{"months": 12} — لكل الصناديق الحالية، يُخصم من المحفظة.
يعيد: {"ok": true, "account": {"expires": "2028-09-26"}}
POST /api/v1/mail/<id>/mailboxes mail:write
إضافة صناديق بريد
{"count": 2} — يُحسب للأشهر المتبقية من المدة الحالية فقط.
يعيد: {"ok": true, "account": {"mailboxes": 5}}

Cloudflare

GET /api/v1/cloud/zones cloud:read
دوميناتك على Cloudflare
الحالة (pending/active)، الخطة، خوادم الأسماء، وأين يشير الدومين الآن.
يعيد: {"ok": true, "zones": [{"domain": "mystore.com", "state": "active", "plan": "free"}]}
POST /api/v1/cloud/zones cloud:write
احمِ دوميناً بـ Cloudflare
{"domain": "mystore.com"} — يُنشأ حسابك على Cloudflare عند أول مرة (يلزم الحد الأدنى في المحفظة). دومين مسجّل عندنا يُنقل بسجلاته بلا انقطاع؛ غيره نعيد خادمَي الأسماء لتضعهما عند مسجّله.
يعيد: {"ok": true, "zone": {"domain": "mystore.com", "state": "pending", "name_servers": ["ada.ns.cloudflare.com"]}}
GET /api/v1/cloud/zones/<name>/dns cloud:read
سجلات DNS
كل سجلات A وAAAA وCNAME وMX وTXT مع حالة الحماية (proxied).
يعيد: {"ok": true, "records": [{"id": "…", "type": "A", "host": "www", "value": "1.2.3.4", "proxied": true}]}
POST /api/v1/cloud/zones/<name>/dns cloud:write
إضافة سجل
{"type": "A", "host": "www", "value": "1.2.3.4", "proxied": true} — وMX مع priority.
يعيد: {"ok": true, "record": {"id": "…"}}
POST /api/v1/cloud/zones/<name>/dns/delete cloud:write
حذف سجل
{"id": "…"} — المعرّف من قائمة السجلات.
يعيد: {"ok": true}
POST /api/v1/cloud/zones/<name>/settings cloud:write
إعدادات الحماية
{"setting": "ssl", "value": "full"} — ssl: off/flexible/full/strict · security_level: low/medium/high/under_attack · always_use_https: on/off · min_tls_version · development_mode.
يعيد: {"ok": true}
POST /api/v1/cloud/zones/<name>/purge cloud:write
مسح الكاش
للدومين الفعّال فقط.
يعيد: {"ok": true}
POST /api/v1/cloud/zones/<name>/check cloud:write
تحقق من التفعيل الآن
بعد تغيير خوادم الأسماء عند المسجّل — يعيد الحالة وأين يشير الدومين.
يعيد: {"ok": true, "zone": {"state": "active"}}

Google Workspace

GET /api/v1/workspace/plans workspace:read
خطط Workspace وأسعارها
السعر لكل مستخدم شهرياً حسب المدة (1 أو 12 شهراً).
يعيد: {"ok": true, "plans": [{"id": "1657", "name": "Business Starter", "per_user_month": {"12": 3.84}}]}
POST /api/v1/workspace workspace:write
طلب Google Workspace
{"domain": "mystore.com", "plan": "1657", "months": 12, "users": 3, "admin_login": "admin", "admin_first_name": "Ahmad", "admin_last_name": "Ali", "alternate_email": "me@gmail.com"} — يُخصم من المحفظة، ننشئ حساب المدير، وتصل رسالة Google إلى البريد البديل. بمفتاح الاختبار: يُنفَّذ فعلاً على بيئة المورّد التجريبية بمال وهمي لا يمسّ محفظتك (20 طلباً يومياً، وتُحذف بعد 7 أيام).
يعيد: {"ok": true, "subscription": {"id": 4, "state": "queued"}}
GET /api/v1/workspace workspace:read
اشتراكاتك
الحالة والمستخدمون والمدير وتاريخ الانتهاء.
يعيد: {"ok": true, "subscriptions": []}
POST /api/v1/workspace/<id>/users workspace:write
إضافة مستخدمين
{"count": 2} — للأشهر المتبقية من المدة.
يعيد: {"ok": true}

استضافة ووردبريس

GET /api/v1/hosting/plans hosting:read
خطط الاستضافة
المواصفات والسعر الشهري بالدولار شاملاً رسوم الخدمة.
يعيد: {"ok": true, "plans": [{"id": "1889", "name": "Starter", "websites": "1"}]}
POST /api/v1/hosting hosting:write
طلب استضافة
{"domain": "mystore.com", "plan": "1889", "months": 1} — يُخصم من المحفظة.
يعيد: {"ok": true, "site": {"id": 3, "state": "pending"}}
GET /api/v1/hosting hosting:read
مواقعك المستضافة
الحالة وتاريخ الانتهاء.
يعيد: {"ok": true, "sites": []}
POST /api/v1/hosting/<id>/login hosting:write
رابط دخول مباشر للوحة
رابط لمرة واحدة.
يعيد: {"ok": true, "url": "https://…"}
POST /api/v1/hosting/<id>/renew hosting:write
تجديد الاستضافة
{"months": 12} — يُخصم من المحفظة.
يعيد: {"ok": true, "site": {"expires": "2027-09-26"}}

الإشعارات الصادرة

نرسلها إلى الرابط الذي تسجّله، موقّعة بنفس الخوارزمية في X-Syriana-Signature. أعد 2xx لتأكيد الاستلام؛ وإلّا نعيد المحاولة ست مرّات على مدى ٤ ساعات.

order.fulfilled اكتمل الطلب وصدرت تراخيصه فعلاً (مفاتيح حقيقية).
order.processing قُبل الطلب وخُصم، وبعض التراخيص قيد التجهيز.
order.cancelled أُلغي الطلب وأُعيد المبلغ إلى رصيدك.
license.delivered وصل مفتاح كان طلباً مسبقاً — اقرأه من /orders/{id}/licenses.
wallet.low الرصيد قارب النفاد — قبل أن يفشل طلب، لا بعده.
wallet.topped_up وصلت شحنتك وأُضيفت إلى رصيدك.
wallet.settled صدرت فاتورة دورتك الآجلة وصُفِّر الرصيد.
wallet.plan_due حان تجديد باقتك ورصيدك لا يكفي. الخدمة تعمل — اشحن ويُخصم التجديد تلقائياً.
quota.warning بلغت ٨٠٪ من طلبات باقتك في هذه الدورة. تنبيه واحد لكل دورة، ولا نوقف شيئاً عند التجاوز.
payment.paid دفع عميلك رابط دفع لك — المبلغ والرسوم والصافي في الجسم. هذا هو الحدث الذي تُسلّم عنده.
payment.failed فشلت محاولة على رابطك؛ الرابط ما زال قابلاً للدفع.
payment.cancelled ألغى الدافع العملية.
payment.refunded استُرجعت الدفعة كاملةً — سواء عبر لوحتك أو لوحة المزوّد. الاسترجاع الجزئي لا يُطلق هذا الحدث.
payment.partially_refunded استُرجع جزءٌ من الدفعة وبقيت «مدفوعة» — refunded في الجسم يقول كم خرج حتى الآن.
installment.signed وقّع عميلك عقد التقسيط — كل قسط بعده يصلك payment.paid ومرجعه رقم العقد.
installment.completed سُدّد العقد كاملاً.
verification.verified أثبت المشتري هويّته لدينا. لا نرسل لك مستنداً ولا اسماً — النتيجة فقط.
verification.refused لم يجتَز التوثيق. القرار في البيع يبقى قرارك.

رموز الأخطاء

الرمزHTTPالمعنى
unauthorized 401 مفتاح أو توقيع غير صالح. لا نفرّق بين السببين عمداً.
stale_timestamp 401 ساعة خادمك بعيدة أكثر من ٥ دقائق عن ساعتنا.
app_not_live 403 التطبيق لم يُعتمد بعد؛ يعمل تجريبياً فقط.
app_suspended 403 التطبيق موقوف.
live_key_required 403 نقطة تلمس بيانات حقيقيّة (مفاتيح، رسائل، سجلّات، شحن): لا تقبل مفتاح التجربة.
missing_scope 403 المفتاح لا يملك الصلاحية المطلوبة لهذه النقطة.
no_wallet 403 مفتاح قراءة بلا محفظة — البيع يحتاج محفظة.
not_found 404 لا يوجد مورد بهذا المعرّف يخصّك.
invalid_request 400 جسم الطلب ناقص أو خارج الحدود المسموحة.
invalid_json 400 الجسم ليس كائن JSON صالحاً.
unknown_sku 400 رمز منتج غير معروف أو غير قابل للبيع.
customer_required 400 الطلب بلا «customer.ref» — من اشترى منك؟ إلزامي منذ 2026-09-09.
missing_parameter 400 معامل إلزامي غائب (مثل since).
invalid_parameter 400 قيمة معامل غير مفهومة.
unsupported_currency 400 لا نملك سعر صرف لهذه العملة. الرسالة تُعدّد المتاح.
currency_mismatch 409 محفظتك بعملة غير عملة الكتالوج.
idempotency_required 400 ترويسة Idempotency-Key ناقصة على الطلبات.
idempotency_conflict 409 نفس المفتاح استُخدم بجسم مختلف.
request_in_progress 409 نسخة سابقة من نفس الطلب قيد المعالجة.
wallet_busy 409 طلب آخر يستخدم محفظتك الآن — أعد المحاولة.
conflict_retry 409 تعارض مؤقّت مع طلب متزامن. أعد المحاولة بنفس مفتاح التكرار.
insufficient_funds 402 الرصيد لا يكفي.
provision_failed 400 تعذّر إنشاء حساب التاجر — الرسالة تقول السبب.
provision_in_progress 409 نفس المتجر يُنشأ الآن في طلب آخر — أعد المحاولة بعد ثوانٍ.
unsupported_platform 422 الخدمة لا تعمل بعد على منصّة تطبيقك — الرسالة تُعدّد المتاح.
channel_mismatch 403 تطبيقك يتكلّم باسم قناته وحدها — «channel» يخالفها أو لتطبيقٍ آخر.
channel_unbound 403 لم تُربط قناةٌ بتطبيقك بعد — مراجعة التوثيق والهويّة ومنح الدفع لتجّار قناتك وحدها. راسلنا لربطها.
not_a_connector 403 حساب تاجرٍ مُزوَّد لا يتكلّم باسم قناة.
platform_only 403 صلاحيّات platform:* لمنصّة سيريانا نفسها.
method_not_allowed 405 المسار موجود بطريقةٍ أخرى — ترويسة Allow تذكرها.
live_only 403 إنشاء الحسابات يحتاج تطبيقاً معتمداً للإنتاج.
invalid_idempotency_key 400 مفتاح التكرار لا يبدأ بـ«test:» في الإنتاج.
replayed_request 401 طلب موقَّع وصل من قبل — وقّع كل طلب بختم زمني جديد. بتوقيع v2 يُستعمل التوقيع مرّةً واحدة لكلّ طريقة، حتى GET وحتى مع Idempotency-Key: أعد التوقيع عند إعادة المحاولة وأبقِ المفتاح نفسه فتأتيك الإجابة المحفوظة.
signature_v2_required 401 تطبيقك (أو المنصّة كلّها) يشترط توقيع الإصدار ٢: X-Syriana-Signature-Version: 2 على "v2\n{timestamp}\n{METHOD}\n{path?query}\n{body}" (أسطر يفصلها LF).
codes_not_yours 403 «codes» تحوي ما ليس من طلباتك عبر الواجهة في آخر ٦٠ يوماً.
too_many_notices 429 أُرسل لهذا العميل ٢٠ إشعاراً خلال ٢٤ ساعة — أعد غداً.
invalid_provider 400 مزوّد دفع غير معروف — راجع /pay_accounts/providers.
missing_public 400 المفتاح العام (publicKey) إلزامي.
missing_secret 400 المفتاح السرّي (secretKey) إلزامي عند أوّل ربط لهذا المزوّد.
kyc_required 403 حساب env=live يحتاج توثيق هويّة أوّلاً — وثّق من /my/verify.
already_verified 409 الحساب موثَّق بالفعل — القرار القائم لا يُعاد فتحه.
kyc_locked 409 البيانات قيد المراجعة أو سليمة — لا يُعدَّل إلّا ما لم يتطابق.
kyc_cooldown 429 قدّمت التوثيق للتوّ — انتظر دقيقة قبل إعادة التقديم.
invalid_document 400 المستند مرفوض: ليس صورة، أو أكبر من الحدّ، أو نوعه غير معروف.
activation_failed 400 التفعيل رفضه النموذج (مفتاحٌ ناقص مثلاً) — الرسالة تقول السبب بالحرف.
topup_refused 400 الشحنة تحت الحدّ الأدنى أو فوق السقف أو بوسيلة غير متاحة لك — الرسالة تقول أيّها.
not_available 503 خدمة لدينا غير مهيّأة الآن — البريد مثلاً. أعد المحاولة أو راسلنا.
installment_refused 422 شروطك أو حدود باقتك ترفض عرض التقسيط هذا — رمز السبب أوّل الرسالة.
manual_only 422 الاسترجاع يدويّ: أرجِع من لوحة المزوّد ثمّ أرسل alreadyDone: true.
nothing_to_refund 409 الدفعة ليست مدفوعة أو استُرجعت كلّها.
exceeds_payment 400 مبلغ الاسترجاع أكبر من المتبقّي.
unsupported 422 المزوّد لا يتيح الاسترجاع الآليّ — أرجِع من لوحته ثمّ أرسل alreadyDone: true.
no_account 409 لا حساب مزوّدٍ مربوط لهذه البيئة.
no_provider_reference 409 المزوّد لم يُعطنا مرجع العمليّة بعد.
no_credentials 409 مفاتيحك لدى المزوّد ناقصة.
unreachable 502 المزوّد لا يردّ — لم يُسترجَع شيء، أعد المحاولة.
refused 402 المزوّد رفض الاسترجاع — سببه في الرسالة.
rate_limited 429 تجاوزت حدّ الطلبات في الدقيقة.
payload_too_large 413 حجم الطلب أكبر من المسموح.
internal_error 500 خطأ لدينا. سُجّل بالكامل للمراجعة.
already_reported 409 لك بلاغ من هذا النوع على هذه الهويّة بالفعل.
no_transaction 403 لا معاملة بينك وبين هذا المشتري — لا يُبلَّغ ولا يُشهَد إلّا عمّن اشترى منك فعلاً.
risk_quota_exceeded 402 استهلكت استعلامات باقتك لهذه الدورة. الإبلاغ يبقى مجانياً بلا حدّ.