
# واجهة برمجة تطبيقات الحملات (Campaigns API)

تجمع الحملة كل ما يحتاجه روبوت الذكاء الاصطناعي للتحدث إلى جهات الاتصال الخاصة بك: تعليماته، والقنوات التي يعمل من خلالها، وساعات نشاطه، وسلوك المتابعة الخاص به. تتيح لك واجهة برمجة تطبيقات الحملات (Campaigns API) إدراج الحملات وإنشائها وتحديثها وتكرارها وتمكينها وأرشفتها وضبطها بدقة من خلال الكود الخاص بك بدلاً من لوحة التحكم.

جميع نقاط النهاية أدناه نسبية إلى عنوان URL الأساسي `https://api.youraiconnector.com/v1`. يجب أن تكون كل طلبية مصادقاً عليها — راجع [الوصول إلى واجهة برمجة التطبيقات](../integrations/api-access.md) و[المصادقة](authentication.md) لمعرفة كيفية الحصول على مفتاح واجهة برمجة التطبيقات الخاص بك وتمريره. الوصول إلى واجهة برمجة التطبيقات هو ميزة مدفوعة؛ وبدونها، يتم رفض الطلبات بـ `403`.

> **تنبيه:** تعرض بعض الأمثلة نموذج استعلام `?apiKey=YOUR_API_KEY` البسيط، بينما يستخدم البعض الآخر رأس `X-API-Key`. كلاهما يعمل في كل مكان — استخدم أياً منهما يناسب إعداداتك.

---

## أنواع الحملات

عند إنشاء حملة، يجب عليك اختيار أحد هذه الأنواع:

| النوع | الغرض منه |
|---|---|
| `Incoming from Unknown Contacts` | يرد البوت على الأشخاص الذين يراسلونك للمرة الأولى. |
| `Outgoing` | يبدأ البوت محادثات مع جهات الاتصال التي تضيفها إلى الحملة. |
| `Keywords` | **خاملة - لا تستخدمها.** حملة `Keywords` خاملة: لا تزال مقبولة للتوافق مع الإصدارات السابقة، لكنها غير مرئية للتوجيه الوارد على أي قناة ولا تقرأ أي كلمات رئيسية للمشغلات الخاصة بها. استخدم نقطة دخول (Entry Point) من نوع **كلمة رئيسية (Keyword)** على وكيل الذكاء الاصطناعي بدلاً من ذلك. |
| `Combined` | مزيج من السلوكيات الواردة والصادرة. |

**حالة الأحرف لا تهم.** `type`، و`status`، و`booking_provider`، و`first_response_mode`، و`bot.anthropic_model`، و`bot.ai_speed` جميعها تقبل أي حالة أحرف — فـ `"live"`، و`"Live"`، و`"LIVE"` هي نفس الشيء — ويتم تخزين القيمة في شكلها القياسي، وهو ما يظهر عند قراءة الحملة. الاستثناء الوحيد هو زوج الإيقاف المؤقت: `"Paused"` و`"paused"` هما حالتان مختلفتان تماماً، لذا يتم رفض التهجئة الغامضة مثل `"PAUSED"` مع إظهار `400` يطلب منك اختيار إحداهما.

### حالتا الإيقاف المؤقت

| الحالة | من يقوم بتعيينها | ماذا تعني |
|---|---|---|
| `Paused` | عمليات التحقق من الأمان الخاصة بالمنصة (انخفاض التفاعل، أخطاء الإرسال المتكررة، الوصول إلى حد معين) وواجهات الوكلاء والبث الأحدث | الحملة معلقة. يمكن لعملية المسح المجدولة رفع الإيقاف المؤقت للأمان تلقائيًا بمجرد زوال السبب. |
| `paused` | زر الإيقاف المؤقت في لوحة التحكم، مقترنًا بـ `resumed` عند الاستئناف | قام شخص بإيقافها يدويًا. يتم إلغاء عمليات الإرسال المجدولة وإعادة بنائها عند الاستئناف. |

كلاهما يوقف الحملة: لا يتم تشغيل توجيه الرسائل الواردة إلا عندما تكون الحالة `Live` تمامًا. **من واجهة برمجة التطبيقات (API)، استخدم `Paused` للإيقاف المؤقت و `Live` للاستئناف** — الزوج المكتوب بأحرف صغيرة مخصص لزر لوحة التحكم ويتم الحفاظ على عمله من أجل ذلك.

