واجهة API والويب هوك
اربط الكاشير أو متجرك أو نظامك الخاص بـ OPT Retention: تسجيل العملاء والعمليات تلقائيًا، وإشعار فوري عند كل حدث. مفاتيح لكل تكامل، سجل طلبات، وإعادة إرسال عند الفشل.
البدء في 5 دقائق
واجهة API تتيح لنظام الكاشير أو المتجر أو أي برنامج لديك أن يسجّل العملاء والعمليات تلقائيًا في حسابك، وأن يستقبل إشعارًا فوريًا (ويب هوك) عند كل حدث مهم: تسجيل عميل، عملية، مكافأة، تقييم، موعد.
- من لوحة التحكم: الإدارة ← API و Webhooks. الميزة ضمن باقة الاحتراف أو كإضافة «ربط API» على الباقات الأخرى.
- اضغط + مفتاح API، سمِّه (مثلًا «كاشير الفرع الرئيسي») وحدد النطاقات. السر يظهر مرة واحدة فقط — انسخه فورًا.
- جرّب أول طلب:
curl https://retention.aimenu.me/api/v1/customers?limit=5 \
-H "Authorization: Bearer grs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
https://retention.aimenu.me/api/v1 · كل الطلبات والردود JSON بترميز UTF-8 · التواريخ بصيغة ISO 8601 (2026-09-22T14:05:00Z) · المبالغ بالهللات/القروش كأعداد صحيحة (amount_minor) أو كمبلغ عشري (amount).المصادقة والنطاقات
أرسل المفتاح في ترويسة Authorization: Bearer <المفتاح> (أو X-Api-Key). المفتاح يخص منشأة واحدة ولا يرى غيرها.
| النطاق | يسمح بـ |
|---|---|
customers:read | عرض العملاء والبحث فيهم |
customers:write | إنشاء عميل |
transactions:write | تسجيل عملية شراء (تُحتسب نقاطها فورًا) |
customers:* / * | كل نطاقات المجموعة / كل شيء |
المفتاح يتوقف تلقائيًا إذا انتهى الاشتراك أو انتقلت المنشأة إلى باقة بلا API (ردّ 403).
العملاء
GET /api/v1/customers
قائمة العملاء مع ترقيم بالمؤشر (cursor).
| معامل | النوع | الوصف |
|---|---|---|
limit | عدد 1–100 | حجم الصفحة (افتراضي 50) |
cursor | نص | قيمة meta.next_cursor من الصفحة السابقة |
search | نص | بحث في الاسم أو الجوال |
lifecycle_state | نص | new · active · at_risk · churned |
{
"ok": true,
"data": [
{ "id": "cust_8f2…", "name": "سارة العتيبي", "phone": "+9665xxxxxxxx",
"lifecycle_state": "active", "visit_count": 12, "points": 340,
"last_visit_at": "2026-09-18T16:20:00Z", "return_due_at": "2026-10-02T16:20:00Z" }
],
"meta": { "limit": 50, "count": 1, "next_cursor": null, "has_more": false }
}
GET /api/v1/customers/{id}
عميل واحد بالشكل نفسه. غير موجود ← 404.
POST /api/v1/customers
| حقل | مطلوب | القواعد |
|---|---|---|
name | نعم | حتى 120 حرفًا |
phone | نعم | جوال؛ يُطبَّع تلقائيًا بمفتاح دولة المنشأة (05xxxxxxxx يصبح +9665xxxxxxxx). الجوال المكرر ← 422 |
expected_return_days | لا | 1–3650 (افتراضي 30) — دورة العودة المتوقعة لهذا العميل |
branch_id | لا | معرّف فرع من فروعك |
preferred_locale | لا | ar-SA افتراضيًا |
curl -X POST https://retention.aimenu.me/api/v1/customers \
-H "Authorization: Bearer grs_…" -H "Content-Type: application/json" \
-d '{"name":"سارة العتيبي","phone":"0551234567"}'
# 201 → { "ok": true, "data": { "id": "cust_…", … } }
تسجيل عملية شراء
POST /api/v1/transactions
يسجّل عملية للعميل ويحتسب نقاطه ومستواه ومكافآت الإحالة فورًا، ويشغّل الرسائل التلقائية (شكر بعد الزيارة، طلب التقييم).
Idempotency-Key إلزامية (8–128 حرفًا، مثل رقم الفاتورة أو UUID). إعادة إرسال الطلب نفسه بالمفتاح نفسه لا تسجّل العملية مرتين، بل تعيد العملية الأصلية مع "duplicate": true. المفتاح نفسه ببيانات مختلفة ← 409.| حقل | مطلوب | القواعد |
|---|---|---|
customer_id | نعم | معرّف عميل من منشأتك |
amount أو amount_minor | نعم | 47.50 أو 4750 (هللات) — أكبر من صفر |
currency | لا | ثلاثة أحرف؛ افتراضيًا عملة المنشأة (SAR) |
occurred_at | لا | ISO 8601؛ افتراضيًا الآن |
external_transaction_id | لا | رقم الفاتورة في نظامك — يُحفظ ويمنع التكرار أيضًا |
branch_id | لا | افتراضيًا فرع العميل المفضل |
curl -X POST https://retention.aimenu.me/api/v1/transactions \
-H "Authorization: Bearer grs_…" -H "Content-Type: application/json" \
-H "Idempotency-Key: INV-2026-000123" \
-d '{"customer_id":"cust_8f2…","amount":180.00,"external_transaction_id":"INV-2026-000123"}'
# 200 → { "ok": true, "data": { "transaction": { "id": "…", "amount_minor": 18000, "currency": "SAR", "status": "completed" }, "duplicate": false } }
نصيحة للكاشير: أرسل العملية بعد إغلاق الفاتورة واستخدم رقم الفاتورة مفتاحًا للتكرار — فتستطيع إعادة المحاولة بأمان عند انقطاع الشبكة.
الأخطاء والحدود
{ "error": { "code": "validation_failed", "message": "تعذر التحقق من الطلب.",
"request_id": "req_…", "fields": { "phone": ["يجب أن يكون رقم هاتف صالحًا"] } } }
| HTTP | code | المعنى |
|---|---|---|
| 401 | invalid_api_key | المفتاح غير صالح أو محذوف |
| 403 | insufficient_scope · feature_not_available · subscription_inactive | النطاق لا يكفي / الباقة بلا API / الاشتراك متوقف |
| 400 | idempotency_key_required | ترويسة التكرار ناقصة |
| 404 | not_found | المسار أو العميل غير موجود |
| 409 | idempotency_conflict | المفتاح نفسه ببيانات مختلفة |
| 422 | validation_failed | حقول غير صالحة — التفاصيل في fields |
| 429 | rate_limited | أكثر من 240 طلبًا في الدقيقة للمفتاح — انتظر ثم أعد |
أرفق request_id عند التواصل مع الدعم.
الويب هوك (إشعارات صادرة)
من الصفحة نفسها اضغط + Webhook: رابط HTTPS في نظامك + الأحداث التي تريدها (فارغ = كل الأحداث). يظهر السر whsec_… مرة واحدة — احفظه للتحقق من التوقيع.
كل حدث يُرسل بطلب POST بهذا الشكل:
POST https://your-system.example/hooks/retention
Content-Type: application/json
User-Agent: RetentionOS-Webhook/1.0
X-Retention-Event: transaction.completed
X-Retention-Event-Id: evt_…
X-Retention-Signature: sha256=3f1a…
{ "event": "transaction.completed", "timestamp": "2026-09-22T14:05:00Z",
"data": { "transaction_id": "…", "customer_id": "cust_…", "amount_minor": 18000, "gross_minor": 18000, "discount_minor": 0, "currency": "SAR" },
"meta": { "event_id": "evt_…", "correlation_id": null } }
- ردّ بـ 2xx خلال ثوانٍ ثم عالج الحدث في الخلفية. أي ردّ آخر يُعاد إرساله تلقائيًا: بعد دقيقة، 5 دقائق، 15، ساعة، 6 ساعات (5 محاولات).
- ردّ
4xx(عدا 408/429) يعني أن نظامك رفض الحدث فلا يُعاد؛ يظهر «فاشلة نهائيًا» في اللوحة مع زر إعادة الإرسال. - الأحداث قد تصل أكثر من مرة — اجعل المعالجة آمنة للتكرار باستخدام
event_id. - الرابط يجب أن يكون HTTPS عامًا (لا localhost ولا عناوين داخلية).
جدول الأحداث
| الحدث | متى | أهم حقول data |
|---|---|---|
customer.created | تسجيل عميل (QR، واي فاي، كاشير، API) | customer_id, display_name |
customer.merged | دمج عميلين | source_customer_id, target_customer_id |
transaction.completed | عملية مسجلة (كاشير/يدوي/API) | transaction_id, customer_id, amount_minor, gross_minor, discount_minor, currency |
transaction.voided | إلغاء عملية | transaction_id, customer_id |
sale.paid / sale.refunded | بيع من كاشير المنصة / استرداد | number, total_minor, customer_id, invoice_id / amount_minor, full |
reward.redeemed | استبدال مكافأة | customer_id, reward_id, transaction_id |
loyalty.adjusted | تعديل نقاط يدوي | customer_id, delta |
tier.changed | تغيّر مستوى العميل | customer_id, to, direction |
coupon.issued / coupon.used | إصدار كوبون / استخدامه | customer_id, coupon_id, code / transaction_id, discount_minor |
referral.joined / referral.qualified / referral.rewarded | صديق انضم / اشترى / مكافأة المُحيل | referrer_customer_id, referee_customer_id / transaction_id / grant_type |
review.rated | تقييم بعد الزيارة | customer_id, rating, positive |
appointment.created / appointment.rescheduled / appointment.canceled | الحجوزات | appointment_id, customer_id, starts_at, source / by |
game.won | جائزة من عجلة الحظ | customer_id, prize, kind |
التحقق من التوقيع
التوقيع = sha256= + HMAC-SHA256 لجسم الطلب الخام بالسر whsec_…. تحقق قبل أي معالجة:
// PHP
$raw = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, $secret);
if (!hash_equals($expected, $_SERVER['HTTP_X_RETENTION_SIGNATURE'] ?? '')) { http_response_code(401); exit; }
$event = json_decode($raw, true);
http_response_code(200); // ثم عالج $event في الخلفية
// Node.js (Express — استخدم الجسم الخام لا المُحلَّل)
app.post('/hooks/retention', express.raw({ type: '*/*' }), (req, res) => {
const expected = 'sha256=' + crypto.createHmac('sha256', SECRET).update(req.body).digest('hex');
const given = req.get('X-Retention-Signature') || '';
if (expected.length !== given.length || !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(given))) return res.sendStatus(401);
const event = JSON.parse(req.body);
res.sendStatus(200); // ثم عالج event
});
قبل الإطلاق
- مفتاح API منفصل لكل نظام (كاشير، متجر، ERP) بأقل نطاقات تكفيه؛ يمكن إيقاف أي مفتاح من اللوحة دون أن يتأثر غيره.
- رقم الفاتورة هو
Idempotency-Keyوexternal_transaction_idمعًا. - سجّل العميل أولًا (أو ابحث عنه بالجوال) ثم أرسل العملية بمعرّفه.
- معالِج الويب هوك يرد 2xx فورًا ويتجاهل الأحداث المكررة بـ
event_id. - راقب صفحة «API و Webhooks»: آخر استخدام لكل مفتاح، وحالة تسليم كل ويب هوك، وإعادة الإرسال عند الفشل.
الدعم الفني للتكامل: تواصل معنا مع request_id أو event_id.