الأتمتة
الأتمتة قاعدة تشغّلها المنصّة نيابة عنك: إذا حدث كذا وتحققت هذه الشروط، فافعل كذا. والتعريف بيانات لا شيفرة — مفردات مغلقة من المُشغّلات والشروط والإجراءات، تُتحقَّق عند الحفظ — فلا شيء يُنشر ولا شيء اعتباطي يُنفَّذ.
الأتمتة
مُشغّل واحد، وشجرة شروط اختيارية، وقائمة إجراءات مرتّبة. ويحدّد priority أي قاعدة تعمل أولًا حين تطابق عدة قواعد الحدث نفسه.
| الحقل | الوصف |
|---|---|
| id | المعرّف العام للأتمتة. |
| trigger_type, trigger | ما يبدؤها، وخيارات المُشغّل نفسه. |
| conditions | شجرة يجب أن تتحقق قبل تنفيذ الإجراءات. |
| actions | ما يجب فعله، بالترتيب. |
| priority | الأقل يعمل أولًا بين القواعد المطابقة للحدث نفسه. |
| enabled | القواعد المعطّلة لا تطابق شيئًا، فورًا. |
| version | يزيد مع كل تغيير في التعريف، ويسجّل كل تشغيل نسخته. |
| stats | run_count و success_count و failure_count و last_run_at و last_error_at و last_error. |
| next_run_at | لمُشغّل الجدولة فقط، وإلا فهو null. |
المصادقة والنطاقات
لا يوجد نطاق قراءة
كل مسار في هذا القسم — بما فيه القراءات — يتطلب automations.manage. لا يوجد دور يستطيع الاطلاع على الأتمتة فقط، فلا تتوقع أن يعمل.
نقاط النهاية
تقبل القائمة مرشِّحَي enabled وtrigger_type وتُرقَّم بالمؤشر، وسجل التشغيل مُرقَّم كذلك ويقبل status.
مفردات التعريف
كل ما يلي قائمة مغلقة. وأي شيء خارجها يُرفض عند الحفظ بـ AUTOMATION_INVALID_DEFINITION، ويُتحقَّق من PATCH مقابل التعريف المدموج لا مقابل التعديل وحده.
المُشغّلات
| القيمة | الوصف |
|---|---|
| message_received | رسالة واردة. يقبل match (any و equals و contains و starts_with و regex) و value و case_sensitive. |
| conversation_opened | فتح محادثة. يقبل reason (created و reopened) و opened_by (inbound و outbound). |
| conversation_closed | إغلاق محادثة. |
| conversation_assigned | إسناد محادثة إلى أحد. |
| contact_created | إنشاء جهة اتصال من أي مصدر. |
| contact_tagged | إضافة وسم. يقبل tag اختياريًا لتضييقه. |
| contact_untagged | إزالة وسم. يقبل tag اختياريًا. |
| schedule | ساعة لا حدث. ويعرض next_run_at الموعد التالي. |
الشروط
| النوع | الشكل | الوصف |
|---|---|---|
| field | field, operator, value?, key? | يقارن أحد الحقول المنشورة — contact.* و conversation.* و message.* و channel.* — بقيمة. ويأخذ contact.attribute اسم السمة في key. |
| tag | operator, value | هل لدى جهة الاتصال وسم: has أو not_has. |
| time_window | operator, timezone, from, to, days? | وقت من اليوم في أيام محددة وبمنطقة زمنية محددة: within أو outside. |
| business_hours | operator | داخل ساعات عمل مساحة العمل أو خارجها، ويُقيَّم على الخادم. |
| group | operator, conditions[] | يضمّ الشروط تحت and أو or. ويمكن للمجموعات أن تحوي مجموعات. |
يقبل شرط الحقل أحد equals وnot_equals وcontains وnot_contains وstarts_with وends_with وregex وin وnot_in وgt وgte وlt وlte وis_set وis_empty، مع case_sensitive اختياريًا.
الإجراءات
| النوع | الشكل | الوصف |
|---|---|---|
| send_message | text | رد بنص حر على المحادثة. |
| send_template | template_slug, variables? | قالب معتمد مع متغيّراته. |
| assign_conversation | assignee_type, assignee_id | إسناد المحادثة إلى عضوية مستخدم أو إلى فريق. |
| add_tag | tag | إضافة وسم إلى جهة الاتصال. |
| remove_tag | tag | إزالة وسم من جهة الاتصال. |
| close_conversation | reason? | إغلاق المحادثة، مع تسجيل سبب اختياريًا. |
| reopen_conversation | — | إعادة فتح المحادثة. |
| add_note | body | إضافة ملاحظة داخلية. ولا تُرسل إلى جهة الاتصال أبدًا. |
| call_webhook | url, method?, headers? | استدعاء نقطة نهاية HTTP لديك. بـ GET أو POST أو PUT أو PATCH. |
curl -X POST https://whats.azzamkh.sa/api/v1/automations \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Tag pricing questions",
"trigger_type": "message_received",
"trigger": { "match": "contains", "value": "price" },
"conditions": [
{ "type": "business_hours", "operator": "within" }
],
"actions": [
{ "type": "add_tag", "tag": "pricing" },
{ "type": "assign_conversation",
"assignee_type": "team", "assignee_id": "tm_..." }
],
"priority": 10
}'
# 201 Created
# {
# "id": "atm_...",
# "enabled": true,
# "priority": 10,
# "version": 1,
# "stats": {
# "run_count": 0, "success_count": 0, "failure_count": 0,
# "last_run_at": null, "last_error_at": null, "last_error": null
# },
# "next_run_at": null,
# ...
# }تشغيل تجريبي للقاعدة
يقيّم POST …/test الشروط الحقيقية مقابل موضوع حقيقي ولا ينفّذ شيئًا. والمعاينة والمحرّك يتشاركان مقيّمًا واحدًا، فما لا يعمل هنا لن يعمل في الإنتاج. ويجيب بـ trigger_matched وconditions_matched وwould_run وحكمٍ لكل إجراء، وهو محدود بـ 60 طلبًا في الدقيقة لكل مساحة عمل.
curl -X POST https://whats.azzamkh.sa/api/v1/automations/atm_.../test \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "conversation_id": "cnv_...", "message_text": "what is the price" }'
# 200 OK
# {
# "automation_id": "atm_...",
# "trigger_matched": true,
# "conditions_matched": false,
# "would_run": false,
# "reason": "condition_not_met",
# "subject": {
# "conversation_id": "cnv_...", "contact_id": "cnt_...",
# "message_id": null, "channel_id": "ch_..."
# },
# "actions": [
# { "index": 0, "type": "add_tag", "would": "skip",
# "reason": "conditions_not_met" }
# ],
# "evaluated_at": "2026-08-14T09:00:00.000Z"
# }سجل التشغيل
يُسجَّل كل تنفيذ سواء فعل شيئًا أم لا. ويحمل التشغيل automation_version التي عمل بها، والموضوع الذي عمل عليه، ونتيجةً لكل إجراء، وduration_ms.
| الحالة | الوصف |
|---|---|
| pending | حُجز ولم يبدأ. |
| running | قيد التنفيذ. |
| completed | نجحت كل الإجراءات. |
| partial | نجح بعض الإجراءات وأخفق بعضها. |
| failed | أخفق التشغيل، والسبب في error. |
| skipped | طابق المُشغّل ولم تتحقق الشروط. |
| blocked | رفضه حارس الحلقات أو حدّ التنفيذ. |
- يوجد
chain_depthوcausation_run_idلأن الإجراء قد يشغّل قاعدة أخرى. والمحرّك يحدّ السلسلة بدل أن يترك قاعدتين تجيبان إحداهما الأخرى إلى الأبد. - يعرض كل عنصر في
actionsحقلstatus(succeeded و skipped و failed) معreason، فيخبرك التشغيل الجزئي بالخطوة التي توقفت تحديدًا. - يُنسب كل تشغيل إلى نسخة التعريف التي نفّذها، فتعديل قاعدة لا يعيد كتابة تاريخ ما جرى بالفعل.
الأخطاء المهمة هنا
| الرمز | HTTP | متى يحدث |
|---|---|---|
| AUTOMATION_NOT_FOUND | 404 | لا توجد أتمتة بهذا المعرّف في مساحة العمل هذه. |
| AUTOMATION_RUN_NOT_FOUND | 404 | لا يوجد تشغيل بهذا المعرّف لهذه الأتمتة. |
| AUTOMATION_INVALID_DEFINITION | 422 | يستخدم التعريف شيئًا خارج المفردات أو يناقض نفسه. |
| AUTOMATION_LIMIT_REACHED | 409 | أوقفه حدّ تنفيذ أو حارس حلقات. |
| ENTITLEMENT_LIMIT_REACHED | 409 | الخطة لا تشمل الأتمتة أو بلغت حدًّا. |
ردّا الترحيب والغياب أتمتتان أيضًا — انظر ساعات العمل والردود التلقائية. وكل رمز وحالته في صفحة الأخطاء.