العنوان الأساسي
كل الطلبات بصيغة JSON عبر HTTPS إلى العنوان التالي:
https://api.message-hub.cloud/api/v1المصادقة
كل طلب يحمل مفتاحك في الترويسة Authorization. تجد المفتاح في لوحة التحكم، ويظهر مرة واحدة فقط عند إنشائه، فاحفظه في مكان آمن ولا تضعه في كود يصل إلى المتصفح أو التطبيق.
Authorization: Bearer mh_live_xxxxxxxxxxxxxxxxxxxxxxxxأرقام الهواتف تُقبل بالصيغة المحلية (07701234567) أو الدولية (9647701234567).
المسارات
| الطريقة | المسار | الوصف |
|---|---|---|
| POST | /otp/send | إرسال رمز OTP إلى رقم واتساب |
| POST | /otp/verify | التحقق من رمز أدخله المستخدم |
| GET | /otp/{id} | حالة رمز OTP |
| POST | /messages | إرسال رسالة قالب أو نص |
| GET | /messages | قائمة رسائلك (status، to، per_page) |
| GET | /messages/{id} | حالة رسالة واحدة |
| GET | /account | الرصيد والأسعار ورقم الإرسال |
إرسال رمز OTP
نولّد الرمز ونرسله بقالب التحقق المعتمد. احتفظ بid لاستخدامه في التحقق.
| الحقل | الوصف |
|---|---|
phoneإلزامي | رقم الزبون. |
lengthاختياري | طول الرمز من 4 إلى 10 (الافتراضي 6). |
expires_inاختياري | مدة الصلاحية بالدقائق من 1 إلى 60 (الافتراضي 5). |
codeاختياري | رمزك الخاص (4–10 أرقام) إن أردت توليده بنفسك. |
referenceاختياري | معرّفك للطلب (حتى 100 حرف) — يجعل إعادة المحاولة آمنة. |
curl -X POST https://api.message-hub.cloud/api/v1/otp/send \
-H "Authorization: Bearer $MESSAGEHUB_KEY" \
-H "Content-Type: application/json" \
-d '{"phone": "07701234567", "length": 6, "expires_in": 5, "reference": "login-123"}'const res = await fetch('https://api.message-hub.cloud/api/v1/otp/send', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MESSAGEHUB_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ phone: '07701234567', length: 6, expires_in: 5, reference: 'login-123' }),
})
const { data } = await res.json()
const otpId = data.id$res = Http::withToken(env('MESSAGEHUB_KEY'))
->post('https://api.message-hub.cloud/api/v1/otp/send', [
'phone' => '07701234567',
'length' => 6,
'expires_in' => 5,
'reference' => 'login-123',
]);
$otpId = $res->json('data.id');201 Created
{
"data": {
"id": "9d3c8f2e-…",
"phone": "9647701234567",
"status": "pending",
"expires_at": "2026-11-05T21:35:00+03:00",
"message": { "id": "…", "status": "sent", "cost": …, "currency": "IQD" }
},
"balance": …
}التحقق من الرمز
أرسل id (أو الرقم) مع الرمز الذي أدخله المستخدم. الرد 200 عند الصحة و422 مع السبب عند الخطأ.
curl -X POST https://api.message-hub.cloud/api/v1/otp/verify \
-H "Authorization: Bearer $MESSAGEHUB_KEY" \
-H "Content-Type: application/json" \
-d '{"id": "9d3c8f2e-…", "code": "482913"}'const res = await fetch('https://api.message-hub.cloud/api/v1/otp/verify', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MESSAGEHUB_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ id: otpId, code: userInput }),
})
const { data } = await res.json()
if (data.valid) signIn()$res = Http::withToken(env('MESSAGEHUB_KEY'))
->post('https://api.message-hub.cloud/api/v1/otp/verify', [
'id' => $otpId,
'code' => $request->input('code'),
]);
if ($res->json('data.valid')) {
Auth::login($user);
}200 OK
{ "data": { "valid": true, "reason": null, "otp": { … } } }
422 Unprocessable Entity
{ "data": { "valid": false, "reason": "invalid_code", "otp": { … } } }أسباب الرفض: invalid_code (رمز خاطئ)، expired (انتهت صلاحيته)، too_many_attempts (محاولات كثيرة)، already_verified (تم التحقق منه سابقاً).
curl https://api.message-hub.cloud/api/v1/otp/9d3c8f2e-… \
-H "Authorization: Bearer $MESSAGEHUB_KEY"رسائل القوالب
أرسل إشعاراً بقالب واتساب معتمد مع متغيراته. الفئة utility للإشعارات وmarketing للتسويق.
curl -X POST https://api.message-hub.cloud/api/v1/messages \
-H "Authorization: Bearer $MESSAGEHUB_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "07701234567",
"template": "order_update",
"language": "ar",
"variables": ["1045", "غداً"],
"category": "utility",
"reference": "order-1045-shipped"
}'curl https://api.message-hub.cloud/api/v1/messages/{id} -H "Authorization: Bearer $MESSAGEHUB_KEY"
curl "https://api.message-hub.cloud/api/v1/messages?status=delivered&per_page=50" -H "Authorization: Bearer $MESSAGEHUB_KEY"حالات الرسالة: queued (بالانتظار)، sent (أُرسلت)، delivered (وصلت)، read (قُرئت)، failed (فشلت).
الرصيد والأسعار
يعيد اسم حسابك ورصيدك بالدينار وأسعار كل فئة ورقم الإرسال.
curl https://api.message-hub.cloud/api/v1/account -H "Authorization: Bearer $MESSAGEHUB_KEY"
{
"data": {
"name": "…",
"balance": …,
"currency": "IQD",
"prices": { … },
"sender": { "phone_number": "…", "display_name": "…", "shared": true }
}
}إعادة المحاولة الآمنة (reference)
إذا أرسلت نفس reference مرتين تحصل على نفس الرسالة دون إرسال جديد ودون خصم جديد. استخدمه دائماً عند إعادة المحاولة بعد انقطاع الشبكة.
الرصيد والاسترداد
- رصيد غير كافٍ ← 402 insufficient_balance ولا يُرسل شيء.
- رفضت Meta الرسالة ← 502 send_failed ويعود المبلغ إلى رصيدك فوراً. وإن أبلغت Meta بفشلها لاحقاً يعود المبلغ أيضاً.
402 Payment Required
{ "message": "Insufficient balance.", "code": "insufficient_balance" }إشعارات الحالة (Webhook)
عند تغيّر حالة رسالة نرسل طلب POST إلى رابط Webhook الذي تضبطه في لوحة التحكم.
POST https://your-app.example/webhooks/messagehub
Content-Type: application/json
X-MessageHub-Signature: sha256=<hex hmac_sha256(raw_body, webhook_secret)>
{
"event": "message.status",
"data": {
"id": "…",
"reference": "login-123",
"to": "9647701234567",
"status": "delivered",
"category": "authentication",
"cost": …,
"refunded": false,
"error": null,
"updated_at": "2026-11-05T21:31:04+03:00"
}
}كل طلب يحمل الترويسة X-MessageHub-Signature وقيمتها sha256= متبوعة بـHMAC-SHA256 للجسم الخام بسرّ Webhook الخاص بك. احسب التوقيع وقارنه بمقارنة ثابتة الزمن قبل الوثوق بالطلب.
import { createHmac, timingSafeEqual } from 'node:crypto'
function isValid(rawBody, header, secret) {
const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex')
const a = Buffer.from(expected)
const b = Buffer.from(header ?? '')
return a.length === b.length && timingSafeEqual(a, b)
}$expected = 'sha256='.hash_hmac('sha256', $request->getContent(), $secret);
if (! hash_equals($expected, (string) $request->header('X-MessageHub-Signature'))) {
abort(401);
}رموز الأخطاء
كل خطأ يعود بـJSON يحتوي message و code.
| 401 | invalid_api_key | المفتاح مفقود أو غير صحيح. |
| 403 | account_suspended | الحساب موقوف. |
| 403 | ability_missing | المفتاح لا يملك صلاحية هذا المسار (otp أو messages). |
| 403 | ip_not_allowed | عنوان IP غير مسموح لهذا المفتاح. |
| 402 | insufficient_balance | الرصيد لا يكفي؛ لم يُرسل شيء. |
| 422 | validation | بيانات الطلب غير صحيحة. |
| 429 | rate_limited | طلبات كثيرة؛ أعد المحاولة بعد قليل. |
| 502 | send_failed | رفضت Meta الرسالة والمبلغ عاد إلى رصيدك. |
| 503 | no_sender · no_otp_template | لا يوجد رقم إرسال أو قالب OTP مفعّل بعد. |