Skip to main content
تُرحّب قائمة الرد الصوتي (IVR) بالمتّصل، وتقرأ عليه بعض الخيارات، ثم توجّهه حسب الزرّ الذي يضغطه — “اضغط 1 للمبيعات، اضغط 2 للدعم.” تُنشئ القائمة مرّة واحدة عبر هذه الواجهة (أو لوحة التحكّم)، وتربطها بأحد أرقام Wave لديك، فتُقدّمها Wave مباشرةً لكلّ متّصل — دون إعادة نشر. خلف الكواليس تُترجَم القائمة إلى أمر WaveML وهو <Gather> يُشغّل التحية ويجمع ضغطة زرّ واحدة، ثم يُنفّذ الفرع الخاصّ بذلك الرقم. هذه الواجهة هي طبقة التأليف فوق WaveML — تصف القائمة بصيغة JSON وتحوّلها Wave إلى مسار مكالمة.
تبدأ هذه الصفحة بالقائمة أحادية المستوى — تحية واحدة ومجموعة خيارات واحدة، ينهي كلٌّ منها المكالمة أو يحوّلها. للقوائم الفرعيّة و«اضغط 9 للقائمة الرئيسيّة» والتكرار عند عدم الإدخال، اكتب قائمة متعدّدة المستويات (graph) — انظر قسم «القوائم متعدّدة المستويات (Graph)» أدناه. أداة البناء المرئيّة ميزة منفصلة لاحقة.

المصادقة والطبقات

تتطلّب جميع نقاط /v1/callflows مفتاح واجهة بنطاق callflows:read أو callflows:write، أو جلسة لوحة تحكّم. يمكنك التأليف والاختبار بمفتاح sandbox (sk_sandbox_)، أمّا تقديم قائمة إلى مكالمة واردة حقيقية فيتطلّب مفتاح production (sk_live_) ومؤسسة بطبقة production ورقمًا مربوطًا (راجع ربط رقم أدناه).

تعريف القائمة

القائمة عبارة عن definition بصيغة JSON: تحية، وفروع لوحة المفاتيح، واحتياطيّ اختياريّ عند عدم ضغط المتّصل أيّ زرّ.

التحية والإجراءات

التحية وكلّ إجراء فرع هو أحد هذه الأنواع. إجراء الفرع طرفيّ — ينهي المكالمة أو يحوّلها.
أهداف dial مقيّدة بأرقام سعوديّة (KSA) — حماية من الاحتيال، لأنّ <Dial> يجسر المتّصل إلى مسار جديد.

مُدخل الفرع (حمولة webhook خاصّتك)

امنح الفرع كائن input، فتدمجه Wave في webhook باسم call.input حين يختار المتّصل ذلك الخيار — نقطة ربط تكاملك لمعرفة ما اختاره المتّصل.
  • حتّى 20 حقلًا؛ القيم نصّ (≤512) أو عدد أو قيمة منطقيّة.
  • المفاتيح call_id وdigits وnode وlimit_reached محجوزة (تضبطها Wave) وتُرفض.

إنشاء قائمة

POST /v1/callflows — أنشئ قائمة بالاسم. مرّر "activate": true لجعلها مباشرة فورًا.
يُعيد 201 Created القائمة، متضمّنةً سجلّ إصداراتها:
الاسم المكرّر يُعيد 409 — استخدم PUT لإضافة إصدار بدلاً من ذلك.

سرد القوائم وجلبها

