انتقل إلى المحتوى

للمطوّرين

نداءان بينك وبين مستخدم موثّق.

أرسل الرمز بطلب verify/start، وتحقق منه بطلب verify/check.

توكيد للتحقق واجهة API لرموز OTP في السعودية.

بوابة المطوّرين الكاملةأدلة، ومرجع تفاعلي تستدعيه من الصفحة، وكل صفحة بصيغة Markdown، وخادم MCP لمساعدك البرمجي، بالإنجليزية.فتح docs.tawked.com

البداية السريعة

  1. 01

    أنشئ مفتاح API

    أنشئ مفتاح ⁦tk_test_⁩ من تبويب «المفاتيح» في تطبيقك. يعمل قبل اعتماد التطبيق.

  2. 02

    أرسل الرمز

    أرسل طلب POST إلى ⁦/v1/verify/start⁩ برقم الوجهة، فيعود إليك id وموعد الانتهاء.

  3. 03

    تحقق من الرمز

    أرسل طلب POST إلى ⁦/v1/verify/check⁩ بالمعرّف نفسه والرمز الذي كتبه المستخدم.

القنوات

تُتاح رموز التحقق عبر واتساب قريبًا، ورسائل SMS تعمل اليوم. ولرسائل قوالب واتساب، مثل تحديثات الطلبات والتذكيرات، نقطتها الخاصة أدناه، من رقمك المربوط.

القناةقيمة channelصيغ الوجهة المقبولةملاحظاتالسعر
SMSsms+966512345678, 966512345678, 00966512345678, 0512345678, 512345678تُحوَّل أي صيغة محلية تلقائيًا إلى ⁦+9665XXXXXXXX⁩ قبل الإرسال.0.09 ر.س لكل رمز يُرسَل

المصادقة

مرّر مفتاحك في ترويسة Authorization بصيغة Bearer، أو في ترويسة x-api-key إن تعذّر ذلك. وإن وُجدت الترويستان فالأولوية لترويسة Authorization.

المفتاح الفعلي

Authorization: Bearer tk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6

مفتاح التجربة

Authorization: Bearer tk_test_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6

مفتاح الشريك

Authorization: Bearer tk_partner_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6

يمرّر مفتاح الشريك التطبيق في حقل application داخل جسم الطلب، أو في حقل service باسمه القديم، لأن مفتاحًا واحدًا يغطي كل متاجر الشريك.

تعزيز المفاتيح ونطاق صلاحياتها