لا يمثل أي من هذين الحالتين ما يحدث عندما يتوقف الذكاء الاصطناعي عن الرد داخل محادثة واحدة. هذا مفتاح تبديل خاص بكل جهة اتصال، `is_bot_active` في جهة الاتصال — يتم تعيينه عندما يتولى إنسان زمام الأمور، أو عندما تختار جهة الاتصال إلغاء الاشتراك، أو عندما ينهي الذكاء الاصطناعي الدردشة. تظل حالة الحملة نفسها دون تغيير، وتستمر كل محادثة أخرى فيها في العمل. راجع [إيقاف أو استئناف الذكاء الاصطناعي لجهة اتصال واحدة](messages.md#pause-or-resume-the-ai-for-one-contact).

> **إنشاء حملة لا يحدد من يرد على القناة.** يتم التعامل مع التوجيه بواسطة **نقاط الدخول (Entry Points)** على وكيل الذكاء الاصطناعي، وليس بواسطة الحملات. لكل قناة نقطة دخول افتراضية واحدة تحدد الوكيل الذي يرد على جهات الاتصال الجديدة وغير المعروفة عليها: قم بتعيينها باستخدام `PUT /entry-points/channel-defaults`، وتحقق مما إذا كان السلم مفعلاً للحساب باستخدام `GET /entry-points/routing-status`، وقم بمسحها باستخدام `DELETE /entry-points/channel-defaults`. لا يزال `POST /channels/campaign` يكتب خريطة توجيه الحملة القديمة لكل قناة، ولكن لم يعد يتم الرجوع إلى تلك الخريطة للتوجيه الوارد على أي حساب؛ حيث يتم الاحتفاظ بها للتراجع فقط. لا تعتمد عليها في البناء. راجع [توجيه قناة إلى حملة](channels.md#route-a-channel-to-a-campaign) للاطلاع على كلا الواجهتين جنباً إلى جنب.

---

## إدراج الحملات

`GET /campaigns`

يعيد حملاتك، بدءاً من الأحدث. يتم استبعاد الحملات المؤرشفة ما لم تقم بتمرير `archived=true`.

**معلمات الاستعلام**

| المعلمة | مطلوبة | الوصف |
|---|---|---|
| `limit` | لا | الحد الأقصى لعدد الحملات المراد إرجاعها. القيمة الافتراضية `50`، والحد الأقصى `100`. |
| `cursor` | لا | مؤشر الترقيم للصفحات. قم بتمرير قيمة `next_cursor` من الاستجابة السابقة للحصول على الصفحة التالية. |
| `archived` | لا | اضبطها على `true` لتضمين الحملات المؤرشفة. |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/campaigns?limit=20&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/campaigns?limit=20", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.campaigns, data.next_cursor);
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/campaigns",
    params={"limit": 20},
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
print(data["campaigns"], data["next_cursor"])
```

**الاستجابة**

```json
{
  "success": true,
  "campaigns": [
    {
      "id": "NBCXrhqGPSFsd6MV7pRo",
      "name": "Inbound WhatsApp Leads",
      "type": "Incoming from Unknown Contacts",
      "status": "Live",
      "enabled": true,
      "archived": false,
      "created_at": 1700000000000,
      "ai_mode": true,
      "language": "en",
      "enabled_channels": ["whatsapp", "instagram"]
    }
  ],
  "next_cursor": "NBCXrhqGPSFsd6MV7pRo"
}
```

عندما تكون `next_cursor` هي `null`، فقد وصلت إلى الصفحة الأخيرة.

---

## الحصول على حملة

`GET /campaigns/{campaignId}`

يعيد مستند الحملة الكامل، بما في ذلك تكوين البوت المباشر (`bot`)، وإعدادات المتابعة، والقنوات المُمكّنة، وأي كلمات رئيسية. يتم إرجاع الطوابع الزمنية كملي ثانية منذ بداية عصر يونكس (epoch milliseconds).

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const { campaign } = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
campaign = res.json()["campaign"]
```

**الاستجابة**

```json
{
  "success": true,
  "campaign": {
    "id": "NBCXrhqGPSFsd6MV7pRo",
    "name": "Inbound WhatsApp Leads",
    "type": "Incoming from Unknown Contacts",
    "status": "Live",
    "language": "en",
    "ai_mode": true,
    "enabled": true,
    "archived": false,
    "created_at": 1700000000000,
    "enabled_channels": ["whatsapp", "instagram"],
    "bot": {
      "instructions": "Greet warmly and ask about their goals.",
      "goal": "Book a discovery call.",
      "ai_speed": "balanced",
      "anthropic_model": "standard",
      "max_messages": 20
    }
  }
}
```

::: note
**ملاحظة:** تُرجع الحملة المملوكة لحساب مختلف `404 Campaign not found` (وليس `403`)، لذا لا يمكنك معرفة ما إذا كان المعرّف موجوداً في حساب آخر.
:::


---

## إنشاء حملة

`POST /campaigns`

ينشئ حملة جديدة. `name` و `type` مطلوبان؛ كل شيء آخر اختياري. يمكنك تضمين أي حقل حملة آخر في نفس الطلب - على سبيل المثال `language`، أو `ai_mode`، أو كائن تكوين `bot` كامل - وسيتم تخزينه مع الحملة الجديدة. يتم تعيين المالك ووقت الإنشاء تلقائياً.

**حقول الطلب**

| الحقل | مطلوب | الوصف |
|---|---|---|
| `name` | نعم | اسم الحملة. |
| `type` | نعم | أحد أنواع الحملات الأربعة المذكورة أعلاه. |
| `language` | لا | اللغة التي يرد بها البوت (مثال: `"en"`). |
| `ai_mode` | لا | ما إذا كان وضع الذكاء الاصطناعي مفعلاً (`true`/`false`). في الحملات التي يتم الرد عليها بواسطة وكيل ذكاء اصطناعي، تقرأ عمليات القراءة مفتاح التبديل **Active** الخاص بالوكيل بدلاً من قيمة مخزنة — راجع الملاحظة تحت قسم التحديث أدناه. |
| `bot` | لا | كائن إعدادات البوت (راجع [حقول إعدادات البوت](#bot-configuration-fields)). |
| `list_id` | لا | معرف قائمة جهات الاتصال المراد إرفاقها. |
| `event_id` | لا | معرف نوع الحدث الذي يمكن للذكاء الاصطناعي حجزه. |
| `event_ids` | لا | عدة أنواع أحداث في وقت واحد، كمصفوفة من معرفات أنواع الأحداث — النوع الأول هو الافتراضي. أرسل إما `event_id` أو `event_ids`، وليس كلاهما. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spring Promo",
    "type": "Outgoing",
    "language": "en",
    "ai_mode": true,
    "bot": {
      "instructions": "Greet warmly and ask about their goals.",
      "goal": "Book a discovery call."
    }
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/campaigns", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Spring Promo",
    type: "Outgoing",
    language: "en",
    ai_mode: true,
    bot: {
      instructions: "Greet warmly and ask about their goals.",
      goal: "Book a discovery call.",
    },
  }),
});
const { campaign_id } = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/campaigns",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "name": "Spring Promo",
        "type": "Outgoing",
        "language": "en",
        "ai_mode": True,
        "bot": {
            "instructions": "Greet warmly and ask about their goals.",
            "goal": "Book a discovery call.",
        },
    },
)
campaign_id = res.json()["campaign_id"]
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo"
}
```

---

## تحديث حملة

`PUT /campaigns/{campaignId}`

يُحدِّث الحملة جزئيًا — أرسل فقط الحقول التي تريد تغييرها. هذا هو فعل التحديث العام الوحيد؛ لا يوجد `PATCH /campaigns/{campaignId}` (مسارا `PATCH` هما تبديلا [التمكين](#enable-or-disable-a-campaign) و[الأرشفة](#archive-or-restore-a-campaign) المحددان).

**الحقول التي يمكنك تغييرها.** كل ما يكتبه محرر الحملة، بما في ذلك `name`، و`status`، و`type`، و`language`، و`ai_mode`، و`enabled_channels`، وإعدادات المشغل (trigger) والتنقيط (drip)، وعلامات الحجز والمتابعة، وحقول مراقبة Instagram/Facebook، وتكوين `bot` بالكامل. الهوية والملكية مقفلتان طوال فترة الحملة: يتم رفض `user`، و`id`، و`created_at`، وكذلك أي اسم حقل لا يتعرف عليه نقطة النهاية (endpoint). الرفض يكون لكل طلب، وليس لكل حقل — أي مفتاح غير معروف يؤدي إلى إرجاع `400` و**لا يتم كتابة أي شيء** في ذلك الطلب.

**تعكس `ai_mode` في الحملات المدعومة بوكيل حالة الوكيل.** عندما يتم الرد على حملة بواسطة وكيل ذكاء اصطناعي، فإن قراءة الحملة تُرجع `ai_mode` مستمدة من مفتاح التبديل **نشط** الخاص بذلك الوكيل — وهو المفتاح الوحيد الذي يقرر فعلياً ما إذا كان الذكاء الاصطناعي سيرد أم لا. يتم قبول كتابة `ai_mode` في مثل هذه الحملات ولكنها لن تغير ما تقرؤه لاحقاً؛ بدلاً من ذلك، قم بتشغيل أو إيقاف مفتاح التبديل الخاص بالوكيل (من لوحة التحكم، أو عبر واجهة برمجة تطبيقات الوكلاء). في الحملات التقليدية التي لا تحتوي على وكيل، تقوم `ai_mode` بقراءة وكتابة القيمة المخزنة كما في السابق.

**حقول البوت تُدمج، ولا يتم استبدالها.** أرسل إعدادات البوت إما كمفاتيح منقطة (`"bot.instructions": "..."`) أو ككائن متداخل (`"bot": { "instructions": "..." }`) — كلاهما يكتب ورقة تلو الأخرى، لذا فإن الحقول التي تتركها تحتفظ بقيمها الحالية. يمكن تعديل `bot.instructions`، و`bot.goal`، و`bot.rules`، و`bot.personality` بهذه الطريقة، وكذلك كل إعداد آخر للبوت مدرج تحت [حقول تكوين البوت](#bot-configuration-fields). وينطبق الشيء نفسه على `test_bot`، و`frequency`، و`follow_up_config`.

لاستبدال تكوين البوت بالكامل — مع حذف أي حقل لا ترسله — استخدم `bot_replace` (أو `test_bot_replace`) مع الكائن الكامل. لا يمكنك الجمع بين الاستبدال والدمج لنفس الكائن في طلب واحد؛ حيث يؤدي ذلك إلى إرجاع `400`.

::: note
**ملاحظة:** الكتابة إلى `bot.*` عبر واجهة برمجة التطبيقات (API) تسري **فوراً** على الحملة المباشرة. يعمل محرر لوحة التحكم بشكل مختلف: يتم حفظ التعديلات هناك كمسودة ولا تصبح مباشرة إلا عندما ينقر العميل على "نشر" (Publish). لذا، إذا كان لدى العميل تغييرات غير منشورة في لوحة التحكم، فإنها تظل في `test_bot`، وتُظهر قراءة واجهة برمجة التطبيقات لـ `bot` بشكل صحيح ما يستخدمه الذكاء الاصطناعي في الوقت الحالي.
:::


يتم تعيين بعض الحقول من خلال مفتاح مخصص بدلاً من كتابتها مباشرة: استخدم `list_id` لقائمة جهات الاتصال، و `event_id` لنوع الحدث (أو `event_ids`، وهي مصفوفة مرتبة من معرفات أنواع الأحداث، للسماح للذكاء الاصطناعي بحجز عدة أحداث — الأول هو الافتراضي؛ مصفوفة فارغة تلغي ربطها جميعاً)، و `contact_ids` (مصفوفة من معرفات جهات الاتصال) لجهات اتصال الحملة. تُدار إدخالات قاعدة المعرفة من خلال [واجهة برمجة تطبيقات الأسئلة الشائعة (FAQs API)](faqs.md)، وليس من خلال نقطة النهاية هذه.

**العلامات تستبدل، ولا تدمج.** أرسل `tags` كمصفوفة كاملة وستصبح هي مجموعة علامات الحملة — راجع [علامات الحملة](#campaign-tags) لمعرفة الحقول ونقاط النهاية التي تضيف أو تعدل علامة واحدة.

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Spring Promo v2", "enabled_channels": ["whatsapp"] }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo",
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      name: "Spring Promo v2",
      enabled_channels: ["whatsapp"],
    }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"name": "Spring Promo v2", "enabled_channels": ["whatsapp"]},
)
data = res.json()
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo"
}
```