يسرد GET /v1/callflows صفًّا واحدًا لكلّ قائمة (إصدارها النشط أو الأحدث):
يُعيد GET /v1/callflows/{name} القائمة كاملةً — definition الإصدار النشط (أو الأحدث) مع سجلّ versions الكامل. 404 إن لم تكن القائمة موجودة. أضف ?version=N لقراءة إصدار واحد بدلًا من ذلك — مثلًا مسودّة محفوظة غير مباشرة، أو إصدار أقدم: GET /v1/callflows/auth-ivr?version=3. للاستجابة الشكل نفسه؛ ويُبيّن is_active هل ذلك الإصدار مباشر. 404 إن لم يكن ذلك الإصدار موجودًا؛ و400 إن لم يكن N عددًا صحيحًا موجبًا. لكلّ مسار kind: إمّا menu (أحاديّ المستوى) أو graph (متعدّد المستويات). يعود definition بالشكل الذي كتبته به: القائمة بحقولها prompt وgather وbranches وno_input، والـ graph مع حقول ui. لذا يمكنك إرسال definition الذي قرأته إلى PUT دون تغيير. المسار الذي أعدّته Wave لك (لا عبر هذه الواجهة) قد يعود بشكل أبسط: يُظهر كلّ خيار إجراءه الرئيسيّ فقط. إن أرسلته إلى PUT، يحفظ الإصدار الجديد هذا الشكل الأبسط.

الإصدارات والاسترجاع

القوائم غير قابلة للتغيير وتُضاف فقط. التعديل لا يغيّر إصدارًا في مكانه أبدًا — بل يُضيف إصدارًا جديدًا.
  • PUT /v1/callflows/{name} بتعريف definition جديد (وactivate اختياريّ) يُضيف الإصدار التالي. 404 إن لم تكن القائمة موجودة.
  • لتجنّب ضياع التعديلات، أرسل أيضًا base_version: الإصدار الذي قرأته وعدّلته. إن حفظ شخص آخر إصدارًا أحدث قبلك، يُعيد PUT الرمز 409 CALLFLOW_VERSION_CONFLICT ولا يكتب شيئًا؛ وتذكر الرسالة أحدث إصدار. اقرأ ذلك الإصدار، وطبّق تعديلك مرّة أخرى، وأرسله مع base_version الجديد. دون base_version، يُضيف PUT دائمًا إصدارًا (كما سبق).
  • POST /v1/callflows/{name}/activate بـ { "version": N } يجعل الإصدار N مباشرًا — الاسترجاع هو ببساطة تفعيل إصدار أقدم. 404 إن لم يكن ذلك الإصدار موجودًا.
يُعيد كلاهما كائن القائمة بالإصدار المُفعَّل حديثًا.

ربط رقم

POST /v1/callflows/{name}/bind-number يوجّه أحد أرقام Wave لديك إلى الإصدار النشط للقائمة — عندها تُنفّذ المكالمات الواردة إلى ذلك الرقم القائمة.
يُعيد { "bound": true }. الأرقام تُوفّرها Wave — راجع الأرقام الافتراضيّة.

إيقاف قائمة

DELETE /v1/callflows/{name} يوقف القائمة إيقافًا ناعمًا: تتوقّف عن خدمة المتّصلين ويُلغى ربط أيّ رقم، لكن يُحفَظ سجلّ الإصدارات (يمكنك إعادة إنشائها لاحقًا). يُعيد { "retired": true }؛ و404 إن لم تكن القائمة موجودة.

webhook باسم call.input

حين يضغط المتّصل رقمًا، تُرسل Wave webhook باسم call.input. تحمل data الأرقام المضغوطة digits إضافةً إلى كائن input لذلك الفرع — فيعرف نظامك الخلفيّ بالضبط ما اختاره المتّصل:
سجّل نقطة نهاية وتحقّق من التوقيع كما هو موضّح في Webhooks.

القوائم متعدّدة المستويات (Graph)

الـ graph قائمة لها أكثر من مستوى. تكتبها مجموعةً من العُقد (nodes) المُسمّاة. تقوم كلّ عقدة بعمل واحد وتشير إلى العقدة التالية next. تبدأ المكالمة من العقدة start. أرسل الـ graph إلى نقاط القائمة نفسها: POST /v1/callflows وPUT /v1/callflows/{name}، مع "kind": "graph" داخل definition. التفعيل والاسترجاع والإيقاف وربط الرقم تعمل كما في القائمة أحاديّة المستوى.

مثال: مستويان، و«اضغط 9 للقائمة الرئيسيّة»

العُقد

