نظرة عامة
لـ Upuah سطحان: ويدجت الشات عبر CDN للزائر على موقعك، وواجهة السيرفر بمفتاح sesh_ للمحادثات والتذاكر من الباك إند.
القاعدة: https://upuah.com/api/v1 · الـ CDN: https://upuah.com
لا تضع مفتاح sesh_ في كود المتصفح. محمّل الـ embed يستخدم رمز emb_ عامًا ومقيّدًا بـ allowed origins.
ويدجت الشات (CDN)
صمّم الويدجت من Dashboard → Integrations → Widget (الألوان، التحية، أيقونة الإطلاق، المواقع المسموحة). الصق السكربت قبل </body>.
مسار الزائر: الاسم → الموبايل → «سيتم ربطك بوكيل» → حالة pending حتى Accept من الـ Inbox → رسالة انضمام الوكيل → شات مفتوح. Close ينهي المحادثة للطرفين.
كل Integration له محمّل emb_… فريد. النواة المشتركة: https://upuah.com/cdn/widget.js
سكربت التضمين
<script src="https://upuah.com/cdn/embed/emb_xxxxxxxx.js" async></script>
واجهة الودجت (آمنة للمتصفح)
بدون سر سيرفر. المسارات تحت /api/v1/widget/{embed_key}/… وتحترم allowed_origins من إعدادات الويدجت.
GET /config — الثيم والتحية والقناة الافتراضية. GET /auto-replies — الأسئلة الشائعة. POST /conversations — بدء بالاسم والموبايل (pending). GET …/messages — جلب الحالة والرسائل (مع can_chat). POST …/messages — رسالة الزائر (فقط عندما تكون الحالة open).
بدء شات (ويدجت)
POST https://upuah.com/api/v1/widget/{embed_key}/conversations
Content-Type: application/json
Accept: application/json
{
"channel_id": 1,
"name": "Alex Guest",
"phone": "+971501234567"
}
جلب الرسائل
curl https://upuah.com/api/v1/widget/{embed_key}/conversations/{uuid}/messages \
-H "Accept: application/json" \
-H "Origin: https://your-site.example"
مصادقة السيرفر
طلبات السيرفر تستخدم مفتاح التكامل (sesh_…) الذي يُنشأ عند إضافة Integration. المفتاح مربوط بمستأجر واحد وتكامل واحد.
أرسله كـ Bearer أو عبر X-Sesh-Key. دوّر المفاتيح من Dashboard → Integrations.
Authorization: Bearer sesh_xxxxxxxx
X-Sesh-Key: sesh_xxxxxxxx
Accept: application/json
القنوات
أنشئ قناة نشطة واحدة على الأقل في الداشبورد (مثل الدعم الفني أو المبيعات) قبل الشات أو التذاكر.
الويدجت يستخدم القناة الافتراضية من إعداداته (أو channel_id في الطلب). التذاكر تستخدم قناة التذاكر الافتراضية من الإعدادات ما لم تمرّر channel_id.
واجهة الشات المباشر (سيرفر)
نفس الـ Inbox مثل الويدجت، لكن من باك إندك بمفتاح sesh_. تُفتح كمحادثة open (وليس مسار pending الخاص بالويدجت).
POST /api/v1/conversations — مطلوب: channel_id و name و subject وإما إيميل أو موبايل. اختياري: message لأول رسالة.
GET /api/v1/conversations/{uuid}/messages — قائمة الرسائل. POST …/messages — رسالة زائر. POST …/close — إغلاق.
curl -X POST https://upuah.com/api/v1/conversations \
-H "Authorization: Bearer sesh_xxx" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"channel_id": 1,
"name": "Nora",
"email": "nora@example.com",
"subject": "مشكلة الدفع",
"message": "زر الدفع لا يعمل على الموبايل."
}'
الرسائل والحالة
محادثات الويدجت: pending → open (بعد Accept) → closed. الزائر لا يرسل حتى open (can_chat: true).
عند التحويل تصبح الحالة transferred وتُرفض الرسائل على الـ uuid القديم. اعرض رسالة النظام وافتح الـ uuid الجديد من transferred_to.
curl https://upuah.com/api/v1/conversations/{uuid}/messages \
-H "Authorization: Bearer sesh_xxx" \
-H "Accept: application/json"
الردود التلقائية
تُدار من Dashboard → Auto replies. تُرجع للويدجت (إن كانت مفعّلة) وعبر GET /api/v1/auto-replies بمفتاح السيرفر.
curl https://upuah.com/api/v1/auto-replies \
-H "Authorization: Bearer sesh_xxx" \
-H "Accept: application/json"
واجهة التذاكر
منفصلة عن الشات المباشر. للتذاكر غير المتزامنة والمرفقات والردود المترابطة — وليست ويدجت التواصل.
POST /api/v1/tickets (multipart للمرفقات). مطلوب: name و subject و body وإيميل أو موبايل. اختياري: channel_id و attachments[].
GET /api/v1/tickets/{uuid} · POST /api/v1/tickets/{uuid}/replies
curl -X POST https://upuah.com/api/v1/tickets \
-H "Authorization: Bearer sesh_xxx" \
-F "name=Omar" \
-F "email=omar@example.com" \
-F "subject=فاتورة" \
-F "body=الرابط لا يعمل" \
-F "attachments[]=@/path/file.pdf"
الويب هوك
يمكن ضبط Webhook URL عند إنشاء التكامل. تحقق من X-Sesh-Signature = HMAC SHA-256 لجسم JSON الخام بسر الويب هوك. X-Sesh-Event يوضح اسم الحدث.
الأحداث: conversation.pending و conversation.accepted و message.created و conversation.closed و conversation.transferred و ticket.created و ticket.replied.
{
"event": "message.created",
"created_at": "2026-08-25T12:00:00+00:00",
"data": {
"conversation_uuid": "...",
"message_uuid": "...",
"body": "جارٍ المراجعة",
"sender_type": "agent"
}
}
التحقق من التوقيع (Node)
import crypto from 'crypto';
function verifyUpuahWebhook(rawBody, signatureHeader, secret) {
const digest = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(digest),
Buffer.from(signatureHeader),
);
}
الربط بـ JavaScript
لواجهات مخصصة على السيرفر (Node) أو بروكسي باك إند. للزوار على الموقع فضّل ويدجت الـ CDN.
من المتصفح نادِ باك إندك الذي يحتفظ بالمفتاح — لا تضع sesh_ في الفرونت.
Node / باك إند
const API = 'https://upuah.com/api/v1';
const KEY = process.env.SESH_API_KEY;
async function startChat({ channelId, name, email, subject, message }) {
const res = await fetch(`${API}/conversations`, {
method: 'POST',
headers: {
Authorization: `Bearer ${KEY}`,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
channel_id: channelId,
name,
email,
subject,
message,
}),
});
if (!res.ok) throw new Error(await res.text());
const { data } = await res.json();
return data.uuid;
}
async function sendMessage(uuid, body) {
const res = await fetch(`${API}/conversations/${uuid}/messages`, {
method: 'POST',
headers: {
Authorization: `Bearer ${KEY}`,
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({ body }),
});
return res.json();
}
async function listMessages(uuid) {
const res = await fetch(`${API}/conversations/${uuid}/messages`, {
headers: {
Authorization: `Bearer ${KEY}`,
Accept: 'application/json',
},
});
return res.json();
}
الربط بـ PHP
خزّن المفتاح في .env (مثلاً SESH_API_KEY). استخدم cURL أو Guzzle من السيرفر.
PHP cURL
$api = 'https://upuah.com/api/v1';
$key = getenv('SESH_API_KEY');
$payload = json_encode([
'channel_id' => 1,
'name' => 'Nora',
'email' => 'nora@example.com',
'subject' => 'مشكلة الدفع',
'message' => 'زر الدفع لا يعمل.',
]);
$ch = curl_init($api.'/conversations');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.$key,
'Content-Type: application/json',
'Accept: application/json',
],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
الربط بـ Python
استخدم requests (أو httpx). احتفظ بالمفتاح في متغير بيئة على السيرفر.
Python requests
import os
import requests
API = 'https://upuah.com/api/v1'
KEY = os.environ['SESH_API_KEY']
HEADERS = {
'Authorization': f'Bearer {KEY}',
'Accept': 'application/json',
}
r = requests.post(
f'{API}/conversations',
headers={**HEADERS, 'Content-Type': 'application/json'},
json={
'channel_id': 1,
'name': 'Nora',
'email': 'nora@example.com',
'subject': 'مشكلة الدفع',
'message': 'زر الدفع لا يعمل.',
},
)
r.raise_for_status()
uuid = r.json()['data']['uuid']
messages = requests.get(
f'{API}/conversations/{uuid}/messages',
headers=HEADERS,
).json()
الأخطاء
401 unauthenticated — مفتاح ناقص أو غير صالح.
403 forbidden — Origin غير مسموح للويدجت.
422 channel_required — أنشئ قناة / عيّن قناة التذاكر الافتراضية.
422 contact_required — أرسل إيميل أو موبايل (شات سيرفر / تذاكر).
422 Waiting for an agent to join — رسالة زائر أثناء pending.
422 validation — أخطاء الحقول في الـ JSON.