---

## حذف حملة

`DELETE /campaigns/{campaignId}`

يحذف حملة بشكل دائم. لا يمكن التراجع عن هذا الإجراء — إذا كنت قد تحتاج إلى الحملة مرة أخرى، فقم بـ [أرشفتها](#archive-or-restore-a-campaign) بدلاً من ذلك.

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo",
  { method: "DELETE", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.delete(
    "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**الاستجابة**

```json
{
  "success": true
}
```

---

## تكرار حملة

`POST /campaigns/{campaignId}/duplicate`

ينشئ نسخة من الحملة مع الاحتفاظ بجميع إعداداتها. تبدأ النسخة وهي **معطلة** ويتم إضافة لاحقة `(copy)` إلى اسمها، بحيث لا ترسل أي رسائل أبداً حتى تقوم بتمكينها صراحةً.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/duplicate?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/duplicate",
  { method: "POST", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const { campaign_id } = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/duplicate",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
new_campaign_id = res.json()["campaign_id"]
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "aZ9plnewCopyId01234"
}
```

> نسخ مكررة **داخل حساب واحد**.

---


## تمكين أو تعطيل حملة

`PATCH /campaigns/{campaignId}/enabled`

يقوم بتشغيل أو إيقاف حملة ما. تتوقف الحملة المعطلة عن التفاعل مع جهات الاتصال ولكنها تحتفظ بجميع إعداداتها.

**حقول الطلب**

| الحقل | مطلوب | الوصف |
|---|---|---|
| `enabled` | نعم | `true` للتمكين، `false` للتعطيل. يجب أن تكون قيمة منطقية (boolean). |

**cURL**

```bash
curl -X PATCH "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/enabled?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/enabled",
  {
    method: "PATCH",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ enabled: true }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.patch(
    "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/enabled",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"enabled": True},
)
data = res.json()
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "enabled": true
}
```

---

## أرشفة حملة أو استعادتها

`PATCH /campaigns/{campaignId}/archived`

يؤدي هذا إلى أرشفة حملة أو استعادتها. يتم إخفاء الحملات المؤرشفة من قائمة الحملات الافتراضية ولكنها تحتفظ بجميع بياناتها ويمكن استعادتها في أي وقت.

**حقول الطلب**

| الحقل | مطلوب | الوصف |
|---|---|---|
| `archived` | نعم | `true` للأرشفة، `false` للاستعادة. يجب أن تكون قيمة منطقية (boolean). |

**cURL**

```bash
curl -X PATCH "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/archived?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "archived": true }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/archived",
  {
    method: "PATCH",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ archived: true }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.patch(
    "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/archived",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"archived": True},
)
data = res.json()
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "archived": true
}
```

---

## تحديث إعدادات البوت

`PUT /campaigns/{campaignId}/bot-config`

هذه هي الطريقة الآمنة لتغيير إعدادات البوت الفردية. يتم **دمج** كل حقل ترسله مع إعدادات البوت الحالية، لذا يتم الاحتفاظ بأي حقول تتركها. استخدم هذا بدلاً من نقطة نهاية تحديث الحملة (campaign-update) كلما أردت فقط تعديل جزء من البوت.

يجب أن تستخدم مفاتيح الحقول الحروف والأرقام والشرطات السفلية والشرطات فقط.

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/bot-config?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "instructions": "Always answer in a friendly, concise tone.",
    "ai_speed": "balanced"
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/bot-config",
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      instructions: "Always answer in a friendly, concise tone.",
      ai_speed: "balanced",
    }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/bot-config",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "instructions": "Always answer in a friendly, concise tone.",
        "ai_speed": "balanced",
    },
)
data = res.json()
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo"
}
```

### حقول إعدادات البوت

جميع حقول البوت اختيارية. أرسل فقط الحقول التي تريد تعيينها. يتم قبول أي حقول إضافية للبوت تتجاوز تلك المدرجة هنا وتخزينها كما هي.

| الحقل | النوع | الوصف |
|---|---|---|
| `instructions` | string | التعليمات الأساسية التي توجه كيفية تحدث البوت مع جهات الاتصال. |
| `rules` | string | قواعد صارمة يجب على البوت اتباعها دائماً. |
| `goal` | string | النتيجة التي يجب أن يعمل البوت لتحقيقها في كل محادثة. |
| `personality` | string | وصف نبرة الصوت وشخصية البوت. |
| `ai_speed` | string | مقدار التفكير الذي يطبقه الذكاء الاصطناعي قبل الرد. أحد القيم التالية: `fast`، `fast_thinker`، `balanced`، `thorough`. |
| `anthropic_model` | string | مستوى جودة الذكاء الاصطناعي المستخدم لردود هذه الحملة. أحد القيم التالية: `standard`، `economy` (تم إيقافه)، `max`، `mini`. لا تسري `max` و `mini` إلا على الحسابات المؤهلة لهذه المستويات. |
| `max_messages` | integer | الحد الأقصى لعدد رسائل البوت في كل محادثة. |
| `alert_human_when` | string | الشروط التي يجب أن ينبه البوت فيها أحد أعضاء الفريق البشري. |
| `availability` | object | جدول ساعات عمل البوت. يمكنك تعيينه هنا، أو استخدام [نقطة نهاية ساعات العمل](#set-the-bot-active-hours) المخصصة. |
| `follow_up_config` | object | تكوين سلوك المتابعة، مخزن كما هو مقدم. |

---

## تعيين ساعات عمل البوت

`PUT /campaigns/{campaignId}/active-hours`

يحدد جدول توافر البوت. خارج النوافذ المكونة، لا يرد البوت تلقائياً. يقوم هذا بكتابة حقل `availability` في إعدادات البوت.

**حقول الطلب**

| الحقل | مطلوب | الوصف |
|---|---|---|
| `availability` | نعم | كائن مفهرس حسب أيام الأسبوع. المفاتيح المسموح بها هي `monday` إلى `sunday`؛ أي مفتاح آخر سيعيد `400`. الأيام التي تستثنيها تظل دون تغيير. |

يحتوي كل يوم من أيام الأسبوع إما على نافذة زمنية واحدة أو مصفوفة من النوافذ. تحتوي النافذة على `start_time` و `end_time` بتنسيق `HH:MM` بنظام 24 ساعة.

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/active-hours?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "availability": {
      "monday": { "start_time": "09:00", "end_time": "17:00" },
      "tuesday": [
        { "start_time": "09:00", "end_time": "12:00" },
        { "start_time": "13:00", "end_time": "17:00" }
      ]
    }
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/active-hours",
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      availability: {
        monday: { start_time: "09:00", end_time: "17:00" },
        tuesday: [
          { start_time: "09:00", end_time: "12:00" },
          { start_time: "13:00", end_time: "17:00" },
        ],
      },
    }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/active-hours",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "availability": {
            "monday": {"start_time": "09:00", "end_time": "17:00"},
            "tuesday": [
                {"start_time": "09:00", "end_time": "12:00"},
                {"start_time": "13:00", "end_time": "17:00"},
            ],
        }
    },
)
data = res.json()
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo"
}
```

---

## سرد الوظائف المخصصة للحملة

`GET /campaigns/{campaignId}/custom-functions`

يعيد الوظائف المخصصة المرتبطة بهذه الحملة، محلولة إلى تعريفات كاملة. الوظائف المخصصة هي إجراءات HTTP خارجية يمكن للبوت استدعاءها أثناء المحادثة — على سبيل المثال، التحقق من المخزون في متجرك أو إنشاء سجل في نظام إدارة علاقات العملاء (CRM) الخاص بك.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/custom-functions?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/custom-functions",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const { custom_functions } = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/custom-functions",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
custom_functions = res.json()["custom_functions"]
```

**الاستجابة**

```json
{
  "success": true,
  "custom_functions": [
    {
      "id": "fn_abc123",
      "name": "check_stock",
      "description": "Looks up whether a product is in stock.",
      "url": "https://example.com/api/stock",
      "method": "POST",
      "input": [
        { "name": "sku", "type": "string" }
      ],
      "ai_action": "Tell the customer whether the item is available.",
      "created_at": 1700000000000,
      "updated_at": 1700000500000
    }
  ]
}
```