مُعرّف العقدة حروف إنجليزيّة صغيرة وأرقام، من 1 إلى 12 حرفًا (main، sales2). يمكن أن تحمل كلّ عقدة أيضًا ui: { "x": number, "y": number, "label"?: string } — بيانات تخطيط لأداة بناء مرئيّة. label هو اسم العرض للعقدة بأيّ لغة (مثلًا "القائمة الرئيسية")، من 1 إلى 40 حرفًا بعد حذف المسافات من الطرفين، ودون أحرف تحكّم أو أحرف تجاوز الاتجاه. تحذف Wave المسافات من طرفي label، وتحفظ الحقل ui وتُعيده دون أيّ تغيير آخر، ولا يؤثّر في المكالمة: يبقى مُعرّف العقدة هو مفتاح التوجيه، ولا يصل label إلى المتّصل ولا إلى الـ webhook.

لا إدخال، وزرّ خاطئ، وحدّ الدورات

  • لم يُضغط زرّ قبل timeout_seconds: تنتقل المكالمة إلى عقدة no_input في القائمة.
  • زرّ ليس خيارًا: تنتقل المكالمة إلى عقدة invalid في القائمة.
  • إن لم تضبط no_input أو invalid، تُعيد Wave تشغيل القائمة نفسها.
  • للمكالمة 20 دورة قائمة على الأكثر. عند القائمة التالية تنتقل المكالمة إلى عقدة on_limit. إن لم توجد on_limit تنتهي المكالمة.

القواعد التي تتحقّق منها Wave عند الحفظ

ترفض Wave الـ graph برمز 400 وتُسمّي الحقل الخاطئ (مثل definition.nodes.sales.options.0.next) في هذه الحالات:
  • start أو on_limit ليست عقدة، أو next يشير إلى عقدة غير موجودة.
  • عقدة لا يمكن الوصول إليها من start. (العُقد التي لا تصلها إلا on_limit مسموحة.)
  • للـ graph أكثر من 50 عقدة، أو لقائمة أكثر من 12 خيارًا أو الرقم نفسه مرّتين.
  • حلقة لا تمرّ بعقدة menu. (لن تتوقّف المكالمة أبدًا.)
  • مسار on_limit يمكن أن يصل إلى عقدة menu.
  • هدف dial ليس رقمًا سعوديًّا، أو audio_ref (في عقدة play أو تحية قائمة أو moh) ليس ملفًّا رفعته مؤسّستك.

call.input في الـ graph

ترسل Wave webhook واحدًا باسم call.input في كلّ مرّة يجيب فيها المتّصل عن عقدة قائمة — ويشمل ذلك عدم الإدخال والزرّ الخاطئ. تحمل data الأرقام digits، وinput الخيار، وnode (مُعرّف عقدة القائمة). حين تصل المكالمة إلى حدّ الـ 20 دورة، تحمل data أيضًا "limit_reached": true.
بعد عقدة dial أو enqueue تنتهي المكالمة، ولا ترسل Wave call.input آخر لها.

المقاطع الصوتيّة

تُشغّل تحية أو إجراء play ملفًّا مسجّلًا بدلاً من TTS — مناسب لتحية مُنتَجة، ويتجاوز تأخّر التركيب الصوتيّ. ارفع الملفّ أوّلًا، ثم أشِر إلى audio_ref المُعاد. POST /v1/callflows/audio يأخذ ملفّ WAV مُرمَّزًا بـ base64 (يُوصى بـ 8 kHz أحاديّ 16-bit PCM — جودة الهاتف) ويُعيد audio_ref مُستضافًا لدى Wave:
استخدم audio_ref في play:
رفع الملفّات الصوتيّة قيد الإطلاق. حتّى تفعيله لحسابك، يُعيد الرفع 503 وتستخدم القوائم تحيات say (TTS). يجب أن يكون audio_ref ملفًّا رفعته أنت — تُرفض الروابط العشوائيّة.

الخطوات التالية

  • WaveML — الأوامر التي تُترجَم إليها القائمة، والمسارات المخصّصة الكاملة.
  • Webhooks — استقبال call.input والتحقّق منه.
  • الطوابير — حيث يُرسل فرع enqueue المتّصل.