مقدمة
Toome Developer API واجهةٌ برمجية من نوع REST تتيح لأي نظام خارجي التكامل مع منصة تومي. يمكن عبرها إرسال إشعارات واتساب، استقبال الطلبات من المتاجر الخارجية، وإدارة بيانات العملاء في CRM — كل ذلك من خلال Bearer Token آمن يُصدَر لكل تطبيق مسجَّل.
https://dygovil.com/api/v1جميع الطلبات والاستجابات بصيغة JSON. يجب إرفاق الترويستَين
Content-Type: application/json و Accept: application/json في كل طلب.
المصادقة
تعتمد الواجهة البرمجية نظام OAuth2 Client Credentials، وهو النمط المخصص للاتصالات بين الخوادم (server-to-server) حيث لا يتدخل المستخدم النهائي في عملية المصادقة. خطوات الاستخدام:
- سجِّل تطبيقاً جديداً من لوحة المطورين للحصول على
client_idوclient_secret. - أرسِل طلب
POST /api/v1/tokenبهذه البيانات للحصول علىaccess_token. - أرفِق رمز الوصول في ترويسة كل طلب لاحق:
Authorization: Bearer {token}.
401 Unauthorized، فيتعين إصدار رمز جديد تلقائياً.نطاقات الصلاحية (Scopes)
يتمتع كل تطبيق بمجموعة محددة من نطاقات الصلاحية تُمنح عند إنشائه. لا يمكن لأي طلب تجاوز النطاقات المُسندة إليه.
| Scope | الصلاحية الممنوحة |
|---|---|
notify | إرسال إشعارات واتساب عبر قوالب Template معتمدة من Meta |
orders.write | إنشاء طلبات خارجية وتحديث حالاتها في تومي |
orders.read | استرجاع الطلبات المحفوظة والاطلاع عليها |
customers.write | إضافة عملاء جدد وتعديل بياناتهم في نظام CRM |
customers.read | استرجاع بيانات العملاء مع دعم البحث والتصفية |
brain.chat | التفاعل مع نظام الذكاء الاصطناعي المرتبط بحسابك |
رموز الأخطاء
تُعيد الواجهة البرمجية رموز HTTP معيارية مصحوبةً بجسم JSON يتضمن تفاصيل الخطأ.
| رمز HTTP | الدلالة |
|---|---|
401 | رمز الوصول مفقود أو منتهي الصلاحية — أعِد إصدار التوكن |
403 | التطبيق لا يملك النطاق (scope) المطلوب لهذه العملية |
404 | المورد المطلوب غير موجود (مثل: قالب Template غير معرَّف) |
422 | خطأ في التحقق من صحة البيانات المُرسَلة — راجع حقل errors في الاستجابة |
429 | تجاوزت الحد المسموح به من الطلبات — انتظِر قبل إعادة المحاولة |
502 | فشل إرسال الرسالة عبر Meta API — قد يكون خللاً مؤقتاً من طرف واتساب |
POST /token
إصدار رمز وصول (Access Token) باستخدام بيانات اعتماد التطبيق. يُستخدم هذا الرمز في ترويسة
Authorization لجميع طلبات الواجهة البرمجية اللاحقة.
بيانات الطلب
| الحقل | النوع | الوضع | الوصف |
|---|---|---|---|
| client_id | string | مطلوب | معرّف التطبيق الفريد — يبدأ بـ tm_ |
| client_secret | string | مطلوب | المفتاح السري للتطبيق — احتفظ به في متغيرات البيئة ولا تُضمِّنه في الكود |
curl -X POST https://dygovil.com/api/v1/token \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "client_id": "tm_xxxxxxxxxxxxxxxx", "client_secret": "your_secret_here" }'
$response = Http::post('https://dygovil.com/api/v1/token', [ 'client_id' => 'tm_xxxxxxxxxxxxxxxx', 'client_secret' => 'your_secret_here', ]); $token = $response->json('access_token');
import requests res = requests.post('https://dygovil.com/api/v1/token', json={ 'client_id': 'tm_xxxxxxxxxxxxxxxx', 'client_secret': 'your_secret_here' }) token = res.json()['access_token']
{ "access_token": "...", "token_type": "Bearer", "scopes": ["notify","orders.write"] }{ "error": "invalid_client", "message": "بيانات الاعتماد غير صحيحة" }GET /test-connection
التحقق من صلاحية رمز الوصول واستعراض نطاقات الصلاحية المُسندة إلى التطبيق. يُفيد هذا الطلب في التشخيص والتأكد من صحة الاندماج قبل الإطلاق.
curl https://dygovil.com/api/v1/test-connection \
-H "Authorization: Bearer {your_token}"{ "status":"success", "app":{"name":"My App","tenant_id":42}, "scopes":{...} }GET /templates
استرجاع جميع قوالب الرسائل (Templates) المعتمدة من Meta والمتاحة لحسابك. لا يمكن إرسال رسالة Template إلا بعد ظهورها في هذه القائمة بحالة معتمدة.
{
"success": true,
"count": 2,
"data": [
{
"id": 5,
"name": "order_confirmed",
"language": "ar",
"category": "UTILITY",
"body": "مرحباً 1، تم تأكيد طلبك رقم 2 ✅",
"variables_count": 2
}
]
}POST /notify
إرسال قالب رسالة واتساب (Template) إلى أي رقم هاتف — حتى في غياب محادثة سابقة مع المستخدم.
يُستخدم لإرسال إشعارات المعاملات كتأكيد الطلبات وتذكيرات المواعيد وتنبيهات الشحن.
يستلزم نطاق الصلاحية: notify.
معاملات الطلب
| الحقل | النوع | الوضع | الوصف |
|---|---|---|---|
| phone | string | مطلوب | رقم الهاتف بالصيغة الدولية بدون + (مثال: 201012345678) |
| template_name | string | مطلوب | اسم القالب المعتمد كما يظهر في GET /templates |
| variables | array | اختياري | قيم المتغيرات الديناميكية مرتّبةً وفق ترتيب {{1}}، {{2}}، ... |
| language | string | اختياري | رمز اللغة (القيمة الافتراضية: ar) |
curl -X POST https://dygovil.com/api/v1/notify \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "phone": "201012345678", "template_name": "order_confirmed", "variables": ["Ahmed", "#1042", "150 ج.م"] }'
Http::withToken($token)->post('/api/v1/notify', [ 'phone' => '201012345678', 'template_name' => 'order_confirmed', 'variables' => ['Ahmed', '#1042', '150 ج.م'], ]);
requests.post('/api/v1/notify', headers={'Authorization': f'Bearer {token}'}, json={ 'phone': '201012345678', 'template_name': 'order_confirmed', 'variables': ['Ahmed', '#1042', '150 ج.م'] } )
{ "success": true, "message": "تم إرسال الإشعار بنجاح.", "phone": "201012345678", "template_used": "order_confirmed" }{ "error": "template_not_found", "message": "القالب غير موجود أو لم تُوافق عليه Meta بعد." }POST /orders
استقبال طلب قادم من نظامك الخارجي وحفظه في تومي، مع إمكانية إرسال إشعار واتساب للعميل
في الوقت ذاته. يستلزم نطاق الصلاحية: orders.write.
معاملات الطلب
| الحقل | النوع | الوضع | الوصف |
|---|---|---|---|
| order_ref | string | مطلوب | رقم الطلب الفريد في نظامك الخارجي |
| customer_phone | string | مطلوب | رقم هاتف العميل بالصيغة الدولية |
| customer_name | string | اختياري | اسم العميل الكامل |
| total | number | اختياري | إجمالي قيمة الطلب |
| currency | string | اختياري | رمز العملة وفق ISO 4217 (مثال: EGP، SAR، USD) |
| items | array | اختياري | قائمة المنتجات — كل عنصر: {name, qty, price} |
| status | string | اختياري | حالة الطلب: pending | confirmed | shipped | cancelled |
| notify_template | string | اختياري | اسم قالب الإشعار الذي سيُرسَل للعميل فور تسجيل الطلب |
| notify_variables | array | اختياري | قيم متغيرات القالب مرتّبةً وفق ترتيب ظهورها في النص |
| meta | object | اختياري | بيانات إضافية مخصصة تُحفظ مع الطلب للرجوع إليها لاحقاً |
curl -X POST https://dygovil.com/api/v1/orders \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "order_ref": "ORD-1042", "customer_phone": "201012345678", "customer_name": "Ahmed Ali", "total": 350.00, "currency": "EGP", "items": [ {"name": "تيشيرت أبيض", "qty": 2, "price": 175} ], "notify_template": "order_confirmed", "notify_variables": ["Ahmed", "ORD-1042"] }'
Http::withToken($token)->post('/api/v1/orders', [ 'order_ref' => 'ORD-1042', 'customer_phone' => '201012345678', 'total' => 350.00, 'notify_template' => 'order_confirmed', 'notify_variables' => ['Ahmed', 'ORD-1042'], ]);
{ "success": true, "order_id": 7, "order_ref": "ORD-1042", "notified": true }GET /orders
استرجاع قائمة الطلبات الخارجية المحفوظة في تومي مع دعم ترقيم الصفحات.
يستلزم نطاق الصلاحية: orders.read.
POST /customers
إضافة عميل جديد إلى نظام CRM في تومي، أو تحديث بياناته إن كان رقم هاتفه موجوداً مسبقاً.
يستلزم نطاق الصلاحية: customers.write.
معاملات الطلب
| الحقل | النوع | الوضع | الوصف |
|---|---|---|---|
| phone | string | مطلوب | رقم الهاتف — يُستخدم معرّفاً فريداً للعميل في النظام |
| name | string | اختياري | الاسم الكامل للعميل |
| string | اختياري | عنوان البريد الإلكتروني | |
| gender | string | اختياري | male | female | unknown |
| source | string | اختياري | مصدر اكتساب العميل (مثال: shopify، website، referral) |
| status | string | اختياري | مرحلة العميل في مسار المبيعات: lead | interested | customer |
curl -X POST https://dygovil.com/api/v1/customers \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "phone": "201012345678", "name": "Ahmed Ali", "email": "ahmed@example.com", "source": "shopify", "status": "customer" }'
{ "success": true, "action": "created", "customer": {"id":15,"name":"Ahmed Ali","phone":"201012345678"} }{ "success": true, "action": "updated", ... }GET /customers
استرجاع قائمة العملاء مع دعم البحث النصي والتصفية بالحالة وترقيم الصفحات.
يستلزم نطاق الصلاحية: customers.read.
مثال تطبيقي: ربط متجر إلكتروني
عند وصول طلب جديد من متجر Shopify عبر Webhook، أرسِله إلى تومي لحفظه وإشعار العميل فوراً عبر واتساب:
// معالج Webhook القادم من Shopify $order = $request->json()->all(); Http::withToken($token)->post('https://dygovil.com/api/v1/orders', [ 'order_ref' => $order['order_number'], 'customer_phone' => $order['phone'], 'customer_name' => $order['customer']['first_name'], 'total' => $order['total_price'], 'notify_template' => 'order_confirmed', 'notify_variables' => [$order['customer']['first_name'], $order['order_number']], ]);
مثال تطبيقي: تأكيد الحجوزات
عقب تسجيل حجز مؤكَّد في نظامك، أرسِل قالب الإشعار مباشرةً إلى العميل دون الحاجة إلى محادثة مسبقة معه:
Http::withToken($token)->post('https://dygovil.com/api/v1/notify', [ 'phone' => $booking->customer_phone, 'template_name' => 'booking_confirmed', 'variables' => [ $booking->customer_name, $booking->service_name, $booking->date->format('Y-m-d H:i'), ], ]);
مثال تطبيقي: استيراد العملاء تلقائياً
عند إتمام المستخدم تسجيله في موقعك، أضِفه تلقائياً إلى نظام CRM في تومي كي يبدأ الذكاء الاصطناعي التفاعل معه فوراً:
// بعد إتمام تسجيل المستخدم في موقعك Http::withToken($token)->post('https://dygovil.com/api/v1/customers', [ 'phone' => $user->phone, 'name' => $user->name, 'email' => $user->email, 'source' => 'website_registration', 'status' => 'lead', ]);
🔐 Toome Auth — خدمة التحقق بكلمة مرور لمرة واحدة (OTP)
Toome Auth خدمةٌ مستقلة لإرسال رموز التحقق (OTP) عبر واتساب — وقريباً عبر الرسائل القصيرة (SMS). تُتيح للمطورين إضافة طبقة تحقق آمنة لأي تطبيق أو موقع إلكتروني في خطوات بسيطة. تدعم الخدمة مسارَي تكامل مختلفَين:
| مسار التكامل | الحالة المناسبة | مسار الطلب | آلية المصادقة |
|---|---|---|---|
| Type A — TenantApp | صاحب متجر أو تطبيق لديه اشتراك تومي نشط وفعَّل ميزة OTP | /api/v1/otp/* |
Bearer Token (عبر POST /token + نطاق otp) |
| Type B — Standalone OTP App | تطبيق مستقل مخصص للتحقق فقط دون الحاجة إلى اشتراك تومي | /api/auth/v1/otp/* |
Authorization: Bearer {api_key} + X-App-Secret |
يُغطي هذا القسم Type B (التطبيق المستقل). إن كنت تستخدم Type A، راجع قسم
المصادقة وتأكد من تفعيل نطاق otp.
مصادقة Toome Auth OTP
يتطلب كل طلب في هذا المسار إرفاق ترويستَين في HTTP headers: الأولى تحمل مفتاح API الخاص بتطبيقك، والثانية السر المشترك (App Secret) للتحقق من هويتك.
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx X-App-Secret: your_app_secret_here
يمكن الاطلاع على API Key و App Secret من لوحة المطورين ←
تطبيقات OTP ← عرض المفاتيح. يشترط أن يكون التطبيق في حالة active
(بعد مراجعته وقبوله من فريق الإدارة).
POST /api/auth/v1/otp/send
إرسال رمز تحقق OTP إلى رقم هاتف عبر واتساب. يُعيد الطلب request_id فريداً يُستخدم في الخطوات اللاحقة.
POST /api/auth/v1/otp/send
Authorization: Bearer sk_live_xxxx
X-App-Secret: your_secret
{
"phone": "201012345678",
"channel": "whatsapp",
"locale": "ar",
"meta": { "order_id": "ORD-789" }
}{
"success": true,
"request_id": "req_01JXXXXXXXXXXXXXXXXXXX",
"expires_at": "2026-06-12T14:05:00Z",
"cooldown_seconds": 60
}$res = Http::withHeaders([
'Authorization' => 'Bearer ' . $apiKey,
'X-App-Secret' => $appSecret,
])->post('https://dygovil.com/api/auth/v1/otp/send', [
'phone' => $user->phone,
'locale' => 'ar',
]);
$requestId = $res->json('request_id');| الحقل | النوع | الوصف |
|---|---|---|
phone * | string | رقم الهاتف بصيغة E.164 دون الرمز + (مثال: 201012345678) |
channel | string | قناة الإرسال: whatsapp (افتراضي) | sms |
locale | string | لغة رسالة OTP: ar (افتراضي) | en |
meta | object | بيانات سياقية اختيارية تُعاد في Webhook عند نجاح التحقق (مثال: رقم الطلب، معرّف الجلسة) |
POST /api/auth/v1/otp/verify
التحقق من الرمز الذي أدخله المستخدم. عند النجاح، يُبطَل الرمز فوراً ولا يمكن إعادة استخدامه.
يُرجع الطلبُ success: true مع بيانات المستخدم وأي بيانات meta
أُرفقت عند الإرسال.
{
"request_id": "req_01JXXXXXXXXXXXXXXXXXXX",
"code": "482917"
}// نجاح
{
"success": true,
"phone": "201012345678",
"meta": { "order_id": "ORD-789" },
"verified_at": "2026-06-12T14:03:22Z"
}
// كود خاطئ
{
"success": false,
"error_code": "INVALID_CODE",
"attempts_remaining": 2
}$res = Http::withHeaders([
'Authorization' => 'Bearer ' . $apiKey,
'X-App-Secret' => $appSecret,
])->post('https://dygovil.com/api/auth/v1/otp/verify', [
'request_id' => $requestId,
'code' => $userInput,
]);
if ($res->json('success')) {
// تمَّ التحقق — أكمِل تسجيل المستخدم أو منحه الصلاحية
}POST /api/auth/v1/otp/resend
إعادة إرسال رمز OTP للرقم ذاته باستخدام request_id الأصلي.
يشترط انتهاء مهلة الانتظار بين الإرساليات (افتراضياً 60 ثانية) قبل قبول هذا الطلب.
{
"request_id": "req_01JXXXXXXXXXXXXXXXXXXX"
}
إذا استُدعي هذا الطلب قبل انتهاء مهلة الانتظار، يُعيد الخادم الخطأ COOLDOWN_ACTIVE
مصحوباً بحقل retry_after يُشير إلى عدد الثواني المتبقية.
DELETE /api/auth/v1/otp/{request_id}
إلغاء طلب OTP وإبطال الرمز المرتبط به فوراً. يُستخدم عندما يتحقق المستخدم بوسيلة بديلة، أو يتراجع عن العملية، أو تنتهي جلسته قبل إتمام التحقق.
DELETE /api/auth/v1/otp/req_01JXXXXXXXXXXXXXXXXXXX
GET /api/auth/v1/otp/logs
استرجاع سجل تاريخي لطلبات OTP مع دعم التصفية بالهاتف وحالة الطلب وترقيم الصفحات. مفيد لأغراض المراجعة والتدقيق.
GET /api/auth/v1/otp/logs?status=verified&per_page=20&page=1
{
"data": [
{
"request_id": "req_01JXXX",
"phone": "201012345678",
"channel": "whatsapp",
"status": "verified",
"created_at": "2026-06-12T14:00:00Z"
}
],
"meta": { "total": 148, "per_page": 20, "current_page": 1 }
}
القيم المتاحة للتصفية بحقل status:
pending (قيد الانتظار) |
verified (تم التحقق) |
expired (انتهت الصلاحية) |
cancelled (ملغى) |
failed (فشل الإرسال)
GET /api/auth/v1/apps/stats
استرجاع إحصاءات أداء تطبيق OTP خلال الثلاثين يوماً الأخيرة، مصنَّفةً حسب القناة.
{
"total_sent": 1420,
"total_verified": 1184,
"verify_rate": "83.4%",
"today": 47,
"by_channel": {
"whatsapp": { "sent": 1400, "verified": 1170 },
"sms": { "sent": 20, "verified": 14 }
}
}أرقام الاختبار (Test Phones)
تُتيح لك هذه الميزة تسجيل ما يصل إلى 10 أرقام هواتف مع رموز تحقق ثابتة لأغراض الاختبار. عند إرسال OTP إلى أي من هذه الأرقام:
- لا تُرسَل أي رسالة واتساب فعلية.
- لا يُستهلَك أي رصيد أو توكن.
- يُعاد الرمز الثابت الذي حددته مسبقاً مخزَّناً في Redis.
- تعمل الميزة في كلا الوضعَين: Live وSandbox.
يمكن إدارة هذه الأرقام من لوحة المطورين ← تطبيقات OTP ← عرض التطبيق ← قسم أرقام الاختبار.
الاستجابة تتضمن حقل test_phone: true في كل طلب موجَّه إلى رقم اختبار.
رموز أخطاء OTP
تُعيد واجهة OTP رمز خطأ نصياً محدداً (error_code) يُسهِّل التعامل الآلي مع حالات الخطأ المختلفة.
| error_code | رمز HTTP | السبب والمعالجة المقترحة |
|---|---|---|
MISSING_CREDENTIALS | 401 | ترويسة Authorization أو X-App-Secret غير مُرفَقة في الطلب |
INVALID_API_KEY | 401 | مفتاح API غير موجود في النظام — تحقق من صحة المفتاح |
INVALID_SECRET | 401 | App Secret غير مطابق — راجع بيانات التطبيق في لوحة المطورين |
APP_PENDING_REVIEW | 403 | التطبيق لا يزال قيد المراجعة ولم يُفعَّل بعد |
APP_REJECTED | 403 | طلب التطبيق مرفوض — تواصَل مع الدعم الفني للاستفسار |
RATE_LIMITED | 429 | تجاوز الحد المسموح به (60 طلباً / دقيقة لكل تطبيق) |
COOLDOWN_ACTIVE | 429 | لم تنقضِ مهلة الانتظار بين الإرساليات — راجع retry_after في الاستجابة |
INVALID_CODE | 422 | الرمز المُدخَل غير صحيح — راجع attempts_remaining لمعرفة المحاولات المتبقية |
OTP_EXPIRED | 410 | انتهت صلاحية رمز OTP — أرسِل طلباً جديداً باستخدام POST /otp/send |
OTP_ALREADY_VERIFIED | 409 | سبق التحقق من هذا الرمز — لا يمكن استخدامه مجدداً |
NOT_FOUND | 404 | المعرّف request_id غير موجود أو انتهت صلاحيته في قاعدة البيانات |