---

## ربط دالة مخصصة بحملة

`POST /campaigns/{campaignId}/custom-functions`

يربط [دالة مخصصة](../ai-automation/custom-functions.md) موجودة بهذه الحملة حتى يتمكن البوت من استدعائها أثناء المحادثة. ربط دالة مرتبطة بالفعل لا يؤدي إلى أي إجراء.

| الحقل | مطلوب | الوصف |
|---|---|---|
| `custom_function_id` | نعم | معرف الدالة المخصصة المراد ربطها. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/custom-functions?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "custom_function_id": "fn_abc123" }'
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "custom_function_id": "fn_abc123"
}
```

---

## إلغاء ربط دالة مخصصة من حملة

`DELETE /campaigns/{campaignId}/custom-functions/{customFunctionId}`

إلغاء ربط دالة غير مرتبطة لا يؤدي إلى أي إجراء.

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/custom-functions/fn_abc123?apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "custom_function_id": "fn_abc123"
}
```

---

## ربط مصدر قاعدة معرفة بحملة

`POST /campaigns/{campaignId}/kb-sources`

يربط مصدر قاعدة معرفة (تم إنشاؤه عبر [واجهة برمجة تطبيقات الأسئلة الشائعة](faqs.md)) بهذه الحملة حتى يتمكن البوت من الاستعانة به عند الإجابة. ربط مصدر مرتبط بالفعل لا يؤدي إلى أي إجراء.

| الحقل | مطلوب | الوصف |
|---|---|---|
| `kb_source_id` | نعم | معرف مصدر قاعدة المعرفة المراد ربطه. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/kb-sources?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "kb_source_id": "kb_abc123" }'
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "kb_source_id": "kb_abc123"
}
```

---

## إلغاء ربط مصدر قاعدة معرفة من حملة

`DELETE /campaigns/{campaignId}/kb-sources/{kbSourceId}`

إلغاء ربط مصدر غير مرتبط لا يؤدي إلى أي إجراء.

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/kb-sources/kb_abc123?apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "kb_source_id": "kb_abc123"
}
```

---

## ربط خادم MCP بحملة

`POST /campaigns/{campaignId}/mcp-servers`

يربط خادم MCP بهذه الحملة، مما يمنح الروبوت إمكانية الوصول إلى أدوات ذلك الخادم أثناء المحادثة. ربط خادم مرتبط بالفعل لا يؤدي إلى أي إجراء.

| الحقل | مطلوب | الوصف |
|---|---|---|
| `mcp_server_id` | نعم | معرف خادم MCP المراد ربطه. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/mcp-servers?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "mcp_server_id": "mcp_abc123" }'
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "mcp_server_id": "mcp_abc123"
}
```

---

## إلغاء ربط خادم MCP من حملة

`DELETE /campaigns/{campaignId}/mcp-servers/{mcpServerId}`

إلغاء ربط خادم غير مرتبط بالفعل لا يؤدي إلى أي إجراء.

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/mcp-servers/mcp_abc123?apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "mcp_server_id": "mcp_abc123"
}
```

---

## مكتبة وسائط الحملة

تحتوي مكتبة الوسائط على الصور ومقاطع الفيديو والمستندات والملاحظات الصوتية التي يمكن للروبوت إرسالها أثناء المحادثة.

### سرد مكتبة وسائط الحملة

`GET /campaigns/{campaignId}/media-library`

```bash
curl "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/media-library?apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "media_items": [
    {
      "id": "media_abc123",
      "item_id": "media_abc123",
      "title": "Pricing sheet",
      "description": "Send when the contact asks about pricing.",
      "media_url": "https://example.com/pricing.pdf",
      "media_content_type": "application/pdf",
      "type": "document",
      "agent_id": "",
      "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
      "media_home": "campaign"
    }
  ]
}
```

`media_url` هو رابط موقع (signed URL) تم التقاطه وقت التحميل - قد يكون منتهي الصلاحية بحلول الوقت الذي تقرأه فيه؛ تقوم لوحة التحكم بإعادة توقيعه عند الطلب.

### تحميل عنصر وسائط

`POST /campaigns/{campaignId}/media-library`

| الحقل | مطلوب | الوصف |
|---|---|---|
| `base64Data` | نعم | الملف، مشفر بـ base64 (بدون بادئة data-URL). |
| `mimeType` | نعم | نوع MIME الخاص بالملف (مثلاً `image/png`). |
| `title` | نعم | تسمية قصيرة تظهر في المكتبة وفي مطالبة الذكاء الاصطناعي. |
| `description` | نعم | تعليمات تخبر الروبوت **متى** يرسل هذا العنصر. |
| `fileName` | لا | اسم الملف الأصلي، يُستخدم لإنشاء اسم كائن التخزين. |
| `sendMessage` | لا | الصياغة المفضلة التي يجب أن يستخدمها الروبوت عند إرسال هذا العنصر. |
| `maxSendsPerConversation` | لا | الحد الأقصى لمرات إرسال الروبوت لهذا العنصر إلى جهة اتصال واحدة في محادثة. القيمة الافتراضية هي `1`. |
| `sendAsVoiceNote` | لا | بالنسبة لتحميل الصوت، قم بتحويل ترميزه إلى ملاحظة صوتية على واتساب. القيمة الافتراضية هي `false` (يتم تخزينه كملف صوتي عادي). |

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/media-library?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "base64Data": "iVBORw0KGgoAAAANSUhEUgAA...",
    "mimeType": "image/png",
    "title": "Product photo",
    "description": "Send when the contact asks what the product looks like."
  }'
```

**الاستجابة**

```json
{
  "success": true,
  "itemId": "media_abc123",
  "mediaUrl": "https://example.com/product.png",
  "storagePath": "ai_media/campaigns/NBCXrhqGPSFsd6MV7pRo/media_abc123.png",
  "mediaContentType": "image/png",
  "type": "image",
  "isVoiceNote": false
}
```

### تحديث عنصر وسائط

`PATCH /campaigns/{campaignId}/media-library/{itemId}`

يعدل بيانات وصف العنصر فقط — لاستبدال الملف نفسه، احذف العنصر وقم بتحميل ملف جديد.

| الحقل | الوصف |
|---|---|
| `title` | تسمية قصيرة. |
| `description` | تعليمات وقت الإرسال. |
| `send_message` | الصياغة المفضلة التي يستخدمها البوت. |
| `max_sends_per_conversation` | عدد صحيح غير سالب، أو `null` لمسح الحد الأقصى. |

```bash
curl -X PATCH "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/media-library/media_abc123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Updated pricing sheet" }'
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "item_id": "media_abc123"
}
```

### حذف عنصر وسائط

`DELETE /campaigns/{campaignId}/media-library/{itemId}`

حذف عنصر تم حذفه بالفعل لا يؤدي إلى أي إجراء.

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/media-library/media_abc123?apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{ "success": true, "deleted": true }
```

---

## علامات الحملة

علامة الحملة هي تسمية تعلمها للبوت ليطبقها على جهة اتصال أثناء المحادثة — `hot-lead`، `not-interested`، `booked-a-call`. تتكون كل علامة من ثلاثة أجزاء:

| الحقل | النوع | الوصف |
|---|---|---|
| `name` | سلسلة نصية، مطلوب | التسمية نفسها. هذا هو ما يطبقه البوت على جهة الاتصال وما تطابقه لاحقاً، لذا اجعلها قصيرة وثابتة. |
| `description` | سلسلة نصية | التعليمات التي تخبر البوت **متى** يطبق هذه العلامة. هذا هو الجزء الذي يقوم بالعمل — "الشخص يؤكد انضمامه إلى المجتمع" يتم استخدامه، بينما "عميل محتمل" لا يتم استخدامه. |
| `webhook` | سلسلة نصية | رابط URL يتلقى `POST` في اللحظة التي يتم فيها وضع العلامة على جهة اتصال. اتركه فارغاً إذا لم تكن بحاجة إليه. |
| `tag_id` | سلسلة نصية | اختياري. يربط هذا الإدخال بعلامة موجودة في حسابك بدلاً من إنشاء علامة جديدة. قم بتوفيره إذا كنت ترغب في التعامل مع هذه العلامة المحددة لاحقاً باستخدام نقاط نهاية العلامة الواحدة أدناه. |