تُضبط عند إنشاء المفتاح من اللوحة، وكلها اختيارية.

  • الحقل expires_at اختياري: بعد انقضائه يعيد كل استدعاء بهذا المفتاح 401 key_expired، ويُفحص فور التعرف على المفتاح قبل أي شيء آخر.
  • الحقل ip_allowlist اختياري: عناوين IP محددة أو نطاقات CIDR، بصيغتي IPv4 وIPv6. وإن كان فارغًا أو غائبًا سُمح لكل العناوين، ويُرد على المستدعي من خارجه بالخطأ 403 ip_not_allowed.
  • الصلاحية: للمفتاح صلاحية كاملة، تشمل كل المنتجات وما يُضاف لاحقًا، أو صلاحية مخصّصة تقتصر على ما مُنح له من كل منتج. التحقق: «بلا» أو «تحقق فقط» أو «إرسال وتحقق». الإشعارات: «بلا» أو «قراءة فقط» أو «إرسال». وأيًّا كانت صلاحيته يبقى المفتاح سرًّا في خادمك: لا تضعه في متصفح ولا في تطبيق جوال.
  • وراء هذه المستويات أربع صلاحيات. تتيح ⁦verify:check⁩ استدعاء ⁦POST /v1/verify/check⁩، ⁦GET /v1/verify/{id}⁩. وتتيح ⁦verify:send⁩ استدعاء ⁦POST /v1/verify/start⁩، ⁦POST /v1/verify/{id}/resend⁩، ⁦POST /v1/verify/{id}/cancel⁩، وتشمل ⁦verify:check⁩. وتتيح ⁦notifications:read⁩ استدعاء ⁦GET /v1/whatsapp/messages/{id}⁩، ⁦GET /v1/whatsapp/templates⁩، ⁦GET /v1/whatsapp/templates/{template_id}⁩. وتتيح ⁦notifications:send⁩ استدعاء ⁦POST /v1/whatsapp/messages⁩، وتشمل ⁦notifications:read⁩. وصلاحية خامسة ليست من مستويات تلك الصفحة: تتيح ⁦notifications:templates⁩ استدعاء ⁦POST /v1/whatsapp/templates⁩، ⁦PATCH /v1/whatsapp/templates/{template_id}⁩، ⁦DELETE /v1/whatsapp/templates/{template_id}⁩، وتشمل ⁦notifications:read⁩. لا يحملها أي مفتاح يُنشأ من صفحة «مفاتيح API»، ولو كان بصلاحية كاملة، فتعيد هذه الاستدعاءات الثلاثة لمثله 403 insufficient_scope. ويحملها مفتاح التطبيق المربوط.
  • الاستدعاء الخارج عن صلاحية المفتاح يعيد 403 بالجسم ⁦{"error":"insufficient_scope"}⁩، وتذكر ترويسة الاستجابة الصلاحية التي يحتاج إليها: ⁦WWW-Authenticate: Bearer error="insufficient_scope", scope="verify:send"⁩. ويُفحص ذلك فور التعرف على المفتاح، بعد الأخطاء unauthorized، key_expired، ip_not_allowed، وقبل account_not_active وشكل الطلب.
  • مفتاح «تحقق فقط» المُنشأ قبل تحديد الصلاحية لكل منتج يعمل كما كان: يحمل ⁦verify:check⁩، ⁦notifications:read⁩، فيتحقق من الرموز ويقرأ الحالات والقوالب في المنتجين، ولا يرسل في أي منهما.
  • لا يُمنح مفتاح التجربة صلاحية على الإشعارات: لا بيئة تجربة لواتساب، وترفض ⁦/v1/whatsapp/*⁩ كل مفتاح تجربة.
  • البريد: «بلا» أو «قراءة فقط» أو «إرسال». تتيح ⁦email:read⁩ استدعاء ⁦GET /v1/email/messages/{id}⁩. وتتيح ⁦email:send⁩ استدعاء ⁦POST /v1/email/messages⁩، وتشمل ⁦email:read⁩. ولا يُمنح مفتاح التجربة صلاحية على البريد: لا بيئة تجربة للبريد، وترفض ⁦/v1/email/*⁩ كل مفتاح تجربة.
  • تُضبط عند إنشاء المفتاح من صفحة «مفاتيح API» للتطبيق في لوحة العميل (إنشاء مفتاح). ولا تتغير صلاحية المفتاح بعد إنشائه: أنشئ مفتاحًا جديدًا بالصلاحية التي تحتاج إليها. ويستطيع الشريك عند تدوير مفتاحه ضبط تاريخ الانتهاء والقائمة المسموحة أيضًا، ومفتاح الشريك بصلاحية كاملة دائمًا، ولا يُقيَّد بمنتج.

بيئة التجربة

أنشئ مفتاح ⁦tk_test_⁩ من اللوحة قبل اعتماد التطبيق. يستخدم نقاط النهاية وصيغ الطلبات نفسها.

tk_test_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
  • تنشئه بنفسك قبل اعتماد التطبيق: من صفحة «مفاتيح API» للتطبيق (إنشاء مفتاح، من نوع تجربة)، أو يُنشأ لك عند أول إرسال من «التحقق ← التجربة» في اللوحة.
  • يستدعي النقاط نفسها بأشكال الطلب والاستجابة نفسها.
  • يرسل رسائل حقيقية، لكن إلى رقم واحد فقط: جوال مالك الحساب الذي وثّقه عند التسجيل، ولا تُضاف وجهات أخرى.
  • تحمل كل رسالة ختمًا ثابتًا لا يُحذف: [تجريبي] في الرسالة العربية، والختم ⁦[TEST]⁩ في الإنجليزية.
  • يُخصم من الرصيد المسبق نفسه كأي إرسال آخر، بسقف مدى الحياة لكل تطبيق قدره 10، حتى لا تستهلك التجربة الرصيد الترحيبي كله.
  • لا بيئة تجربة لواتساب: ترفض ⁦/v1/whatsapp/*⁩ كل مفتاح تجربة بالخطأ ⁦403 live_key_required⁩، أو ⁦403 insufficient_scope⁩ لمفتاح التجربة ذي الصلاحية المخصّصة، إذ لا يحمل صلاحية الإشعارات أبدًا.

رسائل جاهزة للإكمال التلقائي

يُشتق نطاق الإكمال التلقائي من موقع تطبيقك بعد المراجعة. أضف بصمة تطبيق أندرويد لدعم SMS Retriever من Google، إلى جانب iOS AutoFill ومعيار WebOTP.

  • لا يُكتب النطاق يدويًا: يُشتق autofill_domain من موقع التطبيق بعد مراجعته، أي النطاق الأساسي فتُغطى النطاقات الفرعية، ويظهر للقراءة فقط في كل استجابة. ويشغّل autofill_domain_enabled سطره أو يوقفه، ويُضبط android_app_hash، وطوله 11 حرفًا، لكل تطبيق من اللوحة أو عبر واجهة الشركاء عند الإنشاء وفي تعديل إعدادات التحقق.
  • يضيف سطر ⁦@domain #code⁩ نحو 25 حرفًا. والرسالة العربية تُحسب بمقاطع من 70 حرفًا، فقد يحوّلها السطر من مقطع إلى مقطعين، ولذلك تعرض معاينة اللوحة عدد المقاطع، وللسطر مفتاح تشغيل.
  • يُضاف إلى الرسالة بعد نصها: سطر بصمة تطبيق أندرويد إن كانت مضبوطة والهدف أندرويد، ثم ‎@النطاق #الرمز آخر سطر إن كان النطاق مضبوطًا والهدف الويب.
  • يقرأ iOS AutoFill وWebOTP آخر سطر في الرسالة فقط، ولهذا يأتي سطر النطاق دائمًا أخيرًا بعد سطر بصمة التطبيق.
  • تحتاج خدمة SMS Retriever من Google إلى وجود البصمة في أي مكان من الرسالة، وأن يبقى حجمها كله أقل من 140 بايت. ونص GSM-7 بايت واحد لكل حرف، وأي حرف خارجه، ومنه أغلب العربية، بايتان.
  • يحدد الحقل الاختياري autofill في start، بقيمة web أو android أو none، السطر الذي يُرسل في هذه العملية وحدها. اتركه فارغًا لإرسال كل الأسطر المفعّلة للتطبيق.
  • يأتي ختم التجربة، إن وُجد، أولًا دائمًا قبل أي سطر إكمال تلقائي.
  • لا ينطبق على واتساب: رسالته قالب ثابت من Meta لا يتسع لأي من السطرين.

مثال رسالة أقل من ⁦140⁩ بايت

Your Flower Shop verification code is: 482913
FA+9qCX9VSu
@shop.example.com #482913

نقاط النهاية

POST/v1/verify/start

بدء عملية تحقق

يرسل رمزًا لمرة واحدة إلى وجهة، ويعيد id تتحقق به منه.

المعاملات

tostringمطلوب

الوجهة. أي صيغة من الصيغ السعودية المقبولة أدناه.

phonestringاختياري

اسم بديل قديم للحقل to، أُبقي للتكاملات السابقة. يُستخدم فقط إن غاب to أو كان فارغًا، والأولوية للحقل to إن وُجد الاثنان. والتكاملات الجديدة تستخدم to.

channelstringاختياري

قناة التسليم، وقيمتها sms إن غابت أو كانت فارغة. أما whatsapp فتُرفض بالخطأ unsupported_channel حتى يفتح توكيد واتساب للرموز لكل الحسابات.

langstringاختياري

لغة الرسالة. القيمة en وحدها تختار الإنجليزية، وأي قيمة أخرى أو غيابها يعني العربية.

applicationstringمفتاح الشريك

لمفاتيح الشركاء فقط: التطبيق المرسِل من تطبيقاتك المزوَّدة. ويُقبل الاسم القديم service بالمعنى نفسه.

referencestringاختياري

مرجعك، مثل رقم طلب أو معرّف عملية، حتى 64 حرفًا قابلًا للطباعة. يعود في رد start وفي ⁦GET /v1/verify/{id}⁩، وتبحث به في قائمة عمليات التحقق في اللوحة.

client_ipstringاختياري

عنوان IP للمستخدم النهائي. يفعّل حارس الحماية لكل IP لهذا التطبيق إن كان مضبوطًا، ولا يُستنتج من الطلب أبدًا، بل يُمرَّر صراحةً.

autofillstringاختياري

القيمة web أو android أو none، وتحدد سطر الإكمال التلقائي في هذا الإرسال: يرسل web سطر ‎@النطاق #الرمز وحده، ويرسل android سطر بصمة التطبيق وحده، ولا يرسل none أيًا منهما. اتركه فارغًا لإرسال كل الأسطر المفعّلة للتطبيق.

الترويسات

Idempotency-Keystringاختياري

مفتاح تولّده أنت، من 1 إلى 128 حرف ASCII قابلًا للطباعة، مرتبط بمفتاح API لديك، وبالتطبيق المحدد أيضًا لمفاتيح الشركاء. تكرار المفتاح نفسه يعيد استجابة 201 الأصلية كما هي، مع ترويسة الاستجابة Idempotent-Replayed: true، بلا إرسال أو خصم جديد. والإرسال الذي يفشل يحرّر المفتاح لتعيد المحاولة.

الاستجابة

201بدأت
{
    "id": "b7e5c2b0-9c1a-4e2f-8f2a-3a6b0e9d1c44",
    "status": "pending",
    "expires_at": "2026-09-01T12:34:56.789Z"
}

مثال الطلب

curl -X POST https://tawked.com/v1/verify/start \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "0551234567",
    "channel": "sms",
    "lang": "ar"
}'
POST/v1/verify/check

التحقق من رمز

يتحقق من الرمز الذي كتبه المستخدم مقابل id الذي أعاده verify/start.

المعاملات

idstringمطلوب

المعرّف id الذي أعاده verify/start.

codestringمطلوب

الرمز الذي كتبه المستخدم، ويُقارَن كما وصل تمامًا بلا قص للمسافات، فالمسافة الزائدة تمنع التطابق.

applicationstringمفتاح الشريك

لمفاتيح الشركاء فقط، بمعنى verify/start نفسه. ولا يتحقق المفتاح إلا من رمز بدأ تحت التطبيق نفسه.

الاستجابة

200تحقّق
{
    "verified": true,
    "status": "verified"
}
200رمز خاطئ
{
    "verified": false,
    "status": "invalid_code",
    "attempts_remaining": 2
}
200نفدت المحاولات
{
    "verified": false,
    "status": "too_many_attempts",
    "attempts_remaining": 0
}
200فشل الإرسال أو نفدت محاولات سابقة
{
    "verified": false,
    "status": "failed"
}
200انتهت الصلاحية
{
    "verified": false,
    "status": "expired"
}
200أُلغيت
{
    "verified": false,
    "status": "canceled"
}
404معرّف غير معروف
{
    "error": "not_found"
}

مثال الطلب

curl -X POST https://tawked.com/v1/verify/check \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "b7e5c2b0-9c1a-4e2f-8f2a-3a6b0e9d1c44",
    "code": "482913"
}'
GET/v1/verify/{id}

قراءة عملية تحقق

يعيد الحالة الحالية لعملية تحقق، أي الحالة والقناة والوجهة وعدد المحاولات والإعادات المتبقية، دون استهلاك أي محاولة.

المعاملات

applicationstringمفتاح الشريك

لمفاتيح الشركاء فقط: يُمرَّر معاملًا في الرابط ‎⁦?application=…⁩‎ لأن طلب GET بلا جسم، بمعنى start نفسه، ويُقبل الاسم القديم service.

الاستجابة

200الحالة الحالية
{
    "id": "b7e5c2b0-9c1a-4e2f-8f2a-3a6b0e9d1c44",
    "status": "pending",
    "channel": "sms",
    "to": "+966551234567",
    "reference": "order-42",
    "attempts_remaining": 3,
    "resends_remaining": 3,
    "expires_at": "2026-09-01T12:34:56.789Z",
    "verified_at": null,
    "created_at": "2026-09-01T12:29:56.789Z"
}
404معرّف غير معروف
{
    "error": "not_found"
}

مثال الطلب

curl https://tawked.com/v1/verify/b7e5c2b0-9c1a-4e2f-8f2a-3a6b0e9d1c44 \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx"
POST/v1/verify/{id}/resend

إعادة إرسال رمز

يرسل رمزًا جديدًا على المعرّف نفسه: يتوقف الرمز السابق، وتُصفَّر المحاولات وتتجدد الصلاحية، ويُخصم الإرسال ويخضع لحدود المعدل كأي إرسال آخر، بحد أقصى 3 إعادات لكل عملية تحقق.

المعاملات

applicationstringمفتاح الشريك

لمفاتيح الشركاء فقط، بمعنى start نفسه.

الاستجابة

200أُرسل رمز جديد
{
    "id": "b7e5c2b0-9c1a-4e2f-8f2a-3a6b0e9d1c44",
    "status": "pending",
    "expires_at": "2026-09-01T12:39:56.789Z",
    "resends_remaining": 2
}
409في حالة نهائية
{
    "error": "not_resendable",
    "status": "verified"
}
429بلغت حد الإعادات
{
    "error": "resend_limit_reached"
}

مثال الطلب

curl -X POST https://tawked.com/v1/verify/b7e5c2b0-9c1a-4e2f-8f2a-3a6b0e9d1c44/resend \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx"
POST/v1/verify/{id}/cancel

إلغاء عملية تحقق

يلغي عملية تحقق قيد الانتظار، ويعيد أي check لاحق عليها ⁦{ "verified": false, "status": "canceled" }⁩.

المعاملات

applicationstringمفتاح الشريك

لمفاتيح الشركاء فقط، بمعنى start نفسه.

الاستجابة

200أُلغيت
{
    "id": "b7e5c2b0-9c1a-4e2f-8f2a-3a6b0e9d1c44",
    "status": "canceled"
}
409في حالة نهائية
{
    "error": "not_cancelable",
    "status": "verified"
}

مثال الطلب

curl -X POST https://tawked.com/v1/verify/b7e5c2b0-9c1a-4e2f-8f2a-3a6b0e9d1c44/cancel \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx"

رسائل واتساب

أرسل قالب واتساب معتمدًا من رقمك المربوط بتطبيقك، بالمفتاح الفعلي للتطبيق. يتحقق توكيد من القالب مقابل قائمة قوالب الرقم الحالية، ويخصم الرسوم، ويرسل عبر Meta نيابة عنك، ويسجّل الرسالة، ويعرضها في محادثة توكيد شات، ويتابع التسليم والقراءة، ولا يحمل نظامك أي رمز وصول من Meta. ويستطيع أي تطبيق قيد المراجعة أو معتمد ربط حسابه على واتساب للأعمال من اللوحة.

خطوات البدء

أربع خطوات من الصفر إلى أول رسالة، ثلاث منها في اللوحة.

  1. 01

    اربط رقمك

    من اللوحة: التطبيقات، ثم تطبيقك، قيد المراجعة أو معتمدًا، ثم الإشعارات، ثم «ربط واتساب»، ويربطه المالك أو أحد المديرين. تفتح Meta نافذة تختار فيها النشاط والرقم أو تنشئهما، ويسجّل توكيد الرقم ويجهّز صندوق الوارد هنا. وتحتفظ بصلاحيتك الكاملة في WhatsApp Manager وتدفع إلى Meta مباشرة مقابل الرسائل.

  2. 02

    أنشئ قالبًا

    من صفحة القوالب في التطبيق، أو من مكتبة قوالب Meta، أو من WhatsApp Manager. تراجعه Meta في 24 ساعة على الأكثر، والقالب المعتمد وحده يُرسل. وتعمل هنا قوالب الخدمة والتسويق والمصادقة، وقالب المصادقة يرسل رمز تحقق من رقمك.

  3. 03

    استخدم المفتاح الفعلي للتطبيق

    من اللوحة: التطبيقات، ثم تطبيقك، ثم المفاتيح. يحتاج إرسال واتساب مفتاح ⁦tk_live_⁩ للتطبيق المربوط بالرقم، بصلاحية كاملة أو بمستوى «إرسال» في الإشعارات، ويُرفض مفتاح ⁦tk_test_⁩، فلا بيئة تجربة لواتساب.

  4. 04

    اعرض القوالب ثم أرسل

    يعرض ⁦GET /v1/whatsapp/templates⁩ كل قالب مع متغيراته. ويرسل ⁦POST /v1/whatsapp/messages⁩ رسالة بالحقول to وtemplate وparams، والرد 202 مع id. اقرأ الحالة عبر ⁦GET /v1/whatsapp/messages/{id}⁩، أو استقبل ويبهوك message.*.

POST/v1/whatsapp/messages

إرسال رسالة قالب

يرسل قالبًا معتمدًا إلى جوال سعودي من الرقم المربوط بالتطبيق، ويرد 202 مع id تتابع به الرسالة. والرسوم، إن وُجدت، مقابل الإرسال، ويُعاد الخصم عن الإرسال الفاشل.

المعاملات

tostringمطلوب

الوجهة: جوال سعودي بأي صيغة من الصيغ المقبولة، ويُحفظ بالصيغة الدولية.

templatestringمطلوب

اسم القالب كما يظهر في WhatsApp Manager، من 1 إلى 512 حرفًا. ويجب أن يكون معتمدًا في حساب واتساب للأعمال للرقم.

langstringاختياري

لغة القالب كما تسجّلها Meta، مثل ar أو en أو en_US. مطلوبة إن كان القالب بأكثر من لغة.

paramsobjectاختياري

قيم متغيرات نص الرسالة: المفاتيح أسماء المتغيرات في القالب المسمّى مثل ⁦{{name}}⁩، أو ⁦"1"⁩ و⁦"2"⁩ في القالب المرقّم مثل ⁦{{1}}⁩. كل متغير مطلوب، وتُرفض المفاتيح الزائدة، والقيم نصوص من 1 إلى 1024 حرفًا. ويأخذ قالب المصادقة ⁦{ "code": "…" }⁩ وحده، من 4 إلى 15 حرفًا أو رقمًا، فيملأ نصه وزره. ويعرض ⁦GET /v1/whatsapp/templates⁩ متغيرات كل قالب.

headerobjectاختياري

⁦{ "text": "…" }⁩: قيمة متغير الترويسة النصية، مطلوبة إن كان في القالب متغير ترويسة ومرفوضة إن لم يكن، وبلا أسطر جديدة. وللقالب الذي يبدأ بصورة: ⁦{ "image": { "link": "https://…" } }⁩، رابط الصورة العام بـ https، حتى 2048 حرفًا، لصورة JPG أو PNG حتى 5 ميجابايت تجلبها Meta عند الإرسال؛ مطلوب لمثل هذا القالب ومرفوض لغيره. وترويسات الفيديو والمستندات والمواقع غير مدعومة بعد.

buttonsarrayاختياري

⁦[{ "index": 0, "parameter": "…" }]⁩: اللاحقة المتغيرة لكل زر رابط، عنصر واحد لكل زر فيه متغير، وindex ترتيب الزر بين أزرار القالب. وتُرفض مع قالب المصادقة، فالقيمة ⁦params.code⁩ تملأ زره.

referencestringاختياري

مرجعك، مثل رقم طلب أو معرّف حدث، من 1 إلى 64 حرفًا قابلًا للطباعة. يعود إليك في الرد، وتبحث به في سجل الرسائل في اللوحة.

الترويسات

Idempotency-Keystringاختياري

مفتاح تولّده أنت، من 1 إلى 128 حرف ASCII قابلًا للطباعة، مرتبط بمفتاح API لديك. تكرار المفتاح نفسه يعيد استجابة 202 الأصلية كما هي، مع ترويسة الاستجابة Idempotent-Replayed: true، بلا إرسال أو خصم جديد. والإرسال الذي يفشل بخطأ 502 يحرّر المفتاح. استخدم مفتاحًا لكل حدث تجاري، مثل order-1042-received، وأعد المحاولة بالمفتاح نفسه عند 502 أو خطأ في الشبكة.

الاستجابة

202قُبلت
{
    "id": "0f4c9c0e-6d2b-4b8a-9c3e-7a1d2e3f4a5b",
    "status": "accepted",
    "to": "+966550000000",
    "template": "order_received",
    "lang": "ar",
    "reference": "order-30517",
    "price_halalas": 0,
    "created_at": "2026-09-06T12:00:00+03:00"
}
422قالب غير معروف
{
    "error": "unknown_template"
}
402رصيد غير كافٍ
{
    "error": "insufficient_credits",
    "message": "Insufficient credits",
    "balance_halalas": 0,
    "price_halalas": 9
}

مثال الطلب

curl -X POST https://tawked.com/v1/whatsapp/messages \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-30517-received" \
  -d '{
    "to": "0550000000",
    "template": "order_received",
    "lang": "ar",
    "params": {
        "customer_name": "سارة",
        "order_number": "30517"
    },
    "reference": "order-30517"
}'
GET/v1/whatsapp/messages/{id}

قراءة رسالة

يعيد الحالة الحالية للرسالة وأوقاتها. تُتابَع حالات Meta 48 ساعة بعد الإرسال، ويُضبط error إن فشلت الرسالة. والرسالة تخص تطبيق المفتاح، وأي id آخر يعيد 404.

المعاملات

الاستجابة

200وصلت
{
    "id": "0f4c9c0e-6d2b-4b8a-9c3e-7a1d2e3f4a5b",
    "status": "delivered",
    "to": "+966550000000",
    "template": "order_received_v1",
    "lang": "ar",
    "reference": "order-1042",
    "price_halalas": 0,
    "error": null,
    "created_at": "2026-09-06T12:00:00+03:00",
    "sent_at": "2026-09-06T12:00:01+03:00",
    "delivered_at": "2026-09-06T12:00:04+03:00",
    "read_at": null,
    "failed_at": null
}
200فشلت
{
    "id": "0f4c9c0e-6d2b-4b8a-9c3e-7a1d2e3f4a5b",
    "status": "failed",
    "to": "+966550000000",
    "template": "order_received_v1",
    "lang": "ar",
    "reference": "order-1042",
    "price_halalas": 0,
    "error": {
        "code": "131026",
        "message": "Message undeliverable"
    },
    "created_at": "2026-09-06T12:00:00+03:00",
    "sent_at": null,
    "delivered_at": null,
    "read_at": null,
    "failed_at": "2026-09-06T12:00:03+03:00"
}
404معرّف غير معروف
{
    "error": "not_found"
}

مثال الطلب

curl https://tawked.com/v1/whatsapp/messages/0f4c9c0e-6d2b-4b8a-9c3e-7a1d2e3f4a5b \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx"
GET/v1/whatsapp/templates

قائمة القوالب

يعرض قوالب حساب واتساب للأعمال للرقم كما تحفظها Meta، مع متغيرات كل قالب، فيعرف نظامك ما يرسله دون WhatsApp Manager. ويحمل كل صف id القالب لدى Meta، وهو ما تأخذه عمليات القوالب، والحقل managed، وقيمته true حين يكون المفتاح مفتاح تطبيق مربوط أنشأ هذا القالب عبر هذا التطبيق نفسه. ويُخزَّن مؤقتًا 5 دقائق.

المعاملات

الاستجابة

200القوالب ومتغيراتها
{
    "data": [
        {
            "id": "7000",
            "name": "order_received_v1",
            "language": "ar",
            "category": "UTILITY",
            "status": "APPROVED",
            "placeholders": {
                "kind": "named",
                "header": [],
                "body": [
                    "name",
                    "order"
                ],
                "buttons": [
                    {
                        "index": 0,
                        "type": "url"
                    }
                ]
            },
            "managed": false
        }
    ]
}

مثال الطلب

curl https://tawked.com/v1/whatsapp/templates \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx"
GET/v1/whatsapp/templates/{template_id}

قراءة قالب

يقرأ قالبًا واحدًا كاملًا بمعرّفه لدى Meta: حالته وجودته وسبب رفضه، ومكوّناته كما تحفظها Meta، وقيم الأمثلة، والمتغيرات التي يملؤها الإرسال، والحقل managed. والمعرّف غير الموجود في حساب واتساب للأعمال للرقم يعيد 404.

المعاملات

الاستجابة

200القالب
{
    "id": "7000",
    "name": "order_received_v1",
    "language": "ar",
    "category": "UTILITY",
    "status": "APPROVED",
    "quality": "GREEN",
    "rejected_reason": null,
    "components": [
        {
            "type": "HEADER",
            "format": "TEXT",
            "text": "طلبك {{1}}",
            "buttons": []
        },
        {
            "type": "BODY",
            "format": null,
            "text": "استلمنا طلبك رقم {{1}} بقيمة {{2}} ريال.",
            "buttons": []
        },
        {
            "type": "BUTTONS",
            "format": null,
            "text": null,
            "buttons": [
                {
                    "type": "URL",
                    "text": "تتبع الطلب",
                    "url": "https://flowers.example/orders/{{1}}",
                    "phone_number": null
                }
            ]
        }
    ],
    "examples": {
        "header:1": "1042",
        "body:1": "1042",
        "body:2": "250",
        "button:0": "1042"
    },
    "placeholders": {
        "kind": "positional",
        "header": [
            "1"
        ],
        "body": [
            "1",
            "2"
        ],
        "buttons": [
            {
                "index": 0,
                "type": "url"
            }
        ]
    },
    "managed": false
}
404ليس في حساب هذا الرقم
{
    "error": "not_found"
}

مثال الطلب

curl https://tawked.com/v1/whatsapp/templates/7000 \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx"
POST/v1/whatsapp/templates

إنشاء قالب

يتطلب مفتاح تطبيق مربوط (خارجي). مفتاح نشاطك التجاري، حتى بصلاحية كاملة، يعيد 403 insufficient_scope، وتكتب قوالبك من اللوحة. يرسل قالبًا نصيًّا إلى مراجعة Meta بقواعد محرر اللوحة نفسها، ويعيد id القالب لدى Meta، والفئة كما سجّلتها Meta، والحالة status، وهي PENDING في البداية غالبًا. للنص فقط: يُهمل أي حقل غير الحقول أدناه، فالقالب الذي يبدأ بصورة يُنشأ من اللوحة. والحقل المرفوض يعيد 400 invalid_request، وفيه fields بأسماء الحقول وerrors بأسباب كل حقل، وما ترفضه Meta بعد ذلك يعيد 422 template_refused بعبارة Meta نفسها.

المعاملات

namestringمطلوب

حروف إنجليزية صغيرة وأرقام وشرطات سفلية، حتى 512 حرفًا. وتثبّته Meta عند الإنشاء. ولا يأخذ مفتاح تطبيق مربوط اسمًا يبدأ بـ ⁦salla_⁩ أو ⁦zid_⁩ أو ⁦wf_⁩، ولا اسمًا من أسماء قوالب توكيد نفسها، ويحمل ⁦errors.name⁩ عندها القيمة nameReserved.

languagestringمطلوب

إحدى القيم ar أو en أو en_US أو en_GB أو ur أو hi أو bn أو tl أو id أو fr. وتثبت عند الإنشاء.

categorystringمطلوب

القيمة UTILITY. يكتب مفتاح التطبيق المربوط قوالب الخدمة وحدها، وتُرفض MARKETING بالخطأ 422 template_category_not_allowed. وقالب المصادقة يُنشأ من اللوحة.

headerstringاختياري

ترويسة نصية: سطر واحد، حتى 60 حرفًا، بلا رموز تعبيرية ولا علامة النجمة، وبمتغير واحد على الأكثر.

bodystringمطلوب

حتى 1024 حرفًا. والمتغيرات كلها مسمّاة مثل ⁦{{name}}⁩ بحروف صغيرة، أو كلها مرقّمة مثل ⁦{{1}}⁩ ثم ⁦{{2}}⁩ بالترتيب، ولا تقع في أول النص ولا في آخره.

footerstringاختياري

سطر واحد، حتى 60 حرفًا، بلا متغيرات.

buttonsarrayاختياري

حتى 10 عناصر، في كل منها text حتى 25 حرفًا: ⁦{ "type": "QUICK_REPLY", "text" }⁩، أو ⁦{ "type": "URL", "text", "url" }⁩ برابط https قد ينتهي بالمتغير ⁦{{1}}⁩ (زرّان على الأكثر)، أو ⁦{ "type": "PHONE_NUMBER", "text", "phone_number" }⁩ برقم بالصيغة الدولية (زر واحد على الأكثر). وتتجاور أزرار الرد السريع، قبل الأزرار الأخرى أو بعدها.

examplesobjectاختياري

قيمة مثال لكل متغير، بالمفاتيح ⁦header:<key>⁩ و⁦body:<key>⁩ و⁦button:<index>⁩. مطلوبة كلما كان في القالب متغيرات، فبها تراجعه Meta.

الترويسات

Idempotency-Keystringاختياري

مفتاح تولّده أنت، من 1 إلى 128 حرف ASCII قابلًا للطباعة، مرتبط بمفتاح API لديك. تكراره مع الطلب نفسه يعيد استجابة 2xx الأصلية كما هي، مع ترويسة الاستجابة Idempotent-Replayed: true، دون تنفيذ جديد. والمفتاح نفسه مع طلب آخر يعيد 409 idempotency_key_reused، ومع طلب ما زال قيد التنفيذ 409 idempotency_in_progress. والطلب المرفوض لا يُحفظ، فتعمل إعادة المحاولة المصحّحة بالمفتاح نفسه. وتنتهي المفاتيح بعد 24 ساعة.

الاستجابة

201أُرسل إلى Meta
{
    "id": "7100",
    "name": "order_shipped_v1",
    "language": "ar",
    "category": "UTILITY",
    "status": "PENDING"
}
400حقول مرفوضة
{
    "error": "invalid_request",
    "fields": [
        "body",
        "examples.header:order"
    ],
    "errors": {
        "body": [
            "placeholderEdges"
        ],
        "examples.header:order": [
            "exampleRequired"
        ]
    }
}
422رفضته Meta
{
    "error": "template_refused",
    "message": "Meta error 100: Template name already exists"
}

مثال الطلب

curl -X POST https://tawked.com/v1/whatsapp/templates \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_shipped_v1-ar" \
  -d '{
    "name": "order_shipped_v1",
    "language": "ar",
    "category": "UTILITY",
    "header": "طلبك {{order}}",
    "body": "طلبك {{order}} في الطريق، ويصلك خلال {{days}} أيام.",
    "footer": "متجر الورد",
    "buttons": [
        {
            "type": "URL",
            "text": "تتبع الشحنة",
            "url": "https://flowers.example/track/{{1}}"
        }
    ],
    "examples": {
        "header:order": "1042",
        "body:order": "1042",
        "body:days": "3",
        "button:0": "1042"
    }
}'
PATCH/v1/whatsapp/templates/{template_id}

تعديل قالب

يتطلب مفتاح تطبيق مربوط (خارجي). مفتاح نشاطك التجاري، حتى بصلاحية كاملة، يعيد 403 insufficient_scope، وتكتب قوالبك من اللوحة. يستبدل محتوى قالب نصي لدى Meta. أرسل المحتوى الجديد كاملًا: جسم الإنشاء دون name وlanguage، فقد ثبّتتهما Meta عند الإنشاء ويُهملان هنا. وتراجع Meta التعديل من جديد. ولا يُعدَّل إلا قالب حالته APPROVED أو REJECTED أو PAUSED، وما عداه يعيد 409 template_not_editable مع status: حالة القالب نفسها، أو META_SAMPLE لقالب من نماذج Meta، أو MEDIA_HEADER لقالب يبدأ بصورة أو وسائط أخرى، وهذا يُعدَّل من اللوحة. وقالب المصادقة يعيد 422 template_category_not_allowed. ويعيد الرد القالب كما صار بعد التعديل.

المعاملات

categorystringمطلوب

القيمة UTILITY. يكتب مفتاح التطبيق المربوط قوالب الخدمة وحدها، وتُرفض MARKETING بالخطأ 422 template_category_not_allowed. وقالب المصادقة يُنشأ من اللوحة.

headerstringاختياري

ترويسة نصية: سطر واحد، حتى 60 حرفًا، بلا رموز تعبيرية ولا علامة النجمة، وبمتغير واحد على الأكثر.

bodystringمطلوب

حتى 1024 حرفًا. والمتغيرات كلها مسمّاة مثل ⁦{{name}}⁩ بحروف صغيرة، أو كلها مرقّمة مثل ⁦{{1}}⁩ ثم ⁦{{2}}⁩ بالترتيب، ولا تقع في أول النص ولا في آخره.

footerstringاختياري

سطر واحد، حتى 60 حرفًا، بلا متغيرات.

buttonsarrayاختياري

حتى 10 عناصر، في كل منها text حتى 25 حرفًا: ⁦{ "type": "QUICK_REPLY", "text" }⁩، أو ⁦{ "type": "URL", "text", "url" }⁩ برابط https قد ينتهي بالمتغير ⁦{{1}}⁩ (زرّان على الأكثر)، أو ⁦{ "type": "PHONE_NUMBER", "text", "phone_number" }⁩ برقم بالصيغة الدولية (زر واحد على الأكثر). وتتجاور أزرار الرد السريع، قبل الأزرار الأخرى أو بعدها.

examplesobjectاختياري

قيمة مثال لكل متغير، بالمفاتيح ⁦header:<key>⁩ و⁦body:<key>⁩ و⁦button:<index>⁩. مطلوبة كلما كان في القالب متغيرات، فبها تراجعه Meta.

الترويسات

Idempotency-Keystringاختياري

مفتاح تولّده أنت، من 1 إلى 128 حرف ASCII قابلًا للطباعة، مرتبط بمفتاح API لديك. تكراره مع الطلب نفسه يعيد استجابة 2xx الأصلية كما هي، مع ترويسة الاستجابة Idempotent-Replayed: true، دون تنفيذ جديد. والمفتاح نفسه مع طلب آخر يعيد 409 idempotency_key_reused، ومع طلب ما زال قيد التنفيذ 409 idempotency_in_progress. والطلب المرفوض لا يُحفظ، فتعمل إعادة المحاولة المصحّحة بالمفتاح نفسه. وتنتهي المفاتيح بعد 24 ساعة.

الاستجابة

200القالب بعد التعديل
{
    "id": "7000",
    "name": "order_received_v1",
    "language": "ar",
    "category": "UTILITY",
    "status": "PENDING",
    "quality": null,
    "rejected_reason": null,
    "components": [
        {
            "type": "HEADER",
            "format": "TEXT",
            "text": "طلبك {{1}}",
            "buttons": []
        },
        {
            "type": "BODY",
            "format": null,
            "text": "استلمنا طلبك رقم {{1}} بقيمة {{2}} ريال، ونبلغك عند شحنه.",
            "buttons": []
        },
        {
            "type": "BUTTONS",
            "format": null,
            "text": null,
            "buttons": [
                {
                    "type": "URL",
                    "text": "تتبع الطلب",
                    "url": "https://flowers.example/orders/{{1}}",
                    "phone_number": null
                }
            ]
        }
    ],
    "examples": {
        "header:1": "1042",
        "body:1": "1042",
        "body:2": "250",
        "button:0": "1042"
    },
    "placeholders": {
        "kind": "positional",
        "header": [
            "1"
        ],
        "body": [
            "1",
            "2"
        ],
        "buttons": [
            {
                "index": 0,
                "type": "url"
            }
        ]
    },
    "managed": false
}
409غير قابل للتعديل
{
    "error": "template_not_editable",
    "status": "PENDING"
}
404ليس في حساب هذا الرقم
{
    "error": "not_found"
}

مثال الطلب

curl -X PATCH https://tawked.com/v1/whatsapp/templates/7000 \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_received_v1-ar-2" \
  -d '{
    "category": "UTILITY",
    "header": "طلبك {{1}}",
    "body": "استلمنا طلبك رقم {{1}} بقيمة {{2}} ريال، ونبلغك عند شحنه.",
    "buttons": [
        {
            "type": "URL",
            "text": "تتبع الطلب",
            "url": "https://flowers.example/orders/{{1}}"
        }
    ],
    "examples": {
        "header:1": "1042",
        "body:1": "1042",
        "body:2": "250",
        "button:0": "1042"
    }
}'
DELETE/v1/whatsapp/templates/{template_id}

حذف قالب

يتطلب مفتاح تطبيق مربوط (خارجي). مفتاح نشاطك التجاري، حتى بصلاحية كاملة، يعيد 403 insufficient_scope، وتكتب قوالبك من اللوحة. يحذف هذه اللغة وحدها من القالب لدى Meta. ويُرفض الحذف ما دام شيء يرسل القالب: 409 template_in_use، ويبيّن used_by ما هو. ونماذج Meta نفسها لا تُحذف: 409 template_not_editable مع status بالقيمة META_SAMPLE.

المعاملات

الترويسات

Idempotency-Keystringاختياري

مفتاح تولّده أنت، من 1 إلى 128 حرف ASCII قابلًا للطباعة، مرتبط بمفتاح API لديك. تكراره مع الطلب نفسه يعيد استجابة 2xx الأصلية كما هي، مع ترويسة الاستجابة Idempotent-Replayed: true، دون تنفيذ جديد. والمفتاح نفسه مع طلب آخر يعيد 409 idempotency_key_reused، ومع طلب ما زال قيد التنفيذ 409 idempotency_in_progress. والطلب المرفوض لا يُحفظ، فتعمل إعادة المحاولة المصحّحة بالمفتاح نفسه. وتنتهي المفاتيح بعد 24 ساعة.

الاستجابة

200حُذف
{
    "id": "7002",
    "name": "promo_v1",
    "language": "en",
    "deleted": true
}
409ما زال مستخدمًا
{
    "error": "template_in_use",
    "used_by": [
        "campaign",
        "automation"
    ]
}
404ليس في حساب هذا الرقم
{
    "error": "not_found"
}

مثال الطلب

curl -X DELETE https://tawked.com/v1/whatsapp/templates/7002 \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx"

حالات الرسالة

acceptedsentdeliveredreadfailed

وقد تأتي الحالة failed بعد أي من الحالات الثلاث الأولى، فتُعاد الرسوم.

  • accepted: سجّل توكيد الرسالة واستلمتها Meta، وهي استجابة 202.
  • sent وdelivered وread: حالات Meta، تُطبَّق بهذا الترتيب ولا تعود إلى الخلف. تصل إلى توكيد عبر مزامنة الحالات، التي تتابع كل رسالة 48 ساعة بعد إرسالها.
  • failed: ممكنة بعد أي من الحالات الثلاث الأولى، مثل رقم لا يمكن الوصول إليه، أو قالب موقوف، أو نافذة مراسلة مغلقة. ويحمل error رمز Meta ورسالتها.
  • الرسوم مقابل الإرسال لا التسليم: لا تكلّف read شيئًا إضافيًا، وتعيد failed الرسوم مرة واحدة. وتتوقف متابعة الرسالة بعد 48 ساعة من الإرسال، وتبقى على آخر حالة.

ويبهوك واتساب

message.sentmessage.deliveredmessage.readmessage.failed
  • حدث واحد لكل تغيير في الحالة إلى رابط ويبهوك التطبيق، موقّع ومُعاد الإرسال مثل verification.* تمامًا: الترويسات tawked-timestamp وtawked-signature وtawked-event نفسها، وHMAC نفسه على ⁦"{timestamp}.{raw body}"⁩، وجدول إعادة المحاولة نفسه، وسجل التسليم نفسه في اللوحة.
  • غلاف verification.* نفسه: event وdata وsent_at. وحقول الرسالة تحت data، وoccurred_at وقت الحالة التي يعلنها الحدث، وerror قيمته null إلا في message.failed، فيكون عندها ⁦{ "code", "message" }⁩. وحدث التجربة المرسل من اللوحة هو دائمًا verification.verified، فلا يحمل أي حدث message.* الحقل test.
  • يُسلَّم عبر مزامنة الحالات، التي تتابع كل رسالة 48 ساعة بعد إرسالها. ولا يُعلن إلا عن الحالة التي بلغتها الرسالة: الرسالة التي تنتقل مباشرة إلى read تنال حدث message.read واحدًا، بلا الحالات التي بينهما.
  • يُعرض to مقنّعًا كما في اللوحة. احتفظ بنسختك من الوجهة بجانب id المعاد أو reference.

مثال المحتوى

{
    "event": "message.delivered",
    "data": {
        "id": "0f4c9c0e-6d2b-4b8a-9c3e-7a1d2e3f4a5b",
        "status": "delivered",
        "application_id": "c2a10f3e-8b7a-4d2e-9c1a-1a2b3c4d5e6f",
        "to": "+9665•• ••• 000",
        "template": "order_received_v1",
        "lang": "ar",
        "reference": "order-1042",
        "price_halalas": 0,
        "error": null,
        "occurred_at": "2026-09-06T09:00:04.512Z",
        "created_at": "2026-09-06T09:00:01.087Z"
    },
    "sent_at": "1788685205201"
}

أخطاء واتساب

بعد الفحوص المشتركة بين كل النقاط، أي حد المعدل والمصادقة وحالة الحساب وشكل الطلب، بهذا الترتيب.

الحالةerrorالمعنى
403live_key_requiredمفتاح تجربة ⁦tk_test_⁩، ولا بيئة تجربة لواتساب بعد. استخدم المفتاح الفعلي للتطبيق.
403whatsapp_not_enabledواتساب موقوف لهذا التطبيق. تواصل مع الدعم إن كنت تعتقد أن هذا خطأ.
409no_whatsapp_numberلا رقم واتساب مربوطًا بهذا التطبيق بعد. اربط رقمًا من قسم الرقم في تبويب الإشعارات في صفحة التطبيق باللوحة، وهي الخطوة الأولى في «خطوات البدء».
409number_disconnectedالرقم مربوط لكنه غير متصل من جهة Meta الآن، فالويبهوك غير مثبّت أو تبلّغ Meta عن حالة غير CONNECTED. وتعرض صفحة الإشعارات في اللوحة صحة الرقم.
422invalid_destinationالوجهة لا تطابق أي صيغة جوال سعودي مقبولة، ورسائل واتساب للجوالات السعودية فقط.
422unknown_templateلا قالب بهذا الاسم، وبهذه اللغة إن حُددت، في حساب واتساب للأعمال للرقم. ويعرض ⁦GET /v1/whatsapp/templates⁩ القوالب الموجودة.
422template_not_approvedالقالب موجود لكن Meta لم تعتمده، ويحمل message حالة Meta، مثل PENDING أو REJECTED أو PAUSED.
422template_category_not_allowedقالب من فئة AUTHENTICATION أُرسل بمفتاح شريك. ترسل مفاتيح الشركاء قوالب الخدمة والتسويق، ويرسل المفتاح الفعلي للتطبيق قوالب المصادقة. ويعيده كذلك تعديل قالب مصادقة عبر ⁦PATCH /v1/whatsapp/templates/{template_id}⁩، فنصّه نص Meta، ومفتاح تطبيق مربوط مع أي فئة غير UTILITY، في الإرسال أو في قالب ينشئه أو يعدّله.
422consent_opted_outقالب تسويقي إلى مستلم طلب من هذا التطبيق إيقاف رسائله التسويقية، بكتابة «إيقاف» إلى الرقم أو بإيقاف عروضه من واتساب. لم يُرسل شيء ولم يُسجَّل ولم يُخصم. وتبقى قوالب الخدمة والمصادقة تصله.
422unsupported_templateيحتاج القالب شيئًا لا تحمله هذه النقطة بعد: ترويسة فيديو أو ملف أو موقع (أما ترويسة الصورة فتُرسل بـ ⁦header.image.link⁩)، أو زرًا أو مكوّنًا يأخذ معاملًا غير نصي، مثل زر نسخ رمز الخصم في قالب تسويقي أو flow أو كتالوج أو carousel أو عرض محدود، أو متغيرات مسمّاة ومرقّمة معًا في النص. ويبيّن message أيها.
422invalid_paramsقيمة متغير ناقصة أو فارغة أو غير متوقعة، أو أطول من 1024 حرفًا، أو فيها سطر جديد أو تاب أو رمز تحكم ترفضه Meta، أو القالب بعدة لغات ولم يُحدد lang، أو وصل قالبَ المصادقة buttons أو code ليس من 4 إلى 15 حرفًا أو رقمًا، أو قالب يبدأ بصورة بلا ⁦header.image.link⁩، أو برابط لا يبدأ بـ https، أو وصلت صورة قالبًا لا يبدأ بها. ويسمّي message المتغير.
402insufficient_creditsالرصيد المسبق للحساب أقل من رسوم رسالة واتساب. ويضيف الرد balance_halalas وprice_halalas، ولم يُرسل شيء ولم يُسجَّل شيء.
502send_failedرفضت Meta الإرسال أو تعذّر الوصول إليها. ويضيف الرد provider_code، وهو رمز خطأ Meta، وmessage، وتُعاد الرسوم وتُسجَّل الرسالة فاشلة.
403template_not_managedمفتاح تطبيق مربوط مع قالب لم ينشئه ذلك التطبيق لهذا التطبيق. يعدّل هذا المفتاح ويحذف القوالب التي أنشأها وحدها، وهي التي قيمة managed فيها true.
409template_not_editableلا يتغيّر القالب عبر API وهو على حاله، ويبيّن status السبب. في التعديل: حالة القالب إن لم تكن APPROVED أو REJECTED أو PAUSED، أو MEDIA_HEADER لقالب يبدأ بصورة أو وسائط أخرى، وهذا يُعدَّل من اللوحة. وفي التعديل والحذف: META_SAMPLE لقالب من نماذج Meta.
409template_in_useما زال شيء يرسل القالب، فلا يقبل التعديل أو الحذف. ويعدّد used_by ما هو، من campaign لحملة لم تنتهِ، وautomation لأتمتة مفعّلة، وstore_notice لإشعار متجر مفعّل، بهذا الترتيب. يوقفه صاحب الحساب أو يغيّر قالبه من اللوحة أولًا.
409idempotency_in_progressطلب بمفتاح Idempotency-Key نفسه ما زال قيد التنفيذ. انتظر رده، أو أعد المحاولة بعد لحظة.
409idempotency_key_reusedاستُخدم مفتاح Idempotency-Key هذا من قبل لطلب مختلف. استخدم مفتاحًا لكل تغيير.
422template_refusedرفضت Meta القالب بعد أن اجتاز فحوص توكيد، ويحمل message عبارة Meta نفسها، مثل اسم مستخدم من قبل أو نص لا تراجعه. ويعيده كذلك مفتاح تطبيق مربوط بلغ أقصى ما يُسمح له به من القوالب، ويبيّن message ذلك.
503templates_unavailableلم ترد Meta على قراءة قائمة قوالب الرقم، وهي ما تحتاجه نقاط القوالب والإرسال قبل أي شيء، أو لم ترد على تعديل في قالب. لم يُرسل شيء ولم يُخصم شيء، وبقي القالب كما هو، فأعد المحاولة بعد قليل.

كل الأخطاء الممكنة

الحالةerrorالمعنى
429too_many_requestsتجاوزت حد الطلبات لكل مفتاح، وهو افتراضيًا 120 طلبًا في الدقيقة في نافذة ثابتة من 60 ثانية. ويُفحص قبل المصادقة.
401unauthorizedمفتاح غائب أو غير معروف أو ملغى أو من غير نوع النقطة، أو شريك غير معروف أو موقوف.
400service_requiredمفتاح شريك بلا application أو service في جسم الطلب.
404service_not_foundمفتاح شريك، لكن application/service لا يطابق أي تطبيق من تطبيقات هذا الشريك.
403account_not_activeالتطبيق لم يُعتمد بعد، أو الحساب موقوف، أو عطّل الشريك هذا التطبيق. وكل هذه الأسباب تعيد الاستجابة نفسها.
400invalid_jsonجسم الطلب ليس JSON صالحًا.
400invalid_requestفي start: الحقلان to وphone غائبان أو فارغان. وفي check: الحقل id أو code غائب.
422unsupported_channelاسم قناة غير معروف، أو قناة معروفة غير مفعّلة: واتساب حتى يفتحه توكيد لكل الحسابات، أو البريد: لا تُرسل الرموز بالبريد (توكيد للبريد الإلكتروني يرسل بريد النشاط نفسه، https://tawked.com/ar/email).
422sandbox_unsupported_channelمفتاح تجربة ⁦tk_test_⁩ على قناة لا تتسع لختم [تجريبي]، فقالب واتساب الثابت من Meta لا مكان فيه له.
422invalid_destinationالوجهة لا تطابق أي صيغة جوال سعودي مقبولة.
422sandbox_unverified_destinationمفتاح تجربة، والوجهة ليست رقم الجوال الذي وثّقه مالك الحساب عند التسجيل.
429sandbox_quota_exceededبلغ التطبيق سقف إرسال التجربة مدى الحياة، وهو 10 رسائل.
429rate_limitedبلغت الوجهة حدها في الساعة. ويختلف عن too_many_requests أعلاه: حالة HTTP نفسها وقيمة error مختلفة.
402insufficient_creditsالرصيد المسبق للحساب أقل من سعر القناة.
502send_failedفشل استدعاء مزوّد التسليم، ويُعاد الخصم إلى رصيدك تلقائيًا.
404not_foundمعرّف غير معروف، أو معرّف يخص حسابًا أو تطبيقًا غير حساب المفتاح المستدعي وتطبيقه.
500internal_errorخطأ غير متوقع في الخادم. اذكر ترويسة X-Request-Id عند الإبلاغ عنه.
401key_expiredانقضى تاريخ انتهاء المفتاح expires_at. ويُفحص فور التعرف على المفتاح، قبل القائمة المسموحة ونطاق الصلاحية.
403ip_not_allowedعنوان IP للمستدعي خارج القائمة المسموحة للمفتاح ip_allowlist، وهي عناوين محددة أو نطاقات CIDR، بصيغتي IPv4 وIPv6.
403insufficient_scopeلم يُمنح المفتاح هذا الاستدعاء: مفتاح بصلاحية مخصّصة لا تشمل هذا المنتج، أو بمستوى أدنى مما يحتاج إليه الاستدعاء، كمفتاح يتحقق والاستدعاء يرسل. وتذكر ترويسة الاستجابة WWW-Authenticate الصلاحية التي يحتاج إليها الاستدعاء. ويُفحص ذلك فور التعرف على المفتاح، قبل account_not_active وشكل الطلب.
403application_pausedأوقف حارس الحماية من الضخ التطبيق تلقائيًا بعد قفزة في الوجهات الجديدة خلال ساعة، ويستأنفه المالك أو أحد المشرفين.
429ip_rate_limitedمرّر المستدعي client_ip، وأرسل هذا العنوان في الساعة الأخيرة أكثر مما يسمح به max_per_ip_per_hour للتطبيق.
429spend_cap_reachedإنفاق اليوم بتوقيت الرياض مع هذا الإرسال يتجاوز daily_spend_cap_halalas للتطبيق.
409not_resendableعملية التحقق في حالة نهائية: تحققت أو فشلت أو انتهت أو أُلغيت. ويتضمن الرد status الحالية.
409not_cancelableعملية التحقق في حالة نهائية، ويتضمن الرد status الحالية.
429resend_limit_reachedاستخدمت عملية التحقق هذه إعاداتها الثلاث.
403live_key_requiredمفتاح تجربة ⁦tk_test_⁩، ولا بيئة تجربة لواتساب بعد. استخدم المفتاح الفعلي للتطبيق.
403whatsapp_not_enabledواتساب موقوف لهذا التطبيق. تواصل مع الدعم إن كنت تعتقد أن هذا خطأ.
409no_whatsapp_numberلا رقم واتساب مربوطًا بهذا التطبيق بعد. اربط رقمًا من قسم الرقم في تبويب الإشعارات في صفحة التطبيق باللوحة، وهي الخطوة الأولى في «خطوات البدء».
409number_disconnectedالرقم مربوط لكنه غير متصل من جهة Meta الآن، فالويبهوك غير مثبّت أو تبلّغ Meta عن حالة غير CONNECTED. وتعرض صفحة الإشعارات في اللوحة صحة الرقم.
422unknown_templateلا قالب بهذا الاسم، وبهذه اللغة إن حُددت، في حساب واتساب للأعمال للرقم. ويعرض ⁦GET /v1/whatsapp/templates⁩ القوالب الموجودة.
422template_not_approvedالقالب موجود لكن Meta لم تعتمده، ويحمل message حالة Meta، مثل PENDING أو REJECTED أو PAUSED.
422template_category_not_allowedقالب من فئة AUTHENTICATION أُرسل بمفتاح شريك. ترسل مفاتيح الشركاء قوالب الخدمة والتسويق، ويرسل المفتاح الفعلي للتطبيق قوالب المصادقة. ويعيده كذلك تعديل قالب مصادقة عبر ⁦PATCH /v1/whatsapp/templates/{template_id}⁩، فنصّه نص Meta، ومفتاح تطبيق مربوط مع أي فئة غير UTILITY، في الإرسال أو في قالب ينشئه أو يعدّله.
422consent_opted_outقالب تسويقي إلى مستلم طلب من هذا التطبيق إيقاف رسائله التسويقية، بكتابة «إيقاف» إلى الرقم أو بإيقاف عروضه من واتساب. لم يُرسل شيء ولم يُسجَّل ولم يُخصم. وتبقى قوالب الخدمة والمصادقة تصله.
422unsupported_templateيحتاج القالب شيئًا لا تحمله هذه النقطة بعد: ترويسة فيديو أو ملف أو موقع (أما ترويسة الصورة فتُرسل بـ ⁦header.image.link⁩)، أو زرًا أو مكوّنًا يأخذ معاملًا غير نصي، مثل زر نسخ رمز الخصم في قالب تسويقي أو flow أو كتالوج أو carousel أو عرض محدود، أو متغيرات مسمّاة ومرقّمة معًا في النص. ويبيّن message أيها.
422invalid_paramsقيمة متغير ناقصة أو فارغة أو غير متوقعة، أو أطول من 1024 حرفًا، أو فيها سطر جديد أو تاب أو رمز تحكم ترفضه Meta، أو القالب بعدة لغات ولم يُحدد lang، أو وصل قالبَ المصادقة buttons أو code ليس من 4 إلى 15 حرفًا أو رقمًا، أو قالب يبدأ بصورة بلا ⁦header.image.link⁩، أو برابط لا يبدأ بـ https، أو وصلت صورة قالبًا لا يبدأ بها. ويسمّي message المتغير.
403template_not_managedمفتاح تطبيق مربوط مع قالب لم ينشئه ذلك التطبيق لهذا التطبيق. يعدّل هذا المفتاح ويحذف القوالب التي أنشأها وحدها، وهي التي قيمة managed فيها true.
409template_not_editableلا يتغيّر القالب عبر API وهو على حاله، ويبيّن status السبب. في التعديل: حالة القالب إن لم تكن APPROVED أو REJECTED أو PAUSED، أو MEDIA_HEADER لقالب يبدأ بصورة أو وسائط أخرى، وهذا يُعدَّل من اللوحة. وفي التعديل والحذف: META_SAMPLE لقالب من نماذج Meta.
409template_in_useما زال شيء يرسل القالب، فلا يقبل التعديل أو الحذف. ويعدّد used_by ما هو، من campaign لحملة لم تنتهِ، وautomation لأتمتة مفعّلة، وstore_notice لإشعار متجر مفعّل، بهذا الترتيب. يوقفه صاحب الحساب أو يغيّر قالبه من اللوحة أولًا.
409idempotency_in_progressطلب بمفتاح Idempotency-Key نفسه ما زال قيد التنفيذ. انتظر رده، أو أعد المحاولة بعد لحظة.
409idempotency_key_reusedاستُخدم مفتاح Idempotency-Key هذا من قبل لطلب مختلف. استخدم مفتاحًا لكل تغيير.
422template_refusedرفضت Meta القالب بعد أن اجتاز فحوص توكيد، ويحمل message عبارة Meta نفسها، مثل اسم مستخدم من قبل أو نص لا تراجعه. ويعيده كذلك مفتاح تطبيق مربوط بلغ أقصى ما يُسمح له به من القوالب، ويبيّن message ذلك.
503templates_unavailableلم ترد Meta على قراءة قائمة قوالب الرقم، وهي ما تحتاجه نقاط القوالب والإرسال قبل أي شيء، أو لم ترد على تعديل في قالب. لم يُرسل شيء ولم يُخصم شيء، وبقي القالب كما هو، فأعد المحاولة بعد قليل.

حدود المعدل

الحد الافتراضي ⁦120⁩ طلبًا في الدقيقة لكل مفتاح، في نافذة ثابتة من 60 ثانية. ويسمح بالمرور عند أي خلل في التخزين المؤقت، فهو دفاع إضافي فوق سقف الرصيد وسقف الوجهة، لا الضابط الأساسي.

معرّف الطلب

تحمل كل استجابة ترويسة X-Request-Id، فاذكرها إن راسلت الدعم عن طلب بعينه.

ويبهوك العميل

اضبط رابطًا وسر توقيع لكل تطبيق، فتصلك رسالة موقّعة بكل نتيجة، بلا استعلام متكرر.

verification.verifiedverification.failedverification.expired
  • تُضبط لكل تطبيق في صفحة «الويبهوك» الخاصة به: رابط وسر توقيع، يُكشف عند الطلب ويمكن تدويره. والتطبيق الذي يزوّده شريك ليس له ويبهوك خاص: تذهب نتائج التحقق فيه إلى سجل أحداث الشريك، وإلى ويبهوك الشريك إن اشترك فيها، مع external_id الخاص بالشريك.
  • يُطلق verification.verified وverification.failed من check، ويُطلق verification.expired من مسح انتهاء الصلاحية الدوري، ومن أي check أو GET يكتشف الانتهاء.
  • يحمل كل تسليم الترويسات tawked-timestamp وtawked-signature وtawked-event، والتوقيع HMAC-SHA256 بصيغة hex للنص ⁦"{timestamp}.{raw body}"⁩ بسر التوقيع لديك. تحقق من التوقيع مقابل جسم الطلب الخام قبل الوثوق بأي محتوى.
  • يُعاد التسليم تلقائيًا بفواصل متزايدة لأي رد غير 2xx، بالمهمة والجدول المستخدمين لويبهوك الشركاء، وعدد المحاولات أدناه. ويعرض سجل التسليم في اللوحة كل محاولة.
  • يجب أن يكون الرابط https على عنوان عام، وأن يرد عليه خادمك مباشرة: إعادة التوجيه لا تُتبع وتُحسب محاولة فاشلة.
  • حدث التجربة المرسل من صفحة الويبهوك في اللوحة هو عيّنة verification.verified واحدة يحمل غلافها أيضًا ⁦"test": true⁩، وقيم data فيها مصطنعة: المعرّف أصفار، والمرجع test-event، والنمط test. لا يحمل أي حدث حقيقي الحقل test، فتجاوز آثارك الجانبية عند وجوده.
  • ويستقبل التطبيق المربوط بواتساب أيضًا الأحداث message.sent وmessage.delivered وmessage.read وmessage.failed على الرابط نفسه وبالغلاف نفسه، كما في رسائل واتساب.

مثال المحتوى

{
    "event": "verification.verified",
    "data": {
        "id": "b7e5c2b0-9c1a-4e2f-8f2a-3a6b0e9d1c44",
        "status": "verified",
        "application_id": "c2a10f3e-8b7a-4d2e-9c1a-1a2b3c4d5e6f",
        "reference": "order-42",
        "channel": "sms",
        "to": "+966551234567",
        "mode": "live",
        "attempts": 1,
        "expires_at": "2026-09-01T12:34:56.789Z",
        "verified_at": "2026-09-01T12:31:02.145Z",
        "created_at": "2026-09-01T12:29:56.789Z"
    },
    "sent_at": "1788265862201"
}

التحقق من التوقيع في Node.js

const [timestamp, signature] = [
  req.headers["tawked-timestamp"],
  req.headers["tawked-signature"],
];
const expected = crypto
  .createHmac("sha256", webhookSecret)
  .update(`${timestamp}.${rawBody}`)
  .digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) throw new Error("bad signature");

يُعاد الإرسال لأي رد غير 2xx، والحد الأقصى للمحاولات ⁦5⁩، بفواصل متزايدة بالدقائق: ⁦1, 5, 30, 120, 360⁩.

واجهة الشركاء

تستخدم منصات إعادة البيع، مثل تطبيقات سلة وزد، مفتاح ⁦tk_partner_⁩ واحدًا لتزويد متاجر كثيرة عبر ⁦/v1/partner/applications⁩، مع ويبهوك لأحداث المراجعة والرصيد.

دليل الشركاء

هذا المرجع متاح للآلات أيضًا بصيغة Markdown خام: /llms.txt · /llms-full.txt

راسلنا على واتساب