التوثيق — الإصدار v1
المصادقة
كل نداء يحمل ثلاث ترويسات. التوقيع على
"{timestamp}.{raw_body}" بخوارزمية
HMAC-SHA256 وسرّك، ونافذة القبول ٣٠٠ ثانية —
فاضبط ساعة خادمك، فهي أكثر أسباب فشل التوقيع.
X-Syriana-Key: sy_live_xxxxxxxxxxxx
X-Syriana-Timestamp: 1756000000
X-Syriana-Signature: hex(hmac_sha256(secret, "1756000000." + body))
import hashlib, hmac, json, time, requests
KEY, SECRET = "sy_test_...", "...."
BASE = "https://syriana.store"
def call(method, path, payload=None):
body = json.dumps(payload, ensure_ascii=False) if payload else ""
ts = str(int(time.time()))
sig = hmac.new(SECRET.encode(), f"{ts}.{body}".encode(),
hashlib.sha256).hexdigest()
return requests.request(method, BASE + path, data=body.encode(), headers={
"X-Syriana-Key": KEY,
"X-Syriana-Timestamp": ts,
"X-Syriana-Signature": sig,
"Content-Type": "application/json",
})
print(call("GET", "/api/v1/ping").json())
شكل الردّ
ثابت لا يتغيّر: النجاح دائماً data وmeta،
والفشل دائماً error. الحقول تُضاف ولا تُحذف، فما تبنيه
اليوم يبقى يعمل.
{"data": {...}, "meta": {"version": "v1", "page": 1, "total": 201}}
{"error": {"code": "missing_scope", "message": "..."}}
نقاط النهاية
التحقّق
/api/v1/ping
توقيع فقط
{"ok": true, "time": "...", "sandbox": true}
/api/v1/me
توقيع فقط
{"app": "...", "scopes": [...], "wallet": {...}}
الكتالوج
/api/v1/products
catalog:read
قائمة منتجات، كلٌّ برمز sku ثابت وسعرك أنت.
/api/v1/products/{sku}
catalog:read
كائن منتج مفصّل.
/api/v1/products/changes
catalog:read
قائمة منتجات مفصّلة مرتّبة بتاريخ التعديل.
المحفظة
/api/v1/wallet
wallet:read
{"balance": .., "spendable": .., "mode": "prepaid"}
/api/v1/wallet/entries
wallet:read
قائمة حركات بالرصيد بعد كلٍّ منها.
/api/v1/wallet/topup-methods
wallet:read
قائمة وسائل بحدودها.
/api/v1/wallet/topup
wallet:write
201 مع pay_url — افتحه في المتصفّح لإتمام الدفع.
/api/v1/wallet/topups
wallet:read
قائمة شحنات.
الطلبات
/api/v1/orders
orders:write
201 مع order_id والتراخيص، أو 402 لعدم كفاية الرصيد، أو 409 لتضارب مفتاح التكرار.
/api/v1/orders
orders:read
قائمة طلبات مختصرة.
/api/v1/orders/{order_id}
orders:read
الطلب بأصنافه وتراخيصه.
/api/v1/orders/{order_id}/licenses
licenses:read
قائمة تراخيص بحالة كلٍّ منها.
الإشعارات الصادرة
نرسلها إلى الرابط الذي تسجّله، موقّعة بنفس الخوارزمية في
X-Syriana-Signature. أعد 2xx لتأكيد
الاستلام؛ وإلّا نعيد المحاولة ست مرّات على مدى ٤ ساعات.
order.fulfilled |
اكتمل الطلب وصدرت تراخيصه فعلاً (مفاتيح حقيقية). |
order.processing |
قُبل الطلب وخُصم، وبعض التراخيص قيد التجهيز. |
order.cancelled |
أُلغي الطلب وأُعيد المبلغ إلى رصيدك. |
license.delivered |
وصل مفتاح كان طلباً مسبقاً — اقرأه من /orders/{id}/licenses. |
wallet.low |
الرصيد قارب النفاد — قبل أن يفشل طلب، لا بعده. |
wallet.topped_up |
وصلت شحنتك وأُضيفت إلى رصيدك. |
wallet.settled |
صدرت فاتورة دورتك الآجلة وصُفِّر الرصيد. |
رموز الأخطاء
| الرمز | HTTP | المعنى |
|---|---|---|
unauthorized |
401 | مفتاح أو توقيع غير صالح. لا نفرّق بين السببين عمداً. |
stale_timestamp |
401 | ساعة خادمك بعيدة أكثر من ٥ دقائق عن ساعتنا. |
app_not_live |
403 | التطبيق لم يُعتمد بعد؛ يعمل تجريبياً فقط. |
app_suspended |
403 | التطبيق موقوف. |
missing_scope |
403 | المفتاح لا يملك الصلاحية المطلوبة لهذه النقطة. |
no_wallet |
403 | مفتاح قراءة بلا محفظة — البيع يحتاج محفظة. |
not_found |
404 | لا يوجد مورد بهذا المعرّف يخصّك. |
invalid_request |
400 | جسم الطلب ناقص أو خارج الحدود المسموحة. |
invalid_json |
400 | الجسم ليس كائن JSON صالحاً. |
unknown_sku |
400 | رمز منتج غير معروف أو غير قابل للبيع. |
missing_parameter |
400 | معامل إلزامي غائب (مثل since). |
invalid_parameter |
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 | الرصيد لا يكفي. |
topup_refused |
400 | الشحنة تحت الحدّ الأدنى أو فوق السقف أو بوسيلة غير متاحة لك — الرسالة تقول أيّها. |
rate_limited |
429 | تجاوزت حدّ الطلبات في الدقيقة. |
payload_too_large |
413 | حجم الطلب أكبر من المسموح. |
internal_error |
500 | خطأ لدينا. سُجّل بالكامل للمراجعة. |