يجب أن تكون أسماء العلامات فريدة داخل الحملة. يطبق البوت العلامات **بالاسم**، لذا فإن وجود إدخالين يتشاركان نفس الاسم لا يحدد أياً منهما سيتم تطبيقه.

### تعيين جميع علامات الحملة

`PUT /campaigns/{campaignId}` مع مصفوفة `tags`.

هذا يستبدل علامات الحملة بما ترسله بالضبط، وهو نفس ما تفعله علامة التبويب "العلامات" في لوحة التحكم عند حفظها. **أرسل المصفوفة الكاملة في كل مرة** — العلامة التي تحذفها من المصفوفة هي علامة قمت بحذفها. إرسال `[]` يمسحها جميعاً.

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tags": [
      {
        "name": "hot-lead",
        "description": "The person confirms they want to buy, or asks how to get started right away.",
        "webhook": "https://example.com/hooks/campaign-events"
      },
      {
        "name": "not-interested",
        "description": "The person declines the offer or says they are not a fit."
      }
    ]
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo",
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      tags: [
        {
          name: "hot-lead",
          description:
            "The person confirms they want to buy, or asks how to get started right away.",
          webhook: "https://example.com/hooks/campaign-events",
        },
        {
          name: "not-interested",
          description: "The person declines the offer or says they are not a fit.",
        },
      ],
    }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "tags": [
            {
                "name": "hot-lead",
                "description": "The person confirms they want to buy, or asks how to get started right away.",
                "webhook": "https://example.com/hooks/campaign-events",
            },
            {
                "name": "not-interested",
                "description": "The person declines the offer or says they are not a fit.",
            },
        ]
    },
)
data = res.json()
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo"
}
```

اقرأ العلامات مرة أخرى باستخدام [`GET /campaigns/{campaignId}`](#get-a-campaign).

### إضافة علامة واحدة

`POST /campaigns/{campaignId}/tags`

يضيف علامة واحدة دون الحاجة لإعادة إرسال البقية. استخدم هذا عند الإضافة إلى مجموعة لم تقم بإنشائها في هذا الطلب.

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/tags?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "tag": { "name": "booked-a-call", "description": "The person confirms a booked time." } }'
```

نشر نفس العلامة مرتين لا يؤدي إلى أي إجراء في المرة الثانية. نشر نفس `tag_id` باسم أو وصف مختلف يؤدي إلى إضافة إدخال **ثانٍ** بدلاً من تعديل الأول — استخدم نقطة النهاية أدناه للتعديل في نفس المكان.

### تحديث أو إزالة علامة واحدة

`PUT /campaigns/{campaignId}/tags/{tagId}`
`DELETE /campaigns/{campaignId}/tags/{tagId}`

تتعامل هذه مع إدخال واحد بواسطة `tag_id` الخاص به، لذا فهي تعمل فقط على العلامات التي تم إنشاؤها باستخدام واحد. إذا لم تكن للعلامة `tag_id`، فقم بتغييرها باستخدام `PUT /campaigns/{campaignId}` الخاص بالمصفوفة الكاملة أعلاه.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/tags/tag_abc123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "tag": { "name": "hot-lead", "description": "Updated instruction." } }'
```

العلامة `tagId` التي ليست في الحملة تُرجع `404` مع `"Tag not found in campaign tags"`.

---

## تبديل قنوات الحملة

`POST /campaigns/{campaignId}/channels`

يضيف أو يزيل قنوات من مصفوفة `enabled_channels` الخاصة بالحملة دون إعادة إرسال المصفوفة بالكامل — وهو أكثر أمانًا من [`PUT /campaigns/{campaignId}`](#update-a-campaign) عندما يكون هناك شيء آخر قد يقوم بتعديل الحملة في نفس الوقت.

أرسل إما تبديلاً فردياً أو دفعة — لا ترسل كليهما في نفس الطلب:

```json
{ "channel": "whatsapp", "action": "add" }
```

```json
{ "add": ["whatsapp", "instagram"], "remove": ["sms"] }
```

| الحقل | الوصف |
|---|---|
| `channel` | قناة واحدة للتبديل. تقترن بـ `action`. |
| `action` | `"add"` أو `"remove"`. تقترن بـ `channel`. |
| `add` | مصفوفة القنوات المراد إضافتها. صيغة الدفعة — استخدمها بدلاً من `channel`/`action`. |
| `remove` | مصفوفة القنوات المراد إزالتها. صيغة الدفعة. |

القنوات الصالحة: `whatsapp`, `whatsapp_web`, `sms`, `instagram`, `messenger`, `facebook`, `chat_widget`, `custom_channel`, `imessage`, `telegram`, `instagram_private`, `line`, `viber`, `tiktok`, `email`, `linkedin`, `skool`.

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/channels?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "whatsapp", "action": "add" }'
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "added": ["whatsapp"],
  "removed": []
}
```

