اربط نظامك بوامي
وامي يوصل رسائل نظامك إلى جوال المستخدم كإشعار، ويعيد إليك ردوده. الواجهة JSON فوق HTTPS، وتعمل من أي لغة برمجة.
- افتح شركتكمن لوحة الشركة، وخذ مفتاحك.
- اربط المستخدمزر «استقبل التنبيهات على وامي» في حسابه عندك.
- أرسلطلب واحد عند كل حدث.
- استقبل الردوداختياري: لنظامك أو لفريقك في وامي.
العنوان والمفتاح
كل الطلبات إلى هذا العنوان، ومعها المفتاح في الترويسة:
https://wamyapp.com/api/v1/ Authorization: Bearer wmy_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxx Content-Type: application/json
المفتاح سرّي ويبقى في خادمك فقط. لا تضعه في صفحة ويب ولا في تطبيق جوال. الأخطاء ترجع بصيغة JSON فيها error و message.
أول رسالة في 5 دقائق
- افتح لوحة الشركة وأنشئ شركتك. يظهر لك المفتاح مرة واحدة: ضعه في متغير بيئة اسمه
WAMY_KEY. - في اللوحة اضغط «أرسل لي رسالة تجريبية»: تصلك في وامي فترى شكلها عند العميل، وتفعّل التنبيهات على جوالك.
- اطلب رابط ربط لحسابك أنت (القسم التالي) وافتحه، فيرتبط رقمك عندك بحسابك في وامي.
- أرسل بالمثال المجاور، وبدّل
42برقمك.
أرسل
curl -X POST https://wamyapp.com/api/v1/send.php \
-H "Authorization: Bearer $WAMY_KEY" \
-H "Content-Type: application/json" \
-d '{"to": {"external_id": "42"},
"title": "Order confirmed",
"text": {"ar": "تم تأكيد طلبك رقم *5521*", "en": "Order *5521* is confirmed"},
"ref": "order-5521-confirmed"}'<?php
// plain cURL: no library needed (or use WamyClient.php, see the downloads)
$ch = curl_init('https://wamyapp.com/api/v1/send.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('WAMY_KEY'), 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'to' => ['external_id' => '42'],
'title' => 'Order confirmed',
'text' => ['ar' => 'تم تأكيد طلبك رقم *5521*', 'en' => 'Order *5521* is confirmed'],
'ref' => 'order-5521-confirmed',
], JSON_UNESCAPED_UNICODE),
]);
$result = json_decode(curl_exec($ch), true);// Node 18+ (fetch is built in)
const res = await fetch("https://wamyapp.com/api/v1/send.php", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.WAMY_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
to: { external_id: "42" },
title: "Order confirmed",
text: { ar: "تم تأكيد طلبك رقم *5521*", en: "Order *5521* is confirmed" },
ref: "order-5521-confirmed",
}),
});
console.log(await res.json());import os, requests
r = requests.post(
"https://wamyapp.com/api/v1/send.php",
headers={"Authorization": "Bearer " + os.environ["WAMY_KEY"]},
json={
"to": {"external_id": "42"},
"title": "Order confirmed",
"text": {"ar": "تم تأكيد طلبك رقم *5521*", "en": "Order *5521* is confirmed"},
"ref": "order-5521-confirmed",
},
timeout=10,
)
print(r.status_code, r.json())قواعد الشركات المسجّلة بنفسها
أي أحد يستطيع فتح شركة في وامي، لذلك تحمي القواعد التالية الناس من الرسائل غير المرغوبة، وتحمي حساباتهم. هي مبنية في الواجهة ولا يمكن تجاوزها.
- تراسل من وافق فقطمن ربط حسابه بشركتك عبر رابط الربط، أو بدأ محادثة معك من رابط التواصل. إرسال رسالة لبريد لم يربط ولم يراسلك يرجع
404 recipient_not_found. - رابط الربط لا يدخل أحدًا بدلًا عنهمن يفتحه يسجّل الدخول إلى وامي ببريده هو (رمز أو Google)، ثم يُربط حسابه. لذلك لا فائدة من إرسال
emailفي طلب الربط: يُتجاهل. - لا بريد من عنواننا
email_fallbackوcreateغير متاحين للشركات المسجّلة بنفسها. - حد الطلباتحتى 120 طلبًا في الدقيقة لكل شركة.
- الحساب غير موثّق في البدايةاطلب العلامة الخضراء من لوحة الشركة بعد أن تكمل بياناتك.
- من يحظرك لا تصله رسائلك
409 blocked_by_user
1. ربط المستخدم
/api/v1/link.phpPOSTتربط الرابط بزر «استقبل التنبيهات على وامي» داخل حساب المستخدم عندك. يفتحه المستخدم فيدخل وامي ويرتبط رقمه عندك بحسابه. الرابط يعمل مرة واحدة ولمدة 30 دقيقة (أو أيامًا للدعوات المطبوعة).
| الحقل | المعنى |
|---|---|
external_idمطلوب | رقم المستخدم عندك. نصٌّ حتى 120 حرفًا. |
days | من 1 إلى 60: يبقى الرابط صالحًا أيامًا بدل دقائق. لدعوة مطبوعة، مثل رمز QR على ورقة. |
sender | اربطه بمحادثة جهة معينة (انظر «عدة جهات»). |
email, name | تعمل مع تطبيقاتنا فقط. في الشركات المسجّلة بنفسها تُتجاهل. |
ما بعد الربط: أرسل بالرقم نفسه ("to": {"external_id": "42"}).
curl -X POST https://wamyapp.com/api/v1/link.php \
-H "Authorization: Bearer $WAMY_KEY" \
-H "Content-Type: application/json" \
-d '{"external_id": "42", "email": "customer@example.com", "name": "Salem"}'
# -> {"url": "https://wamyapp.com/link.php?t=...", "expires_at": "..."}<?php
$ch = curl_init('https://wamyapp.com/api/v1/link.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('WAMY_KEY'), 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode(['external_id' => (string) $user->id, 'email' => $user->email, 'name' => $user->name]),
]);
$url = json_decode(curl_exec($ch), true)['url'];
header('Location: ' . $url); // the button "Get notifications on Wamy"const res = await fetch("https://wamyapp.com/api/v1/link.php", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.WAMY_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ external_id: String(user.id), email: user.email, name: user.name }),
});
const { url } = await res.json();
response.redirect(url); // the button "Get notifications on Wamy"import os, requests
r = requests.post(
"https://wamyapp.com/api/v1/link.php",
headers={"Authorization": "Bearer " + os.environ["WAMY_KEY"]},
json={"external_id": str(user.id), "email": user.email, "name": user.name},
timeout=10,
)
url = r.json()["url"] # open it from the button "Get notifications on Wamy"201
{"url": "https://wamyapp.com/link.php?t=…", "expires_at": "2026-10-26T10:30:00+00:00"}2. إرسال رسالة
/api/v1/send.phpPOST| الحقل | المعنى |
|---|---|
toمطلوب | المستقبل: {"external_id": "42"} |
textمطلوب | النص، أو {"ar": "…", "en": "…"} ليرى كل مستخدم لغته. حتى 4096 حرفًا. يدعم *عريض* و _مائل_ والروابط. |
title | سطر عريض فوق النص (اختياري). |
image_url | صورة برابط https (اختياري). |
buttons | حتى 3 أزرار، نص الزر حتى 30 حرفًا: رابط {"type":"url","label":"…","url":"https://…"} أو رد سريع {"type":"reply","label":"…","payload":"…"}. |
ref | رقمك المرجعي. نفس الرقم مرتين = نفس الرسالة، فإعادة المحاولة آمنة. |
file | ملف مرفق (انظر «المرفقات»). |
sender | أرسل باسم جهة (انظر «عدة جهات»). |
pushed_devices: 0 تعني أن المستخدم لم يفعّل التنبيهات: الرسالة محفوظة له وتظهر حين يفتح وامي، لكنها لن تصله كإشعار.
curl -X POST https://wamyapp.com/api/v1/send.php \
-H "Authorization: Bearer $WAMY_KEY" \
-H "Content-Type: application/json" \
-d '{"to": {"external_id": "42"},
"title": "Order confirmed",
"text": {"ar": "تم تأكيد طلبك رقم *5521*", "en": "Order *5521* is confirmed"},
"ref": "order-5521-confirmed"}'<?php
// plain cURL: no library needed (or use WamyClient.php, see the downloads)
$ch = curl_init('https://wamyapp.com/api/v1/send.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('WAMY_KEY'), 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'to' => ['external_id' => '42'],
'title' => 'Order confirmed',
'text' => ['ar' => 'تم تأكيد طلبك رقم *5521*', 'en' => 'Order *5521* is confirmed'],
'ref' => 'order-5521-confirmed',
], JSON_UNESCAPED_UNICODE),
]);
$result = json_decode(curl_exec($ch), true);// Node 18+ (fetch is built in)
const res = await fetch("https://wamyapp.com/api/v1/send.php", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.WAMY_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
to: { external_id: "42" },
title: "Order confirmed",
text: { ar: "تم تأكيد طلبك رقم *5521*", en: "Order *5521* is confirmed" },
ref: "order-5521-confirmed",
}),
});
console.log(await res.json());import os, requests
r = requests.post(
"https://wamyapp.com/api/v1/send.php",
headers={"Authorization": "Bearer " + os.environ["WAMY_KEY"]},
json={
"to": {"external_id": "42"},
"title": "Order confirmed",
"text": {"ar": "تم تأكيد طلبك رقم *5521*", "en": "Order *5521* is confirmed"},
"ref": "order-5521-confirmed",
},
timeout=10,
)
print(r.status_code, r.json())201
{"id": 812, "status": "sent", "pushed_devices": 2, "emailed": false,
"created_at": "2026-10-26T09:41:00+00:00", "delivered_at": null, "read_at": null,
"ref": "order-5521-confirmed", "duplicate": false}{"to": {"external_id": "42"},
"title": "Appointment tomorrow",
"text": {"ar": "موعدك غدًا الساعة 10:00", "en": "Your appointment is tomorrow at 10:00"},
"image_url": "https://example.com/map.png",
"buttons": [
{"type": "url", "label": {"ar": "الموقع", "en": "Location"}, "url": "https://maps.example.com/clinic"},
{"type": "reply", "label": {"ar": "سأحضر", "en": "I will come"}, "payload": "confirm_1042"}
],
"ref": "appt-1042-reminder"}3. حالة الرسالة والمستخدم
قبل رسالة مهمة (رمز دخول، تأكيد دفع) اسأل: هل سيصله تنبيه؟ وبعدها اسأل: هل وصلت؟ فإن لم تصل تستعمل قناة أخرى.
/api/v1/user.php?external_id=42GETlinked · joined · notifications (عدد الأجهزة التي تستقبل التنبيهات) · blocked · muted · last_seen_at
/api/v1/message.php?ref=order-5521-confirmedGETsent— محفوظةdelivered— وصلت إلى جهازread— فتحها المستخدم
تقبل id أو ref.
curl "https://wamyapp.com/api/v1/user.php?external_id=42" -H "Authorization: Bearer $WAMY_KEY"
# {"linked": true, "joined": true, "notifications": 2, "blocked": false, "muted": false, ...}
curl "https://wamyapp.com/api/v1/message.php?ref=order-5521-confirmed" -H "Authorization: Bearer $WAMY_KEY"
# {"id": 812, "status": "delivered", "pushed_devices": 2, ...}4. استقبال الردود
ضع عنوان استقبال (Webhook) في لوحة الشركة وفعّل «يستطيع العملاء أن يكتبوا إلينا». كل رد أو ضغطة على زر رد سريع يصل إلى عنوانك هكذا:
POST https://your-app.example.com/wamy
X-Wamy-Timestamp: 1792800000
X-Wamy-Signature: sha256=…
{"event": "message", "id": 913, "app": "your-code",
"from": {"external_id": "42", "email": null, "name": "Salem"},
"text": "Great", "payload": "confirm_1042",
"reply_to": {"id": 905, "ref": "appt-1042-reminder"},
"file": null, "created_at": "2026-10-26T09:50:11+00:00"}- ردّ برمز نجاح من 200 إلى 299 خلال 6 ثوانٍ، وإلا نعيد المحاولة 5 مرات خلال ساعتين.
- العنوان يجب أن يكون https عامًا يمكن الوصول إليه من الإنترنت. لا نتصل بعناوين الشبكات الداخلية.
- من لم يربط حسابه (جاء من رابط التواصل) يصلك
"external_id": nullوبريده. - بعد أن تقرأ الرد استدع
POST /api/v1/read.php {"id": 913}لتظهر للمستخدم العلامتان الزرقاوان.
تحقّق من التوقيع دائمًا
التوقيع هو HMAC-SHA256 للنص timestamp + "." + raw body بسرّ التوقيع الذي تجده في لوحة الشركة. ارفض الطلب إن مضى على الطابع الزمني أكثر من 5 دقائق.
<?php
$raw = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_WAMY_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_WAMY_SIGNATURE'] ?? '';
$mine = 'sha256=' . hash_hmac('sha256', $ts . '.' . $raw, getenv('WAMY_WEBHOOK_SECRET'));
if (!ctype_digit($ts) || abs(time() - (int) $ts) > 300 || !hash_equals($mine, $sig)) { http_response_code(401); exit; }
$event = json_decode($raw, true); // {"event": "message", "id": 913, "from": {...}, "text": "..."}
http_response_code(204); // any 2xx = receivedimport crypto from "node:crypto";
// Express: app.post("/wamy", express.raw({ type: "*/*" }), handler)
function verify(raw, ts, sig, secret) {
if (!/^\d+$/.test(ts) || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const mine = "sha256=" + crypto.createHmac("sha256", secret).update(ts + "." + raw).digest("hex");
return mine.length === sig.length && crypto.timingSafeEqual(Buffer.from(mine), Buffer.from(sig));
}
// verify(req.body, req.get("X-Wamy-Timestamp"), req.get("X-Wamy-Signature"), process.env.WAMY_WEBHOOK_SECRET)import hashlib, hmac, time
def verify(raw: bytes, ts: str, sig: str, secret: str) -> bool:
if not ts.isdigit() or abs(time.time() - int(ts)) > 300:
return False
mine = "sha256=" + hmac.new(secret.encode(), ts.encode() + b"." + raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(mine, sig)
# verify(request.get_data(), request.headers["X-Wamy-Timestamp"], request.headers["X-Wamy-Signature"], SECRET)رابط التواصل: الناس يبدؤون المحادثة
لكل شركة رابط تواصل. ضعه خلف زر «راسلنا على وامي» في موقعك، أو اطبعه رمز QR. من يفتحه يدخل ببريده إن لزم، ثم تُفتح له محادثة معك. لا تحتاج مفتاحًا ولا برمجة: تجده جاهزًا في لوحة الشركة.
/api/v1/contact.phpPOSTلتأخذه من الكود (أو لكل جهة ترسل باسمها): {"sender": {"id": "school-12", "name": "…"}}
openصحيحة حين تُقبل الردود ويوجد في الفريق من يرى الزوار. بدونها لا يعمل الرابط.- حماية من الإغراق: قبل أن تردّ أول مرة يرسل الشخص 5 رسائل في الساعة على الأكثر.
curl -X POST https://wamyapp.com/api/v1/contact.php -H "Authorization: Bearer $WAMY_KEY"
# {"url": "https://wamyapp.com/start.php?to=your-code", "open": true}<a href="https://wamyapp.com/start.php?to=your-code" target="_blank" rel="noopener"> Message us on Wamy </a>
فريق الردود
من يرد باسم شركتك داخل وامي: موظف استقبال، معلم، فريق مبيعات. يدخل وامي فيجد تبويب «الردود» فيه كل من كتب إليكم. أسهل طريقة: أضفه ببريده من لوحة الشركة. ومن الكود:
/api/v1/agent.phpPOST| الحقل | المعنى |
|---|---|
external_idمطلوب | الشخص عندك. يجب أن يكون قد ربط حسابه أولًا. |
title | الاسم الظاهر للناس على ردوده (الافتراضي: اسمه). |
people | قائمة أرقام: يرى محادثات هؤلاء فقط (معلم وأولياء أمور صفّه). بدونها يرى الكل. |
scope | "guests": يرى الزوار فقط، من ليسوا مستخدمين عندك بعد. |
active | false يزيله من الفريق. |
curl -X POST https://wamyapp.com/api/v1/agent.php \
-H "Authorization: Bearer $WAMY_KEY" -H "Content-Type: application/json" \
-d '{"external_id": "u-15", "title": "Ms Huda, Grade 5 teacher", "people": ["p-101", "p-102"]}'المرفقات: صور ومستندات
الرسالة تحمل ملفًا واحدًا: صورة (jpg، png، webp) أو مستندًا (pdf، doc/docx، xls/xlsx، ppt/pptx، txt، csv)، حتى 10 ميجابايت. يُعرف نوع الملف من محتواه لا من اسمه، وتُعاد رسم الصور فتسقط منها بيانات الكاميرا والموقع.
ملف يرسله المستخدم يصل إلى عنوان الاستقبال في الحقل "file": {"url", "name", "mime", "size"}. الرابط موقّع وصالح 7 أيام، فنزّل الملف إن احتجته.
{"to": {"external_id": "42"}, "text": "Your invoice",
"file": {"name": "invoice.pdf", "data": "<base64 of the file>"}}عدة جهات بمفتاح واحد
منصة تخدم عدة مدارس أو فروع أو عيادات؟ أضف الحقل sender عند الإرسال وعند طلب الربط، فتظهر كل جهة للمستخدم محادثة مستقلة باسمها وشعارها، وتُنشأ عند أول استعمال. المستخدمون مربوطون بشركتك: رقمهم عندك واحد في كل الجهات.
- الردود تصل إلى عنوانك ومعها
"sender": {"id": "school-12"}. - حالة المستخدم في جهة معينة:
user.php?external_id=42&sender_id=school-12. - لكل جهة رابط تواصل خاص: يطلبه نظامك من
contact.php.
"sender": {"id": "school-12",
"name": {"ar": "مدرسة النور", "en": "Al Noor School"},
"logo_url": "https://example.com/logo.png", "color": "#017672"}الأخطاء والحدود
| الرمز | المعنى |
|---|---|
400 bad_json | الجسم ليس JSON صحيحًا. |
401 unauthorized | المفتاح خطأ، أو الشركة موقوفة. |
404 recipient_not_found | المستخدم لم يربط حسابه بعد، أو لم يراسلك. |
409 blocked_by_user | المستخدم حظر شركتك. |
413 file_too_big | الملف أكبر من 10 ميجابايت. |
422 text_required | لا نص ولا عنوان ولا صورة ولا ملف. |
422 text_too_long | النص أطول من 4096 حرفًا. |
422 buttons_invalid | أكثر من 3 أزرار، أو نص زر أطول من 30 حرفًا، أو رابط غير صحيح. |
422 image_must_be_https | رابط الصورة يجب أن يبدأ بـ https. |
429 rate_limited | تجاوزت حد الطلبات في الدقيقة. الرد يذكر الحد، وأعد المحاولة بعد قليل. |
نصائح
- أرسل
refمع كل رسالة، فتكون إعادة المحاولة بعد انقطاع الشبكة آمنة. - لا تُوقف عمل نظامك إن تعذّر الإرسال: سجّل الخطأ وتابع.
- للمهم جدًا (رمز دخول) اسأل حالة المستخدم أولًا، واحتفظ بقناة بديلة.
- لا تراسل إلا من ربط حسابه أو راسلك: هذا ما نفرضه، وهذا ما يريده الناس.
التنزيلات
لا تحتاج مكتبة: كل ما فوق يعمل بطلب HTTP عادي. لمن يستعمل PHP ملف واحد يغلّف الطلبات ويتحقق من توقيع الردود.
WamyClient.phprequire 'WamyClient.php';
$wamy = new WamyClient('https://wamyapp.com', getenv('WAMY_KEY'));
$url = $wamy->linkUrl((string) $user->id); // 1. link
$wamy->send(['external_id' => (string) $user->id], // 2. send
['ar' => 'تم تأكيد طلبك', 'en' => 'Your order is confirmed'],
['ref' => 'order-5521-confirmed']);
$ok = WamyClient::verifyWebhook($raw, $ts, $sig, $secret); // 4. verify a reply