> هذا يغير فقط القنوات التي تعلن عنها الحملة — ولا يحدد من يجيب على القناة. راجع [أنواع الحملات](#campaign-types) أعلاه و [توجيه حملة إلى القنوات الواردة](#route-a-campaign-to-incoming-channels) أدناه لمعرفة ذلك.

---

## التعليق إلى رسالة مباشرة (Instagram و Facebook)

تحول ميزة "التعليق إلى رسالة مباشرة" (Comment-to-DM) التعليق على أحد منشوراتك إلى محادثة خاصة: يقوم شخص ما بالتعليق، فيرسل البوت إليه رسالة مباشرة (DM)، وتتولى الحملة إدارة المحادثة من هناك. يتم تكوين هذه الميزة بالكامل من خلال كائن الحملة، لذا لا يوجد جزء منها يقتصر على واجهة المستخدم فقط.

قم بتوصيل صفحة Facebook أولاً - راجع [توصيل القناة](channels.md#instagram--messenger-meta). ثم قم بتعيين الحقول أدناه باستخدام [`PUT /campaigns/{campaignId}`](#update-a-campaign).

> **يجب أن تكون الحملة `Live`.** لا تلتقط مراقبة التعليقات سوى الحملات التي تكون `status` الخاصة بها هي `Live` (بأي حالة أحرف — راجع [أنواع الحملات](#campaign-types)). أي حالة أخرى تعطلها بصمت، ويتم الآن رفض أي حالة مبتكرة مثل `"Active"` مع إظهار `400` بدلاً من تخزينها. تشمل الحالات الصالحة `Draft`، و`Pending Approval`، و`Scheduled`، و`Live`، و`Paused`، و`Completed`، و`Sent`، و`Failed`.

**الحقول**

| الحقل | النوع | الوصف |
|---|---|---|
| `monitor_instagram_posts` | boolean | مراقبة كل منشورات Instagram على الصفحة المتصلة. |
| `instagram_post_ids` | string[] | مراقبة منشورات Instagram هذه فقط. اتركها غير محددة عند تفعيل `monitor_instagram_posts`. |
| `instagram_comment_delay_minutes` | number | انتظر هذا العدد من الدقائق بعد التعليق قبل إرسال الرسالة المباشرة (DM). |
| `monitor_facebook_posts` | boolean | مراقبة كل منشورات Facebook على الصفحة المتصلة. |
| `facebook_post_ids` | string[] | مراقبة منشورات Facebook هذه فقط. |
| `facebook_comment_delay_minutes` | number | التأخير قبل إرسال الرسالة المباشرة، بالدقائق. |
| `public_comment_reply_instructions` | string | توجيهات للرد المرئي المتروك على التعليق نفسه. يتجاوز الصياغة الافتراضية "تحقق من رسائلك المباشرة". |
| `first_response_mode` | string | `"ai"` (الافتراضي) ينشئ أول رسالة مباشرة والرد العام. `"exact_text"` يرسل صياغتك كما هي، بدون إنشاء بواسطة الذكاء الاصطناعي وبدون خصم رصيد. |
| `first_response_exact_text` | string | أول رسالة مباشرة حرفية، تُستخدم عندما يكون `first_response_mode` هو `"exact_text"`. مطلوبة لكي يسري مفعول هذا الوضع. |
| `first_response_exact_text_variants` | string[] | صياغات إضافية لأول رسالة مباشرة. يتم اختيار واحدة عشوائياً لكل إرسال، بحيث لا تكون الرسائل المباشرة المتكررة متطابقة تماماً. |
| `public_comment_reply_exact_text` | string | الرد العام الحرفي في وضع `"exact_text"`. اتركه فارغاً لتخطي الرد العام وإرسال الرسالة المباشرة فقط. |
| `public_comment_reply_exact_text_variants` | string[] | صياغات إضافية للرد العام. |
| `monitor_instagram_followers` | boolean | التعامل مع المتابع الجديد كمحفز وإرسال رسالة مباشرة افتتاحية (حسابات Instagram الشخصية). |
| `follower_outreach_instructions` | string | توجيهات لرسالة المتابع الجديد الافتتاحية المباشرة. |
| `respond_to_instagram_story_replies` | boolean | ما إذا كان الذكاء الاصطناعي يجيب على الردود على قصص Instagram الخاصة بك. الافتراضي `true`. اضبط `false` لجعل ردود القصص تصل إلى الدردشة (مع إرفاق القصة) بدون رد من الذكاء الاصطناعي. إعداد مباشر - ليس جزءاً من المسودة، لذا لا يحتاج إلى نشر. |

**مسح حقل**

يتم إزالة هذه الحقول بدلاً من تعيينها إلى `null` عند إرسال `null`، لذا يعود البوت إلى إعداداته الافتراضية: `instagram_post_ids`، `facebook_post_ids`، `instagram_comment_delay_minutes`، `facebook_comment_delay_minutes`، `public_comment_reply_instructions`، `follower_outreach_instructions`، `first_response_exact_text`، `first_response_exact_text_variants`، `public_comment_reply_exact_text`، `public_comment_reply_exact_text_variants`.

> **مفتاح واحد غير معروف يرفض الطلب بأكمله.** يقوم `PUT /campaigns/{campaignId}` بالتحقق من صحة النص الأساسي بالكامل مقابل قائمة مسموح بها. المفتاح الذي لا يتم التعرف عليه يعيد `400` للطلب ككل - لا يتم تجاهله بصمت، ولا يتم كتابة أي من الحقول الأخرى في ذلك النص الأساسي.

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "Live",
    "monitor_instagram_posts": true,
    "instagram_comment_delay_minutes": 2,
    "first_response_mode": "exact_text",
    "first_response_exact_text": "Hey! Sending the details over now.",
    "first_response_exact_text_variants": [
      "Hi there, here are the details you asked for.",
      "Thanks for commenting, here is what you need."
    ],
    "public_comment_reply_exact_text": "Just sent you a DM."
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo",
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      status: "Live",
      monitor_instagram_posts: true,
      instagram_comment_delay_minutes: 2,
      first_response_mode: "ai",
      public_comment_reply_instructions:
        "Tell them to check their message requests folder too.",
    }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "status": "Live",
        "monitor_facebook_posts": True,
        "facebook_post_ids": None,
        "facebook_comment_delay_minutes": 5,
    },
)
data = res.json()
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo"
}
```

> يتطلب الرد المرئي الذي يُترك على التعليق ميزة "الرد على التعليقات" في خطتك. بدونها، لا تزال الرسالة المباشرة تُرسل ويتم تخطي الرد العام.

---

## تحسين حملة باستخدام الذكاء الاصطناعي

`POST /campaigns/{campaignId}/optimize`

يُشغّل نفس عملية إعادة الكتابة بالذكاء الاصطناعي الموجودة في تدفقات "تحسين" (Optimize) وملاحظات زر عدم الإعجاب (thumbs-down) في لوحة التحكم: يأخذ ملاحظاتك، ويعيد كتابة تعليمات البوت، ويجهز النتيجة كمسودة مراجعة جديدة لتراجعها.

| الحقل | مطلوب | الوصف |
|---|---|---|
| `user_feedback` | أحد هذين الحقلين مطلوب | ملاحظات حرة تصف ما يجب تحسينه. |
| `thumbs_down_feedback` | أحد هذين الحقلين مطلوب | الملاحظات التي تم التقاطها من زر عدم الإعجاب على رد معين من البوت. |
| `thumbs_down_message` | لا | رسالة البوت التي تشير إليها ملاحظات عدم الإعجاب. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/optimize?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "user_feedback": "Make the tone more casual and mention the free trial earlier." }'
```

**الاستجابة** (`202` — تعمل عملية إعادة الكتابة في الخلفية)

```json
{ "success": true, "campaign_id": "NBCXrhqGPSFsd6MV7pRo" }
```

قم بعملية استطلاع [`GET /campaigns/{campaignId}`](#get-a-campaign) وراقب `test_bot.status`: ستتحول فوراً إلى `"Optimizing"`، ثم تعود إلى `"Draft"` بمجرد وصول إعادة الكتابة إلى `test_bot`. من هناك، ستتصرف مثل أي مسودة في لوحة التحكم — راجعها، ثم انشرها في لوحة التحكم لتصبح مباشرة. تعني `409` أن عملية تحسين تعمل بالفعل لهذه الحملة.

> تستهلك عملية التحسين أرصدة، تماماً مثل أي عملية ذكاء اصطناعي أخرى على حسابك.

---

## تعيين جهة اتصال لحملة

`POST /campaigns/{campaignId}/contacts/{contactId}/assign`

يضع جهة اتصال موجودة في حملة، وإذا طلبت ذلك، يرسل رسالة الحملة الافتتاحية على الفور. هذه هي الطريقة لإرسال قالب WhatsApp المعتمد الخاص بحملة إلى جهة اتصال واحدة: القالب الذي تم اعتماد الحملة به ينتمي إلى تلك الحملة، لذا فهو لا يظهر في مكتبة [Templates API](templates.md) ولا يمكن إرساله من خلال `/whatsapp-templates/send`.

| الحقل | مطلوب | الوصف |
|---|---|---|
| `sendOpeningMessage` | لا | `true` يرسل رسالة الحملة الافتتاحية (قالب WhatsApp المعتمد في حملة WhatsApp) بمجرد تعيين جهة الاتصال. القيمة الافتراضية هي `false`. |
| `triggerAIResponse` | لا | `true` يسمح للذكاء الاصطناعي بكتابة رسالته الأولى بنفسه بدلاً من ذلك. القيمة الافتراضية هي `false`. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/contacts/contact_abc123/assign?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "sendOpeningMessage": true }'
```

**الاستجابة**

```json
{
  "success": true,
  "data": { "contactId": "contact_abc123", "campaignId": "NBCXrhqGPSFsd6MV7pRo" }
}
```

> **الأرصدة:** يتم احتساب تكلفة إرسال الرسالة الافتتاحية في حملة WhatsApp مثل أي إرسال للقوالب، ويتم تسعيرها حسب بلد المستلم وفئة القالب. في القنوات الأخرى، تكون الرسالة الافتتاحية رسالة صادرة عادية.

---

## توجيه حملة إلى القنوات الواردة

تدير نقاط النهاية هذه الحملة التي تجيب على جهات الاتصال الجديدة وغير المعروفة على القناة. **فَضِّل نقاط الدخول (Entry Points)** لعمليات التكامل الجديدة (راجع الملاحظة تحت [أنواع الحملات](#campaign-types)) — تظل هذه النقاط مفيدة للعمل مع الحملات التي يتم توجيهها بالطريقة القديمة، ولحل تعارض ملكية القناة بين حملتين واردتين.

### تعيين حملة للقنوات الواردة

`POST /campaigns/{campaignId}/incoming-routing`

| الحقل | مطلوب | الوصف |
|---|---|---|
| `channels` | نعم | مصفوفة القنوات التي يجب أن تجيب عليها هذه الحملة لجهات الاتصال الجديدة وغير المعروفة. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/incoming-routing?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channels": ["whatsapp", "instagram"] }'
```

**الاستجابة**

```json
{
  "success": true,
  "uid": "abc123",
  "campaignId": "NBCXrhqGPSFsd6MV7pRo",
  "channels": ["whatsapp", "instagram"],
  "failed": []
}
```

تسرد `channels` فقط القنوات التي تم توجيهها فعلياً إلى هذه الحملة؛ بينما تسرد `failed` أي قنوات لم يتم توجيهها. إذا فشلت كل القنوات المطلوبة، يفشل الطلب نفسه.

### مسح توجيه الحملة الوارد

`DELETE /campaigns/{campaignId}/incoming-routing`

| الحقل | مطلوب | الوصف |
|---|---|---|
| `channelToUnassign` | لا | مسح التوجيه لهذه القناة فقط. احذف هذا الحقل لمسح كل قناة تجيب عليها هذه الحملة حالياً. |

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/incoming-routing?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channelToUnassign": "instagram" }'
```

**الاستجابة**

```json
{
  "success": true,
  "uid": "abc123",
  "campaignId": "NBCXrhqGPSFsd6MV7pRo",
  "channelsRemoved": ["instagram"]
}
```

### إعادة تنشيط حملة خاملة

`POST /campaigns/{campaignId}/reactivate`

يعيد حملة من حالة `Ended`، أو `Completed`، أو `Paused`، أو `Draft` ويستعيد قنواتها. يعمل فقط على الحملات ذات الحالة `Incoming from Unknown Contacts` أو `Combined` — أما الحملة التي تكون بالفعل `Live` فيتم التعامل معها كنجاح ولا تتطلب أي إجراء.

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/reactivate?apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{
  "success": true,
  "data": {
    "success": true,
    "channelsReactivated": ["whatsapp"],
    "channelsBlockedByConflict": [],
    "campaignType": "Incoming from Unknown Contacts"
  }
}
```

تظهر القناة التي تم حجزها بالفعل بواسطة وكيل حملة أخرى في `channelsBlockedByConflict` بدلاً من فشل الطلب بالكامل — استخدم [إيقاف حملة واردة متعارضة](#stop-a-conflicting-incoming-campaign) أدناه لتحريرها أولاً إذا كنت تريد أن تستولي هذه الحملة عليها. يتم إرجاع `400` لنوع حملة لا يدعم إعادة التنشيط، أو لحالة ليست واحدة من الحالات الخاملة المذكورة أعلاه.

### إيقاف حملة واردة متعارضة

`POST /campaigns/{campaignId}/stop-incoming`

يحرر قنوات هذه الحملة من أي حملة أخرى تحتجزها حالياً، حتى تتمكن هذه الحملة من حجزها بعد ذلك. هذه هي نسخة REST لما تقوم به لوحة التحكم تلقائياً عند إطلاق حملة واردة في قناة يقوم شخص آخر بالرد عليها بالفعل.

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/stop-incoming?apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "ended_campaign_ids": [],
  "released_channels": ["whatsapp"],
  "cleared_entire_field": false
}
```

يتم إرجاع `released_channels` فارغاً عندما تمتلك هذه الحملة بالفعل كل قناة تعلن عنها — فلا يوجد شيء للاستيلاء عليه.

---

## تقديرات التكلفة

قدّر تكلفة إطلاق حملة قبل إرسالها.

### تقدير تكلفة قالب WhatsApp

`GET /campaigns/{campaignId}/template-cost-estimate`

```bash
curl "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/template-cost-estimate?apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{
  "success": true,
  "billing_mode": "credits",
  "data": {
    "countries": [
      {
        "countryCode": "1",
        "name": "United States",
        "iso": "US",
        "flag": "🇺🇸",
        "contactCount": 120,
        "costPerContact": 2,
        "subtotal": 240
      }
    ],
    "totalContacts": 120,
    "totalTemplateCost": 240,
    "templateCategory": "marketing",
    "billing_mode": "credits",
    "service_messages_billable_soon": false
  }
}
```

`billing_mode` يكون `"credits"` على مسار WhatsApp المُدار. في المسار الذي تقوم فيه Meta بفوترة حساب WhatsApp Business الخاص بك مباشرة، يتم إرجاع `costPerContact`، و`subtotal`، و`totalTemplateCost` كـ `null` — وليس أبداً `0`، والتي تُقرأ على أنها مجانية — نظراً لعدم وجود رقم رصيد للإبلاغ عنه.

### تقدير تكلفة الرسائل القصيرة (SMS)

`GET /campaigns/{campaignId}/sms-cost-estimate`

```bash
curl "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/sms-cost-estimate?apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{
  "success": true,
  "billing_mode": "twilio_direct",
  "data": {
    "totalContacts": 120,
    "messageLength": 87,
    "segmentsPerMessage": 1,
    "totalSegments": 120,
    "estimatedCostUsd": 0.96,
    "priceUnit": "USD per segment",
    "billedByTwilio": true
  }
}
```

يتم إرسال الرسائل القصيرة دائماً من خلال حساب Twilio الخاص بك (انظر [مزود خدمة الرسائل القصيرة](../settings/sms-provider.md))، لذا يتم فوترة هذا دائماً بواسطة Twilio مباشرة — `estimatedCostUsd` هو تقدير لفاتورة Twilio تلك، وليس خصماً من الرصيد.

---

## فحوصات الحدود

تحقق من الحد قبل الإطلاق، بدلاً من اكتشاف ذلك من خلال فشل الإرسال.

### فحوصات على مستوى الحملة

`GET /campaigns/{campaignId}/limits/ai-credit-messaging` — ما إذا كان إطلاق هذه الحملة أو جدولتها سيتجاوز حد مراسلات رصيد الذكاء الاصطناعي الخاص بحسابك.

`GET /campaigns/{campaignId}/limits/messaging` — ما إذا كان ذلك سيتجاوز حد المراسلات اليومي لحسابك.

```bash
curl "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/limits/messaging?apiKey=YOUR_API_KEY"
```

**الاستجابة** (لم يتم تجاوز الحد)

```json
{
  "success": true,
  "data": "Campaign is within the daily messaging limit."
}
```

يتم إرجاع `400` بدلاً من ذلك عند تجاوز الحد، مع توضيح السبب في `error`.

### فحوصات على مستوى الحساب

`GET /campaigns/limits/campaigns` — ما إذا كنت قد وصلت إلى حد إنشاء الحملات الشهري لاشتراكك.

`GET /campaigns/limits/contacts` — ما إذا كنت قد وصلت إلى حد جهات الاتصال لاشتراكك.

```bash
curl "https://api.youraiconnector.com/v1/campaigns/limits/campaigns?apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{
  "success": true,
  "data": "You can create 3 more campaigns this month."
}
```

---

## إجمالي إحصائيات الحملة

`GET /campaigns/stats/totals`

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

| معامل الاستعلام | الوصف |
|---|---|
| `days` | حجم النافذة الزمنية المتتالية، من 1 إلى 365. القيمة الافتراضية هي 90. |

```bash
curl "https://api.youraiconnector.com/v1/campaigns/stats/totals?days=30&apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{
  "success": true,
  "byCampaign": {
    "NBCXrhqGPSFsd6MV7pRo": { "sent": 1204, "replied": 318 }
  },
  "byAgent": {
    "agent_abc123": { "sent": 1204, "replied": 318 }
  },
  "windowDays": 30
}
```

`byAgent` هو تجميع خاص به، وليس مجموع `byCampaign` — يمكن لحركة مرور حساب وكيل الذكاء الاصطناعي ألا تحمل أي حملة على الإطلاق، لذا ستكون غير مرئية هنا بخلاف ذلك.

---

## اختبار حملة في بيئة الاختبار (Playground)

تتيح لك بيئة الاختبار إجراء محادثة مع بوت الحملة دون لمس قناة حقيقية أو جهة اتصال حقيقية. إنها نفس بيئة الاختبار المعزولة الموجودة في لوحة تجربة لوحة التحكم، وهي متاحة بالكامل عبر واجهة برمجة التطبيقات (API).

سير العمل هو: إنشاء جهة اتصال اختبار مخفية، إرسال رسالة، ثم استطلاع الحملة للحصول على رد البوت. يتم إنشاء الردود بشكل غير متزامن، لذا فهي تصل في `test_messages` على الحملة بدلاً من نص الاستجابة.

> **يتم تشغيل Playground على حساب أرصدة تكلفة واجهة برمجة التطبيقات (API).** يتم احتساب تكلفة محادثة الاختبار التي تبدأ باستخدام مفتاح API وفقاً لسعر رسائل الذكاء الاصطناعي العادي، تماماً مثل الرد الحقيقي، وتظهر في سجل استخدامك كإدخال عادي. يظل الاختبار من لوحة التحكم مجانياً. هذا الاختلاف مقصود: فتشغيل الاختبار يقوم بنفس عمل الذكاء الاصطناعي الذي يقوم به التشغيل المباشر، لذا فإن استخدام Playground لواجهة برمجة التطبيقات بدون قيود سيكون وسيلة لتشغيل ذكاء اصطناعي غير محدود على حساب شخص آخر.

### الخطوة 1 - إنشاء جهة اتصال الاختبار

`POST /campaigns/{campaignId}/try-out/contact`

ينشئ جهة اتصال اختبار مخفية ويربطها بالحملة. جميع حقول النص اختيارية؛ أي شيء تتركه فارغاً سيتم استبداله بهوية نموذجية مدمجة (John Doe).

| الحقل | مطلوب | الوصف |
|---|---|---|
| `first_name` | لا | الاسم الأول لجهة اتصال الاختبار. |
| `last_name` | لا | الاسم الأخير لجهة اتصال الاختبار. |
| `email` | لا | البريد الإلكتروني لجهة اتصال الاختبار. |
| `phone` | لا | رقم هاتف جهة اتصال الاختبار. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/try-out/contact?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "first_name": "Maria", "last_name": "Lopez" }'
```

**الاستجابة**

```json
{
  "success": true,
  "contactId": "8kQx1vNbA2fLpR7d"
}
```

### الخطوة 2 - تسجيل الرسالة الواردة

`POST /campaigns/{campaignId}/try-out/messages`

يضيف الرسائل إلى سلسلة محادثات الاختبار. أرسل رسالة الزائر هنا أولاً، حتى تظهر في سجل المحادثة الذي يقرأه البوت.

| الحقل | مطلوب | الوصف |
|---|---|---|
| `messages` | نعم | مصفوفة من كائنات الرسائل، بحد أقصى 200 لكل طلب. |
| `messages[].body` | نعم | نص الرسالة. |
| `messages[].direction` | نعم | `"inbound"` للزائر، `"outbound"` للبوت. |
| `messages[].timestamp` | لا | سلسلة ISO-8601 أو ميلي ثانية منذ بداية العصر (epoch). |
| `messages[].role` | لا | تسمية دور اختيارية. |
| `messages[].name` | لا | اسم عرض اختياري. |
| `ignoreCounter` | لا | عدد صحيح. يعيد تعيين عداد تجاهل الحملة في نفس عملية الكتابة. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/try-out/messages?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "body": "Do you ship to Belgium?",
        "direction": "inbound",
        "timestamp": "2026-07-22T09:30:00Z"
      }
    ]
  }'
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "appended": 1
}
```

### الخطوة 3 - طلب الرد من البوت

`POST /campaigns/{campaignId}/try-out/test-message`

يرسل الرسالة إلى خط معالجة الذكاء الاصطناعي. هذا هو الاستدعاء الذي ينتج فعلياً رد البوت.

| الحقل | مطلوب | الوصف |
|---|---|---|
| `message` | نعم | نص أحدث رسالة من الزائر. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/try-out/test-message?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Do you ship to Belgium?" }'
```

**الاستجابة**

```json
{
  "success": true,
  "data": "Published"
}
```

تعني `"Published"` أن الرسالة قد تم إرسالها إلى خط معالجة الذكاء الاصطناعي. تعني `"Ignored"` أن رسالة اختبار أحدث قد حلت محل هذه الرسالة — حيث تقوم ساحة اللعب (playground) بدمج الدفقات السريعة في رد واحد، بعد حوالي أربع ثوانٍ من آخر رسالة، بنفس الطريقة التي تنتظر بها المحادثة الحقيقية حتى ينتهي الشخص من الكتابة. وبسبب نافذة الدمج هذه، يستغرق هذا الاستدعاء بضع ثوانٍ للعودة.

### الخطوة 4 - قراءة الرد

`GET /campaigns/{campaignId}`

يتم إلحاق رد البوت بمصفوفة `test_messages` الخاصة بالحملة. قم باستطلاع الحملة حتى يظهر إدخال `outbound` جديد.

```json
{
  "success": true,
  "campaign": {
    "id": "NBCXrhqGPSFsd6MV7pRo",
    "test_messages": [
      { "body": "Do you ship to Belgium?", "direction": "inbound" },
      { "body": "Yes, we ship across the EU.", "direction": "outbound" }
    ]
  }
}
```

### إعادة تعيين ساحة اللعب

`POST /campaigns/{campaignId}/try-out/reset`

يمسح بيئة الاختبار بالكامل: يحذف جهة اتصال الاختبار، ويمسح `test_messages`، ويحرر أقفال استجابة البوت. استخدم هذا بين عمليات تشغيل الاختبار.

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/NBCXrhqGPSFsd6MV7pRo/try-out/reset?apiKey=YOUR_API_KEY"
```

**الاستجابة**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo"
}
```

### نقاط نهاية أخرى لبيئة الاختبار

| نقطة النهاية | وظيفتها |
|---|---|
| `DELETE /campaigns/{campaignId}/try-out/contact` | تحذف جهة اتصال الاختبار الحالية فقط وتلغي ربطها، مع ترك `test_messages` كما هي. تنجح العملية حتى في حال عدم وجود جهة اتصال مرتبطة. |
| `POST /campaigns/{campaignId}/try-out/transfer` | تبدأ بيئة اختبار جديدة محملة بمحادثة موجودة، في طلب واحد: تستبدل جهة اتصال الاختبار وتستبدل `test_messages`. يأخذ النص الأساسي `first_name`، و`last_name`، و`messages` (قد تكون فارغة) و`ignoreCounter`. يفضل استخدام هذا الخيار بدلاً من الحذف ثم الإنشاء ثم الإلحاق، مما يضاعف استهلاك حد المعدل ثلاث مرات. |
| `POST /campaigns/{campaignId}/try-out/messages/replace` | تستبدل `test_messages` بالكامل بدلاً من الإلحاق. استخدمها لاقتطاع سلسلة محادثة أو إرجاعها. |
| `POST /campaigns/{campaignId}/try-out/contact/reset-ignore-counter` | تعيد تعيين عداد التجاهل لجهة اتصال الاختبار فقط، وذلك لإعادة تنفيذ وتكرار التدفقات بعد الإرسال. |

---

## أخطاء واجهة برمجة تطبيقات الحملات

تُرجع نقاط نهاية الحملات غلاف الخطأ القياسي:

```json
{
  "success": false,
  "error": "Campaign not found"
}
```

| الحالة | متى يحدث ذلك في نقطة نهاية الحملة |
|---|---|
| `400` | حقل مطلوب مفقود أو غير صالح (على سبيل المثال، `type` خاطئ، أو `enabled` ليس منطقياً، أو مفتاح يوم أسبوع غير معروف). يتم إرجاعه أيضاً بواسطة نقطة نهاية [فحص الحد](#limit-checks) عند تجاوز الحد، وبواسطة [إعادة التنشيط](#reactivate-a-dormant-campaign) لنوع حملة أو حالة لا تدعم ذلك. |
| `404` | لم يتم العثور على الحملة — إما أنها غير موجودة أو أنها تنتمي إلى حساب آخر. |
| `409` | هناك [تحسين](#optimize-a-campaign-with-ai) قيد التشغيل بالفعل لهذه الحملة. |

الرموز المشتركة التي يمكن أن تُرجعها كل نقطة نهاية — `401`، و `403` (خطتك لا تتضمن الوصول إلى واجهة برمجة التطبيقات)، و `429` (حد المعدل)، و `500` — مدرجة مع إرشادات إعادة المحاولة في [الأخطاء والترقيم](errors-and-pagination.md).

---

## ذات صلة

- [توجيه قناة إلى حملة](channels.md#route-a-channel-to-a-campaign) — قم بتوجيه Instagram أو WhatsApp أو أي قناة أخرى إلى وكيل الذكاء الاصطناعي الذي يجب أن يجيب عليها، باستخدام نقاط الدخول (Entry Points).
- [إنشاء قوالب متابعة باستخدام الذكاء الاصطناعي](templates.md#generate-follow-up-templates-with-ai) — ابدأ مهمة في الخلفية لكتابة قوالب متابعة WhatsApp الخاصة بالحملة.
- [واجهة برمجة تطبيقات الأسئلة الشائعة (FAQs API)](faqs.md) — إدارة إدخالات الأسئلة والأجوبة التي تستخدمها حملاتك.
- [الوصول إلى واجهة برمجة التطبيقات (API Access)](../integrations/api-access.md) — إنشاء مفتاح واجهة برمجة التطبيقات الخاص بك.
- [المصادقة](authentication.md) — جميع الطرق لتمرير مفتاحك.
