
# API אנשי קשר

איש קשר הוא אדם בודד שאליו אתה שולח הודעות — השם שלו, מספר הטלפון, האימייל, הערוץ, תגיות, שדות מותאמים אישית, והרשימות והקמפיינים שאליהם הוא שייך. ה-API של אנשי הקשר מאפשר לך ליצור אנשי קשר, לחפש אותם, לעדכן אותם, לתייג אותם, לייבא אותם בכמות גדולה ולהסיר אותם, וכל זאת מבלי להשתמש בלוח הבקרה.

כל הנתיבים בדף זה הם יחסיים לכתובת ה-URL הבסיסית:

```
https://api.youraiconnector.com/v1
```

לכן `/contacts` משמעו `https://api.youraiconnector.com/v1/contacts`.

> **חדש ב-API?** קרא תחילה את [גישה ל-API](../integrations/api-access.md) — הוא מכסה כיצד ליצור את מפתח ה-API שלך, שלוש הדרכים לאימות, מגבלות קצב, ופורמט השגיאות. כל מה שמופיע בדף זה מניח שכבר יש לך מפתח API פעיל.

---

## אודות מזהי אנשי קשר

לכל איש קשר יש מזהה (ID) ייחודי. המזהה שאתה מקבל בחזרה כאשר אתה **יוצר** איש קשר (ב-`data.contactId`) הוא אותו מזהה שבו תשתמש בכל מקום אחר — כדי לשלוף, לעדכן, לתייג, לשלוח הודעה או למחוק את איש הקשר הזה. שמור אותו פעם אחת והשתמש בו שוב.

אינך חייב ליצור איש קשר כדי לקבל את המזהה שלו. באפשרותך גם לחפש אותו לפי מספר טלפון או אימייל (ראה [קבלת איש קשר](#get-a-contact-by-phone-or-email)), או לדפדף בין כל אנשי הקשר שלך (ראה [רשימת אנשי קשר](#list-contacts)). כל אחת מהפעולות הללו מחזירה את אותו מזהה.

---

## יצירת איש קשר

`POST /contacts`

מוסיף איש קשר חדש לחשבונך. **נדרש מספר טלפון עם קידומת מדינה** — אימייל בלבד אינו מספיק. כל השאר הוא אופציונלי.

באפשרותך להוסיף את איש הקשר החדש ישירות לרשימה אחת או יותר באמצעות `listId` (רשימה בודדת) או `listIds` (מערך). אם שניהם נשלחים, `listIds` גובר.

כל שדה שתשלח שאינו אחד משדות היצירה הסטנדרטיים המפורטים בטבלת השדות של **יצירת איש קשר** להלן (`phoneNumber`, `firstName`, `lastName`, `email`, `channel`, `is_bot_active`, `is_private`, `lead_profile`, `listId`, `listIds`, `custom_fields`) נשמר אוטומטית כ**שדה מותאם אישית** — כך שמטען (payload) שטוח מכלי כמו Make או Zapier עובד ללא צורך בקינון. ניתן גם להעביר אובייקט `custom_fields` מפורש.

| שדה | נדרש | תיאור |
|---|---|---|
| `phoneNumber` | כן | מספר הטלפון של איש הקשר, עם קידומת מדינה (למשל `+15551234567`). |
| `firstName` | לא | שם פרטי. |
| `lastName` | לא | שם משפחה. |
| `email` | לא | כתובת אימייל. |
| `channel` | לא | ערוץ הודעות. אחד מ-`whatsapp`, `sms`, `whatsapp_web`. ברירת המחדל היא `whatsapp`. |
| `is_bot_active` | לא | האם העוזר הווירטואלי (AI) משיב לאיש קשר זה. ברירת המחדל היא `true`. |
| `is_private` | לא | סמן את איש הקשר כפרטי. כאשר `true`, העוזר הווירטואלי כבוי עבורו. ברירת המחדל היא `false`. |
| `lead_profile` | לא | הערות בטקסט חופשי על הליד. |
| `listId` | לא | מזהה רשימה בודד להוספת איש הקשר אליה. |
| `listIds` | לא | מערך של מזהי רשימות להוספת איש הקשר אליהן (גובר על `listId`). |
| `custom_fields` | לא | אובייקט של שדות מפתח/ערך משלך. באפשרותך גם להעביר אותם כמפתחות ברמה העליונה. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/contacts?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+15551234567",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane@example.com",
    "is_bot_active": true,
    "listIds": ["list123", "list456"]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/contacts", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    phoneNumber: "+15551234567",
    firstName: "Jane",
    lastName: "Smith",
    email: "jane@example.com",
    is_bot_active: true,
    listIds: ["list123", "list456"],
  }),
});
const data = await res.json();
console.log(data.data.contactId);
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/contacts",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "phoneNumber": "+15551234567",
        "firstName": "Jane",
        "lastName": "Smith",
        "email": "jane@example.com",
        "is_bot_active": True,
        "listIds": ["list123", "list456"],
    },
)
print(res.json()["data"]["contactId"])
```

**תגובה**

```json
{
  "success": true,
  "data": {
    "message": "Successfully created new contact",
    "contactId": "contact_abc123",
    "listsAdded": ["list123", "list456"]
  }
}
```

המזהה של איש הקשר החדש נמצא ב-`data.contactId`. הרשימות שאליהן הוא נוסף מוחזרות ב-`data.listsAdded`.

> **כפילויות לא נוצרות.** אם איש קשר עם אותו מספר טלפון כבר קיים, קריאת היצירה **לא** תיצור אותו ולא תחזיר אותו. התגובה חוזרת עם סטטוס HTTP `200` ו-`error_code` של `409` בגוף התגובה, לכן בצע הסתעפות לפי `error_code` במקום לפי סטטוס ה-HTTP:
>
> ```json
> { "success": false, "error_code": 409, "error": "A contact with this phone number already exists for the current user." }
> ```
>
> כדי לעבוד עם איש קשר קיים לאחר `error_code` של `409`, חפש אותו באמצעות [קבלת איש קשר לפי טלפון או אימייל](#get-a-contact-by-phone-or-email) — `GET /contacts?phoneNumber=...` — והשתמש מחדש במזהה (ID) שהוא מחזיר.

> **איותים שונים ב-WhatsApp נחשבים לאותו מספר.** במדינות מסוימות יש שני איותים תקפים לאותו קו נייד, ו-WhatsApp עשויה לדווח על כל אחד מהם: מקסיקו (`+52…` והגרסה הישנה `+521…`), ברזיל (עם או בלי הספרה התשיעית) וארגנטינה (עם או בלי ה-`9` אחרי ה-`+54`). בדיקת הכפילויות בעת יצירה ו-`GET /contacts?phoneNumber=` תואמת את שני האיותים, כך שתקבל בחזרה את איש הקשר הקיים ללא קשר לצורה שבה שלחת אותו. ה-`phone_number` שנשמר באיש הקשר לעולם אינו נכתב מחדש.

---

## קבלת איש קשר לפי טלפון או אימייל

`GET /contacts?phoneNumber=...` או `GET /contacts?email=...`

מחפש איש קשר בודד ומחזיר את אובייקט איש הקשר המלא והמועשר — כולל הרשימות, התגיות והקמפיינים שלו שנפתרו לזוגות `{ id, name }`, בתוספת ההודעה האחרונה שהוחלפה.

העבר **או** את `phoneNumber` (בפורמט בינלאומי) **או** את `email`. אם לא תעביר אף אחד מהם, נקודת קצה זו תעבור למצב [רשימת אנשי קשר](#list-contacts) במקום זאת.

**cURL**

```bash
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?phoneNumber=%2B15551234567&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const phone = encodeURIComponent("+15551234567");
const res = await fetch(`https://api.youraiconnector.com/v1/contacts?phoneNumber=${phone}`, {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.contact);
```

**Python**

```python
import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"phoneNumber": "+15551234567"},
)
print(res.json()["contact"])
```

**תגובה**

```json
{
  "success": true,
  "contactId": "contact_abc123",
  "contact": {
    "id": "contact_abc123",
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "jane@example.com",
    "phoneNumber": "+15551234567",
    "channel": "whatsapp",
    "isBotActive": true,
    "isPrivate": false,
    "doNotDisturb": false,
    "lead_profile": null,
    "avatarUrl": "https://example.com/photo.jpg",
    "customFields": {},
    "lists": [{ "id": "list123", "name": "VIP customers" }],
    "tags": [{ "id": "tagHotLead", "name": "Hot lead" }],
    "campaigns": [{ "id": "campaign789", "name": "Spring promo" }],
    "currentCampaign": { "id": "campaign789", "name": "Spring promo" },
    "lastMessage": {
      "direction": "inbound",
      "body": "Sounds good, thanks!",
      "status": "received",
      "timestamp": "2026-06-09T10:21:00.000Z"
    }
  }
}
```

מזהה איש הקשר מוחזר גם ברמה העליונה (`contactId`) וגם בתוך האובייקט (`contact.id`). אם אין התאמה, תקבל `404` עם `{ "success": false, "message": "Contact not found" }`.

> **`avatarUrl`** היא תמונת הפרופיל של איש הקשר, שנלקחה מ-WhatsApp או מ-Meta כאשר הם שולחים לך הודעה. היא לקריאה בלבד: לא ניתן להגדיר אותה, והיא `null` עבור אנשי קשר שאין להם תמונה או שפונים אליך בערוץ שאינו משתף תמונה כזו. התייחס לקישור כאל זמני במקום לשמור אותו, מכיוון שחלק מקישורי התמונות הללו פגים ומתרעננים באופן אוטומטי. (בנקודת הקצה של הרשימה להלן, אותו ערך נקרא `avatar_url`.)

> **מספרי טלפון בכתובות URL.** סימן `+` במחרוזת שאילתה חייב להיות מקודד כ-URL בתור `%2B`, אחרת הוא ייקרא כרווח. הדוגמאות לעיל עושות זאת עבורך.

---

## קבלת איש קשר לפי מזהה (ID)

`GET /contacts/{contactId}`

כאשר יש לך כבר את המזהה (ID) של איש קשר, ניתן לשלוף אותו ישירות. מבנה התגובה זהה לזה של החיפוש לעיל.

**cURL**

```bash
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.contact);
```

**Python**

```python
import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["contact"])
```

מזהה איש קשר שאינו קיים בחשבון שלך יחזיר `404`.

---

## קבלת נתוני סטטיסטיקה של איש קשר

`GET /contacts/{contactId}/stats`

מחזיר נתונים סטטיסטיים מצטברים של הודעות עבור איש קשר אחד: סך הכל, תשובות של בינה מלאכותית לעומת אנושיות, קרדיטים שנוצלו, וחותמות זמן של ההודעה הראשונה והאחרונה.

**cURL**

```bash
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/stats?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/stats", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.totalMessages, data.creditsUsed);
```

**Python**

```python
import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/stats",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
print(data["totalMessages"], data["creditsUsed"])
```

**תגובה**

```json
{
  "success": true,
  "totalMessages": 48,
  "sent": 21,
  "received": 27,
  "aiReplies": 18,
  "humanReplies": 3,
  "creditsUsed": 34,
  "botMessageCount": 18,
  "firstMessageAt": "2026-05-01T09:00:00.000Z",
  "lastMessageAt": "2026-06-09T10:21:00.000Z"
}
```

`botMessageCount` הוא אותו מונה הודעות בינה מלאכותית שכפתור ה-"איפוס" בתוך האפליקציה עבור איש קשר מאפס. `creditsUsed` הוא סך הקרדיטים המצטבר עבור איש קשר זה, ולא רק המספרים של תגובה זו. מזהה איש קשר שאינו קיים בחשבונך יחזיר `404`.

---

## רשימת אנשי קשר

`GET /contacts`

קרא ל-`GET /contacts` **ללא** `phoneNumber` או `email` כדי לדפדף בין כל אנשי הקשר שלך, מהחדש לישן. כל דף מחזיר סיכומים תמציתיים של אנשי קשר (רשימות, תגיות וקמפיינים מוחזרים כמערכי מזהים במקום כאובייקטים מלאים) ו-`next_cursor`.

| פרמטר שאילתה | תיאור |
|---|---|
| `limit` | גודל דף. ברירת המחדל היא 50, המקסימום הוא 100. |
| `cursor` | הערך `next_cursor` מהדף הקודם. השמט אותו בדף הראשון. |
| `listId` | אופציונלי. החזר רק אנשי קשר השייכים לרשימה זו. |

כדי לעבור על כל הדפים: בצע את הקריאה הראשונה ללא סמן (cursor), ולאחר מכן המשך להעביר את ה-`next_cursor` שהוחזר כ-`cursor`. **עצור כאשר `next_cursor` הוא `null`** — זה אומר שאין יותר תוצאות.

**cURL**

```bash
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?limit=50&apiKey=YOUR_API_KEY"

# next page:
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?limit=50&cursor=contact_abc123&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
async function listAllContacts() {
  const all = [];
  let cursor = null;
  do {
    const url = new URL("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts");
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("cursor", cursor);
    const res = await fetch(url, { headers: { "X-API-Key": "YOUR_API_KEY" } });
    const data = await res.json();
    all.push(...data.contacts);
    cursor = data.next_cursor;
  } while (cursor);
  return all;
}
```

**Python**

```python
import requests

def list_all_contacts():
    all_contacts = []
    cursor = None
    while True:
        params = {"limit": 100}
        if cursor:
            params["cursor"] = cursor
        res = requests.get(
            "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts",
            headers={"X-API-Key": "YOUR_API_KEY"},
            params=params,
        )
        data = res.json()
        all_contacts.extend(data["contacts"])
        cursor = data["next_cursor"]
        if not cursor:
            break
    return all_contacts
```

**תגובה**

```json
{
  "success": true,
  "contacts": [
    {
      "id": "contact_abc123",
      "first_name": "Jane",
      "last_name": "Smith",
      "email": "jane@example.com",
      "phone_number": "+15551234567",
      "channel": "whatsapp",
      "is_bot_active": true,
      "is_private": false,
      "do_not_disturb": false,
      "avatar_url": "https://example.com/photo.jpg",
      "custom_fields": {},
      "created_at": "2026-06-01T09:00:00.000Z",
      "list_ids": ["list123"],
      "tag_ids": ["tagHotLead"],
      "campaign_ids": ["campaign789"],
      "current_campaign_id": "campaign789"
    }
  ],
  "next_cursor": "contact_abc123"
}
```

::: note
**הערה:** סינון לפי `listId` שאינו קיים בחשבונך יחזיר `404`. `cursor` לא תקין יחזיר `400`.
:::


---

## ספירת אנשי קשר

`GET /contacts/count`

מחזירה כמה אנשי קשר תואמים למסנן מסוים, בתוספת פירוט לפי ערוץ, ללא צורך בדפדוף ביניהם. זוהי הקריאה המתאימה לכל שאלה מסוג "כמה יש" — עבור אריח בלוח בקרה, אוטומציה, או שאילתה ל-Champ. כל המסננים הם אופציונליים, ושילוב של כמה מהם יצמצם את הספירה (איש קשר חייב להתאים לכל אחד מהמסננים שתשלח).

| פרמטר שאילתה | תיאור |
|---|---|
| `agentId` | רק אנשי קשר שהוקצו לסוכן AI זה. העבר `none` עבור אנשי קשר ללא סוכן מוקצה (אלו נענים על ידי סוכן ברירת המחדל של הערוץ). |
| `channel` | רק אנשי קשר בערוץ זה, למשל `whatsapp`, `messenger`, `instagram`, `sms`, `email`, `chat_widget`. |
| `tag` | רק אנשי קשר הנושאים תגית זו, לפי **שם** התגית (אין חשיבות לאותיות גדולות/קטנות). שם תגית שאינו קיים יחזיר `404`. |
| `listId` | רק אנשי קשר ברשימה זו. |
| `botActive` | `true` או `false` — רק אנשי קשר שהעוזר ה-AI שלהם פעיל או כבוי. |
| `status` | רק אנשי קשר עם סטטוס זה, למשל `Lead`. |
| `rules` | אובייקט חוקי JSON מקודד ב-URL, המשתמש באותו מבנה כמו רשימה חכמה (ראה [מבנה ה-`smart_rules`](#the-smart_rules-shape) בהמשך). לא ניתן לשילוב עם המסננים האחרים. |

שלח ללא מסננים כלל ותקבל את המספר הכולל של אנשי הקשר בחשבונך.

**cURL**

```bash
# everything
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count?apiKey=YOUR_API_KEY"

# only the contacts one agent handles on Messenger
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count?agentId=agent_xyz789&channel=messenger&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const url = new URL("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count");
url.searchParams.set("agentId", "agent_xyz789");
url.searchParams.set("channel", "messenger");

const res = await fetch(url, { headers: { "X-API-Key": "YOUR_API_KEY" } });
const data = await res.json();
console.log(data.total);
```

**Python**

```python
import requests

res = requests.get(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/count",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"agentId": "agent_xyz789", "channel": "messenger"},
)
data = res.json()
print(data["total"])
```

**תגובה**

```json
{
  "success": true,
  "total": 3423,
  "by_channel": { "messenger": 2744, "instagram": 667, "none": 12 },
  "filters": { "agentId": "agent_xyz789" }
}
```

`by_channel` מפצלת את אותו סך כולל לפי ערוץ; אנשי קשר שאינם נמצאים באף ערוץ נספרים תחת `none`. `filters` מחזירה את המסננים שהוחלו, כך שתוכל לוודא שהקריאה ביצעה את מה שהתכוונת.

::: note
**הערה:** שליחת `rules` יחד עם כל מסנן אחר, או ערך `rules` שאינו JSON תקין, תחזיר `400`. שם תגית או מזהה רשימה שאינם קיימים בחשבונך יחזירו `404`.
:::


---

## עדכון איש קשר

`PUT /contacts/{contactId}`

מעדכן איש קשר קיים. רק השדות שתכלול ישתנו — השאר בחוץ כל מה שאינך רוצה לשנות. עליך לשלוח לפחות שדה אחד, אחרת תקבל `400` ("אין שדות לעדכון").

| שדה | תיאור |
|---|---|
| `firstName` | שם פרטי. |
| `lastName` | שם משפחה. |
| `email` | כתובת אימייל. |
| `is_bot_active` | האם העוזר הדיגיטלי משיב לאיש קשר זה. |
| `is_private` | סימון כפרטי. הגדרת ערך זה ל-`true` גם מכבה את העוזר הדיגיטלי. |
| `do_not_disturb` | השהיית פנייה אוטומטית לאיש קשר זה. בנוסף, מפסיק את העוזר הדיגיטלי מלהשיב. |
| `follow_ups_disabled` | עצירת כל המעקבים האוטומטיים עבור איש קשר זה (מהירים, מחזוריים ולידים קרים) בזמן שהעוזר הדיגיטלי ממשיך להשיב להודעות שהם שולחים. שימושי לאחר שמישהו ביצע רכישה. נשאר כבוי עד שתגדיר זאת בחזרה ל-`false`. |
| `lead_profile` | הערות ליד בטקסט חופשי. |
| `custom_fields` | אובייקט של שדות מותאמים אישית. **ממוזג לפי מפתח** — רק המפתחות שאתה שולח נכתבים, שאר השדות המותאמים אישית הקיימים נשמרים. ניתן גם להעביר מפתחות של שדות מותאמים אישית ברמה העליונה. |

**cURL**

```bash
curl -X PUT "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "firstName": "Jane", "do_not_disturb": true }'
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123", {
  method: "PUT",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ firstName: "Jane", do_not_disturb: true }),
});
const data = await res.json();
console.log(data.message);
```

**Python**

```python
import requests

res = requests.put(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"firstName": "Jane", "do_not_disturb": True},
)
print(res.json()["message"])
```

**תגובה**

```json
{
  "success": true,
  "message": "Contact updated successfully"
}
```

> **שדות מותאמים אישית ממוזגים, לא מוחלפים.** שליחת `{ "custom_fields": { "tier": "gold" } }` רק מגדירה את `tier` — כל שדה מותאם אישית אחר באיש הקשר יישאר בדיוק כפי שהיה. כדי להסיר שדה מותאם אישית לחלוטין מכל אנשי הקשר, השתמש ב-[מחיקת שדה מותאם אישית](#delete-a-custom-field).

---

## הוספה או הסרה של תגיות

`POST /contacts/{contactId}/tags`

מוסיף ו/או מסיר תגיות מאיש קשר בודד בקריאה אחת. העבר **מזהי** תגיות ב-`addTagIds` וב-`removeTagIds`. לפחות אחד מהשניים חייב להיות לא ריק.

התגיות חייבות כבר להיות קיימות בחשבונך — צור אותן תחילה דרך [נקודת הקצה של תגיות](reference.md). אם איש הקשר או אחת התגיות המוזכרות אינם קיימים, תקבל `404`.

| שדה | תיאור |
|---|---|
| `addTagIds` | מערך של מזהי תגיות להוספה לאיש הקשר. |
| `removeTagIds` | מערך של מזהי תגיות להסרה מאיש הקשר. |

**cURL**

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/tags?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "addTagIds": ["tagHotLead"], "removeTagIds": ["tagColdLead"] }'
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/tags", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    addTagIds: ["tagHotLead"],
    removeTagIds: ["tagColdLead"],
  }),
});
const data = await res.json();
console.log(data.added, data.removed);
```

**Python**

```python
import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/tags",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"addTagIds": ["tagHotLead"], "removeTagIds": ["tagColdLead"]},
)
data = res.json()
print(data["added"], data["removed"])
```

**תגובה**

```json
{
  "success": true,
  "contact_id": "contact_abc123",
  "added": 1,
  "removed": 1
}
```

---

## ניהול ספריית התגיות שלך

נקודות קצה אלו מנהלות את התגית עצמה — שינוי שם או מחיקה שלה מהחשבון שלך — בניגוד להחלה או הסרה של תגית מאיש קשר אחד (ראה [הוספה או הסרה של תגיות](#add-or-remove-tags) לעיל). לכל תגית בחשבונך יש מזהה (`tagId`): זה שמוצג במנהל התגיות בלוח הבקרה שלך, וזה שמוחזר כ-`data.tag_id` כאשר אתה יוצר תגית עם `POST /tags` וגוף JSON של `{ "name": "..." }` (ללא `phoneNumber`, `email`, או `contactId`).

### עדכון תגית

`PUT /tags/{tagId}`

שלח רק את השדות שברצונך לשנות.

| שדה | תיאור |
|---|---|
| `name` | שם התגית. |

```bash
curl -X PUT "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/tags/tagHotLead?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Hot lead (Q3)" }'
```

**תגובה**

```json
{ "success": true, "tag_id": "tagHotLead" }
```

`tagId` שאינו קיים בחשבונך יחזיר `404`.

### מחיקת תגית

`DELETE /tags/{tagId}`

מוחק תגית אחת לפי מזהה. **פעולה זו אינה ניתנת לביטול** — אנשי קשר הנושאים את התגית פשוט יאבדו אותה. מחיקת תגית שכבר אינה קיימת (או מעולם לא הייתה קיימת) תחזיר `200` עם `deleted: 0` במקום `404`, מכיוון שאין מה למנות.

```bash
curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/tags/tagColdLead?apiKey=YOUR_API_KEY"
```

**תגובה**

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

### מחיקת מספר תגיות בבת אחת

`DELETE /tags`

| שדה | תיאור |
|---|---|
| `tagIds` | מערך של מזהי תגיות למחיקה (עד 1000). |

```bash
curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/tags?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "tagIds": ["tagColdLead", "tagUnsubscribed"] }'
```

**תגובה**

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

מזהים שאינם קיימים, או ששייכים לחשבון אחר, ידולגו בשקט ולא ייספרו ב-`deleted`.

---

## הגדרת דגל בכמות גדולה

`POST /contacts/bulk-flag`

מגדיר דגל בוליאני אחד עבור אנשי קשר רבים בבת אחת. עד 500 מזהי אנשי קשר לכל בקשה. מזהים שאינם קיימים בחשבונך ידולגו וייספרו ב-`skipped`.

| שדה | תיאור |
|---|---|
| `contactIds` | מערך של מזהי אנשי קשר לעדכון (מקסימום 500). |
| `field` | איזה דגל להגדיר. אחד מ-`bot_active` (עוזר AI מופעל/כבוי), `dnd` (השהיית פנייה אוטומטית), `spam`, `private`. |
| `value` | הערך הבוליאני להגדרת הדגל. |

**cURL**

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-flag?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contactIds": ["contactId1", "contactId2"],
    "field": "bot_active",
    "value": false
  }'
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-flag", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    contactIds: ["contactId1", "contactId2"],
    field: "bot_active",
    value: false,
  }),
});
const data = await res.json();
console.log(data.updated, data.skipped);
```

**Python**

```python
import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-flag",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "contactIds": ["contactId1", "contactId2"],
        "field": "bot_active",
        "value": False,
    },
)
data = res.json()
print(data["updated"], data["skipped"])
```

**תגובה**

```json
{
  "success": true,
  "updated": 2,
  "skipped": 0
}
```

---

## ייבוא מרוכז של אנשי קשר

`POST /contacts/import`

יוצר עד 500 אנשי קשר בקריאה אחת מתוך מערך JSON. כל רשומה זקוקה ל-`phone_number` בפורמט בינלאומי; כל השאר אופציונלי. רשומות עם מספרי טלפון לא תקינים או ערוצים שאינם נתמכים **מדלגים עליהן** (הן לא נוצרות), וכל רשומה שנדלגה מדווחת עם האינדקס והסיבה שלה — כך שתוכל לתקן רק את הכשלים ולנסות שוב.

מספרי טלפון שכבר קיימים בחשבונך נדלגים כ-`duplicate` כברירת מחדל. שלח `updateExisting: true` כדי **לעדכן** את אנשי הקשר האלה במקום זאת: השדות הקיימים ברשומה דורסים את פרטי איש הקשר (`first_name`, `last_name`, `email`, `lead_profile`, ו-`custom_fields` ממוזגים מפתח לפי מפתח), `tags` מתווספים, ואיש הקשר מתווסף ל-`listId`. ערוץ, מספר טלפון ודגלי בוט לעולם לא משתנים באיש קשר קיים.

באפשרותך להוסיף באופן אופציונלי כל איש קשר מיובא (או מעודכן) לרשימה עם `listId`, להגדיר `defaultChannel` לרשומות שלא מציינות אחד כזה, ולתייג רשומות עם `tags` (שמות תגיות — תגיות חסרות נוצרות, קיימות מותאמות ללא תלות באותיות רישיות/קטנות).

**שדות ברמה העליונה**

| שדה | חובה | תיאור |
|---|---|---|
| `contacts` | כן | מערך של רשומות אנשי קשר (מקסימום 500). |
| `listId` | לא | רשימה להוספת כל איש קשר מיובא (ומעודכן). חייבת להיות רשימה בחשבונך. |
| `defaultChannel` | לא | ערוץ המוחל על רשומות שמשמיטות את `channel`. אחד מ-`whatsapp`, `sms`, `whatsapp_web`. ברירת המחדל היא `whatsapp`. |
| `updateExisting` | לא | `true` לעדכון אנשי קשר שמספר הטלפון שלהם כבר קיים במקום לדלג עליהם כ-`duplicate`. ברירת המחדל היא `false`. |

**שדות לכל רשומה**

| שדה | חובה | תיאור |
|---|---|---|
| `phone_number` | כן | מספר טלפון בפורמט בינלאומי (`+` מוביל מתווסף אם חסר). |
| `first_name` | לא | שם פרטי. |
| `last_name` | לא | שם משפחה. |
| `email` | לא | כתובת אימייל. |
| `channel` | לא | אחד מ-`whatsapp`, `sms`, `whatsapp_web`. חוזר ל-`defaultChannel` במקרה של חוסר. |
| `is_bot_active` | לא | האם עוזר ה-AI משיב. ברירת המחדל היא `true`. |
| `is_private` | לא | סימון כפרטי. ברירת המחדל היא `false`. |
| `lead_profile` | לא | הערות ליד בטקסט חופשי. |
| `custom_fields` | לא | אובייקט של מפתחות וערכים של שדות מותאמים אישית. |
| `tags` | לא | מערך של שמות תגיות (גם מחרוזת `"a; b"` בודדת עובדת). תגיות שלא קיימות נוצרות; קיימות מותאמות ללא תלות באותיות רישיות/קטנות. מקסימום 25 לרשומה. |

**cURL**

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      { "phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee", "tags": ["vip", "newsletter"] },
      { "phone_number": "+12025551235", "first_name": "Bob" }
    ],
    "listId": "list123",
    "defaultChannel": "whatsapp_web",
    "updateExisting": true
  }'
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    contacts: [
      { phone_number: "+12025551234", first_name: "Ann", last_name: "Lee", tags: ["vip", "newsletter"] },
      { phone_number: "+12025551235", first_name: "Bob" },
    ],
    listId: "list123",
    defaultChannel: "whatsapp_web",
    updateExisting: true,
  }),
});
const data = await res.json();
console.log(`Imported ${data.imported}, updated ${data.updated}, skipped ${data.skipped.length}`);
```

**Python**

```python
import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "contacts": [
            {"phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee", "tags": ["vip", "newsletter"]},
            {"phone_number": "+12025551235", "first_name": "Bob"},
        ],
        "listId": "list123",
        "defaultChannel": "whatsapp_web",
        "updateExisting": True,
    },
)
data = res.json()
print(f"Imported {data['imported']}, updated {data['updated']}, skipped {len(data['skipped'])}")
```

**תגובה**

```json
{
  "success": true,
  "imported": 2,
  "contact_ids": ["contact_abc123", "contact_def456"],
  "updated": 0,
  "updated_contact_ids": [],
  "skipped": []
}
```

אם לא ניתן ליצור רשומות מסוימות, הן יופיעו ב-`skipped` עם הסיבה (כאן ללא `updateExisting`, לכן המספר הקיים נדלג):

```json
{
  "success": true,
  "imported": 1,
  "contact_ids": ["contact_abc123"],
  "updated": 0,
  "updated_contact_ids": [],
  "skipped": [
    { "index": 1, "phone_number": "+12025551235", "reason": "duplicate" }
  ]
}
```

עם `updateExisting: true` אותה בקשה מדווחת על איש הקשר הקיים תחת `updated` / `updated_contact_ids` במקום זאת.

סיבות אפשריות לדילוג: `invalid_record`, `missing_phone_number`, `invalid_phone_number`, `invalid_channel`, `duplicate_in_request`, `duplicate`, `contact_limit_reached`, `create_failed`.

> **מגבלות תוכנית.** אם מגבלת אנשי הקשר בתוכנית שלך אינה מאפשרת כמות כזו של אנשי קשר חדשים, הבקשה כולה נדחית מראש עם `403`. אם המגבלה מגיעה במהלך התהליך, הרשומות הנותרות יוחזרו כרשומות שדלגו עליהן עם הסיבה `contact_limit_reached`.

---

## ייבוא אנשי קשר מקובץ CSV

עבור ייבוא גדול יותר ממה ש-[ייבוא מרוכז](#bulk-import-contacts) תומך בו (עד כ-50,000 שורות), יש להוסיף לתור משימת ייבוא אסינכרונית עבור קובץ CSV שכבר נמצא באחסון החשבון שלך, ולאחר מכן לבצע תשאול (poll) עד לסיומה.

### התחלת הייבוא

`POST /contacts/import-csv`

| שדה | חובה | תיאור |
|---|---|---|
| `csvStoragePath` | כן | נתיב האחסון של קובץ ה-CSV, תחת `users/{your account id}/imports/`, שמסתיים ב-`.csv`. |
| `listName` | כן | יוצר (או משתמש מחדש ב-) רשימה עם שם זה ומוסיף אליה כל איש קשר מיובא. |
| `existingListRefs` | לא | מערך של מזהי רשימות קיימות שגם אליהן יתווסף כל איש קשר מיובא. |
| `defaultChannel` | לא | ערוץ המוחל על שורות שלא מציינות ערוץ. |

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "csvStoragePath": "users/abc123/imports/leads.csv",
    "listName": "Webinar signups"
  }'
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    csvStoragePath: "users/abc123/imports/leads.csv",
    listName: "Webinar signups",
  }),
});
const data = await res.json();
console.log(data.job_id);
```

**Python**

```python
import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "csvStoragePath": "users/abc123/imports/leads.csv",
        "listName": "Webinar signups",
    },
)
job_id = res.json()["job_id"]
```

**תגובה** (`202` — הייבוא בתור, טרם הסתיים)

```json
{
  "success": true,
  "job_id": "csvimp_abc123",
  "status": "queued"
}
```

> **העברת הקובץ לאחסון.** נקודת קצה זו מתחילה ועוקבת אחר משימת הייבוא; היא אינה מקבלת העלאה בעצמה. קובץ ה-CSV צריך כבר להימצא ב-`csvStoragePath` לפני הקריאה אליה — כלי ייבוא ה-CSV של לוח הבקרה מבצע זאת כצעד ראשון.

### בדיקת סטטוס משימת הייבוא

`GET /contacts/import-csv/{jobId}`

```bash
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/import-csv/csvimp_abc123?apiKey=YOUR_API_KEY"
```

**תגובה**

```json
{
  "success": true,
  "job_id": "csvimp_abc123",
  "status": "completed",
  "imported": 812,
  "updated": 0,
  "skipped": 14,
  "errors": [],
  "error_message": null
}
```

`status` עובר דרך `queued` ← `processing` ← `completed`, או `failed` עם הסיבה ב-`error_message`. `jobId` שאינו קיים בחשבונך יחזיר `404`.

---

## ייצוא אנשי קשר

מפעיל ייצוא CSV אסינכרוני של אנשי הקשר שלך ומחזיר משימה שעליך לתשאל כדי לבדוק את השלמתה.

### התחלת הייצוא

`POST /contacts/export`

| שדה | חובה | תיאור |
|---|---|---|
| `listId` | לא | ייצוא אנשי קשר השייכים לרשימה זו בלבד. |
| `contactIds` | לא | ייצוא מזהי אנשי קשר ספציפיים אלו בלבד. |

השארת שני השדות ריקים תייצא את כל אנשי הקשר בחשבון שלך.

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "listId": "list123" }'
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ listId: "list123" }),
});
const data = await res.json();
console.log(data.job_id);
```

**Python**

```python
import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"listId": "list123"},
)
job_id = res.json()["job_id"]
```

**תגובה** (`202` — הייצוא בתור)

```json
{
  "success": true,
  "job_id": "export_abc123",
  "status": "queued"
}
```

### סקירת מצב משימת הייצוא

`GET /contacts/export/{jobId}`

```bash
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/export/export_abc123?apiKey=YOUR_API_KEY"
```

**תגובה**

```json
{
  "success": true,
  "job_id": "export_abc123",
  "status": "completed",
  "export_id": "exp_xyz789",
  "contact_count": 812,
  "error_message": null
}
```

> ברגע ש-`status` יהיה `"completed"`, תקבל `export_id` ו-`contact_count`. הורדת קובץ ה-CSV שנוצר מתבצעת מדף הייצוא בלוח הבקרה שלך.

---

## שלח הודעה לאיש קשר

`POST /contacts/{contactId}/send-message`

שולח הודעה לאיש קשר קיים בערוץ שבו הוא כבר נמצא. ההודעה מתווספת לתור ונשלחת ברקע — התגובה מאשרת שהיא התקבלה, לא שהיא כבר נמסרה.

| שדה | נדרש | תיאור |
|---|---|---|
| `body` | כן | טקסט ההודעה לשליחה. |
| `mediaUrl` | לא | כתובת URL של קובץ מדיה לצירוף. |
| `mediaContentType` | לא | סוג MIME של המדיה המצורפת (למשל `image/jpeg`). |

**cURL**

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/send-message?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "body": "Hi! Your appointment is confirmed." }'
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/send-message", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ body: "Hi! Your appointment is confirmed." }),
});
const data = await res.json();
console.log(data.messageId);
```

**Python**

```python
import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/send-message",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"body": "Hi! Your appointment is confirmed."},
)
print(res.json()["messageId"])
```

**תגובה**

```json
{
  "success": true,
  "messageId": "aB3dE5fG7hI9jK1lM2nO",
  "contactId": "contact_abc123",
  "channel": "whatsapp",
  "message": "Message created successfully. Delivery is being processed."
}
```

> **לא ניתן לשלוח כרגע?** אם איש הקשר הפעיל מצב 'נא לא להפריע' או מצב פרטי, או שאינו נמצא בערוץ שיכול לקבל הודעות יוצאות, הבקשה תידחה עם `422` ו-`error` הסברי. 

לשליחה לפי מספר טלפון, מזהה אינסטגרם או זהות ערוץ אחרת במקום לפי מזהה איש קשר — ולמידע נוסף על הודעות באופן כללי — עיינו ב-[Messages API](messages.md).

---

## הקצאת סוכן בינה מלאכותית לאיש קשר

`POST /contacts/{contactId}/assign-agent`

מעביר שיחה קיימת לסוכן בינה מלאכותית אחר, החל מההודעה הבאה ואילך. פעולה זו זהה ל-**הקצאת סוכן בינה מלאכותית** בתפריט הצ'אט, וזהה לשלב שבו משתמשת הפעולה **הקצאת סוכן בינה מלאכותית או קמפיין** באוטומציות.

| שדה | חובה | תיאור |
|---|---|---|
| `agentId` | כן | המזהה (ID) של סוכן הבינה המלאכותית שאמור להשתלט על השיחה, או `null` כדי לנקות את ההקצאה כך שהשיחה תחזור לתיבת הדואר הנכנס של הצוות שלך. |
| `triggerAIResponse` | לא | `true` גורם לסוכן שהוקצה זה עתה להשיב להודעות האחרונות שלא נענו של איש הקשר באופן מיידי. ברירת המחדל היא `false`. |

> **זהירות עם `triggerAIResponse: true`** — פעולה זו שולחת לאיש הקשר הודעה באותו רגע, לכן השתמש בה רק כאשר ברצונך שהם יקבלו הודעה עכשיו. ב-Messenger וב-Instagram הודעה זו תיכשל אם איש הקשר כתב לך לאחרונה לפני יותר מ-24 שעות.

**cURL**

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/assign-agent?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "agentId": "agent_xyz789" }'
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/assign-agent", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ agentId: "agent_xyz789" }),
});
const data = await res.json();
console.log(data.data.agentId);
```

**Python**

```python
import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/assign-agent",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"agentId": "agent_xyz789"},
)
print(res.json()["data"]["agentId"])
```

**תגובה**

```json
{
  "success": true,
  "data": {
    "contactId": "contact_abc123",
    "agentId": "agent_xyz789",
    "aiResponseTriggered": false
  }
}
```

> הסוכן חייב להשתייך לאותו חשבון כמו איש הקשר; אחרת הבקשה תידחה עם `404` או `403`. ניתן למצוא מזהי סוכנים בדף סוכני בינה מלאכותית (ה-URL של כל סוכן מסתיים במזהה שלו).

---

## הקצאת סוכן AI למספר רב של אנשי קשר

`POST /contacts/bulk-assign-agent`

מעבירה שיחות רבות לסוכן AI אחר בקריאה אחת — או מנקה את ההקצאה עבור כולם עם `null`. זהו שינוי ניתוב בלבד: **לא נשלחת הודעה והסוכן לא משיב לאף אחד**. כל איש קשר פשוט מקבל את הסוכן החדש בפעם הבאה שהוא כותב. (זו הסיבה שאין כאן `triggerAIResponse`).

| שדה | נדרש | תיאור |
|---|---|---|
| `agentId` | כן | סוכן ה-AI שצריך להשתלט, או `null` כדי לנקות את ההקצאה. |
| `contactIds` | אחד משלושתם | עד 500 מזהי אנשי קשר להעברה. |
| `filter` | אחד משלושתם | בחר את אנשי הקשר בשרת במקום לרשום אותם, מהחדש לישן. מקבל את אותם מפתחות כמו מסנני נקודת הקצה של הספירה: `agentId` (או `none`), `channel`, `tag`, `listId`, `botActive`, `status`. |
| `rules` | אחד משלושתם | אובייקט חוקי רשימה חכמה — ראה [מבנה ה-`smart_rules`](#the-smart_rules-shape). |
| `limit` | לא | כמה אנשי קשר להעביר בקריאה זו כאשר אתה בוחר עם `filter` או `rules`. 1 עד 500, ברירת המחדל היא 500. |

שלח בדיוק אחד מ-`contactIds`, `filter` או `rules`.

**cURL**

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-assign-agent?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "agent_xyz789",
    "filter": { "agentId": "agent_abc123", "channel": "messenger" }
  }'
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-assign-agent", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    agentId: "agent_xyz789",
    filter: { agentId: "agent_abc123", channel: "messenger" },
  }),
});
const data = await res.json();
console.log(data.updated, data.remaining);
```

**Python**

```python
import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/bulk-assign-agent",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "agentId": "agent_xyz789",
        "filter": {"agentId": "agent_abc123", "channel": "messenger"},
    },
)
data = res.json()
print(data["updated"], data["remaining"])
```

**תגובה**

```json
{
  "success": true,
  "agentId": "agent_xyz789",
  "matched": 3415,
  "updated": 500,
  "skipped": 0,
  "remaining": 2915,
  "filters": { "agentId": "agent_abc123" }
}
```

`matched` הוא כמה אנשי קשר נמצאו בבחירה בסך הכל, `updated` כמה הועברו על ידי קריאה זו, `skipped` כמה מהמזהים ששלחת לא נמצאו בחשבונך, ו-`remaining` כמה עדיין תואמים כעת לאחר סיום הקריאה.

**העברת כולם.** מכיוון שקריאה מעבירה לכל היותר 500 אנשי קשר, קבוצה גדולה דורשת מספר קריאות. השתמש במסנן שמפסיק להתאים לאיש קשר ברגע שהוא הועבר — למשל `filter: { "agentId": "agent_abc123" }` בזמן הקצאה ל-`agent_xyz789` — וחזור על אותה קריאה בדיוק עד ש-`remaining` יחזור כ-`0`. כאשר אתה מעביר `contactIds` במקום זאת, `remaining` הוא תמיד `0`.

---

## שיוך איש קשר למחלקה

`POST /contacts/{contactId}/department`

"שייך ליד זה למכירות" — מתייק איש קשר תחת מחלקה בעלת שם, וברירת המחדל היא להעביר אותו למי שבאותה מחלקה יש כרגע הכי פחות אנשי קשר. פעולה זו נפרדת מ-[שיוך סוכן בינה מלאכותית](#assign-an-ai-agent-to-a-contact): מחלקה עונה על השאלה "איזה צוות אחראי על זה", סוכן עונה על השאלה "איזו בינה מלאכותית עונה על זה", והגדרה של אחד לעולם לא מוחקת את השני.

| שדה | חובה | תיאור |
|---|---|---|
| `department_id` | כן | המחלקה שתחתיה יש לתייק את איש הקשר. העבר `null` כדי לנקות זאת. |
| `hand_to_member` | לא | העבר את איש הקשר גם לאדם העמוס פחות באותה מחלקה. ברירת המחדל היא `true`. לעולם לא יבוצע שיוך מחדש לאיש קשר שכבר שייך למישהו. |

**cURL**

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/department?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "department_id": "dept_sales" }'
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/department", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ department_id: "dept_sales" }),
});
const data = await res.json();
console.log(data.assigned_to);
```

**Python**

```python
import requests

res = requests.post(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/department",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"department_id": "dept_sales"},
)
print(res.json()["assigned_to"])
```

**תגובה**

```json
{
  "success": true,
  "department_id": "dept_sales",
  "assigned_to": "member_uid_123"
}
```

`assigned_to` הוא `null` כאשר איש הקשר כבר היה שייך למישהו, או שהעברת `hand_to_member: false`.

---

## קישור איש קשר בין ערוצים

"המשך ב-WhatsApp" (או ב-SMS) מוצא או יוצר את איש הקשר של אדם זה בערוץ מבוסס טלפון אחר ומקשר בין השניים, כך ששאר האפליקציה תזהה אותם כאותו אדם.

### קישור לערוץ אחר

`POST /contacts/{contactId}/link-channel`

| שדה | חובה | תיאור |
|---|---|---|
| `channel` | כן | הערוץ לקישור. אחד מתוך `whatsapp`, `whatsapp_web`, `sms`. |
| `phoneNumber` | לא | מספר טלפון לשימוש בערוץ החדש. כברירת מחדל משתמש במספר של איש הקשר המקורי. |

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/link-channel?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "sms" }'
```

**תגובה**

```json
{
  "success": true,
  "data": {
    "contact_id": "contact_def456",
    "person_id": "person_xyz789",
    "created": true
  }
}
```

`created` מציין אם נוצר איש קשר חדש עבור ערוץ היעד או שנמצא איש קשר קיים וקושר. קריאה לפעולה זו פעם שנייה היא בטוחה — היא מחזירה את אותו `contact_id` עם `created: false` במקום ליצור כפילות.

`422` פירושו שהחשבון אינו יכול לבצע קישור זה כרגע: איש הקשר כבר נמצא במשפחת ערוצים זו, אין לו מספר טלפון לשימוש, או שאין שולח מחובר עבור ערוץ היעד. `409` פירושו ששני אנשי הקשר כבר מקושרים לשני אנשים שונים — יש לבטל תחילה את הקישור של אחד מהם.

### הצגת רשימת השיחות המקושרות של איש קשר

`GET /contacts/{contactId}/linked`

מחזיר את השיחות האחרות השייכות לאותו אדם כמו איש קשר זה. איש קשר שאינו מקושר יחזיר מערך ריק, לא `404` — "לאדם זה אין ערוצים אחרים" הוא מצב תקין.

```bash
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/linked?apiKey=YOUR_API_KEY"
```

**תגובה**

```json
{
  "success": true,
  "data": [
    {
      "contact_id": "contact_def456",
      "channel": "sms",
      "custom_channel": null,
      "first_name": "Jane",
      "last_name": "Smith",
      "phone_number": "+15551234567",
      "last_message": "Sounds good, thanks!",
      "last_message_timestamp": "2026-06-09T10:21:00.000Z",
      "linked_from": {
        "contact_id": "contact_abc123",
        "channel": "whatsapp",
        "linked_at": "2026-06-01T09:00:00.000Z",
        "reason": "continue_on_channel"
      }
    }
  ]
}
```

### ביטול קישור של איש קשר

`DELETE /contacts/{contactId}/link`

מסיר את איש הקשר הזה מהאדם שאליו הוא משויך, באופן חד-צדדי — כל אנשי הקשר האחרים שעדיין מקושרים לאותו אדם שומרים על הקישור שלהם, כך שביטול קישור של אחד מתוך שלושה אינו מפרק את הקבוצה.

```bash
curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/link?apiKey=YOUR_API_KEY"
```

**תגובה**

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

---

## שליפת תמונת פרופיל של איש קשר

`POST /contacts/{contactId}/profile-pic`

שולף (ומשמור במטמון) את תמונת הפרופיל של איש הקשר ב-WhatsApp או ב-Meta לפי דרישה — אותה תמונה שמוחזרת כ-`avatarUrl` ב-[קבלת איש קשר](#get-a-contact-by-phone-or-email), לאחר רענון.

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123/profile-pic?apiKey=YOUR_API_KEY"
```

**תגובה**

```json
{
  "success": true,
  "avatar_url": "https://example.com/photo.jpg",
  "cached": false
}
```

`cached: true` פירושו שה-URL הגיע משליפה אחרונה ולא מחיפוש טרי אצל הספק — תמונות נשמרות במטמון למשך 7 ימים, ואיש קשר שהספק מדווח שאין לו תמונה זמינה נשמר במטמון כלא זמין למשך 24 שעות. כאשר אין תמונה לשליפה, `avatar_url` מושמט ו-`message` מסביר מדוע.

---

## תיוג אוטומטי של אנשי קשר באמצעות בינה מלאכותית

מריץ את חוקי התיוג של החשבון שלך על היסטוריית השיחות המלאה של איש קשר אחד או יותר ומחיל (או מסיר) תגיות בדיוק כמו התיוג בזמן אמת שפועל במהלך צ'אט חי — אותם חוקים, אותה עלות קרדיט לכל תגית.

### התחלת הרצה

`POST /contacts/auto-tag`

| שדה | חובה | תיאור |
|---|---|---|
| `scope` | כן | `"contacts"` כדי לתייג אנשי קשר ספציפיים, או `"agent"` כדי לתייג כל שיחה שמטופלת כרגע על ידי סוכן בינה מלאכותית אחד. |
| `contact_ids` | חובה כאשר `scope` הוא `"contacts"` | מערך של מזהי אנשי קשר, 1 עד 500. |
| `agent_id` | חובה כאשר `scope` הוא `"agent"` | סוכן הבינה המלאכותית שהשיחות שלו יתויגו. כאשר `scope` הוא `"contacts"`, שדה זה הוא אופציונלי ורק מצמצם את חוקי התיוג של הסוכן שיופעלו. |

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/auto-tag?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "scope": "contacts", "contact_ids": ["contact_abc123", "contact_def456"] }'
```

עבור איש קשר **יחיד**, ההרצה מתבצעת באופן מקוון (inline) ומחזירה את התוצאה מיד:

```json
{ "success": true, "result": { "tags_applied": 2, "tags_removed": 0 } }
```

**שני אנשי קשר או יותר** (או `scope: "agent"`) רצים כמשימת רקע ומחזירים `202` באופן מיידי:

```json
{ "success": true, "run_id": "m1x2y3-a1b2c3d4", "total": 214 }
```

### בדיקת מצב הרצה (Poll)

`GET /contacts/auto-tag/run`

מחזיר את ההרצה הנוכחית (או האחרונה ביותר) של החשבון, כך שתוכל לבדוק את ההתקדמות מבלי לעקוב אחר `run_id` בעצמך.

```bash
curl "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/auto-tag/run?apiKey=YOUR_API_KEY"
```

**תגובה**

```json
{
  "success": true,
  "run": {
    "run_id": "m1x2y3-a1b2c3d4",
    "status": "running",
    "total": 214,
    "processed": 58,
    "tagged_contacts": 12,
    "tags_applied": 15,
    "tags_removed": 2,
    "credits_charged": 15
  }
}
```

`run` הוא `null` כאשר החשבון מעולם לא התחיל הרצה. `status` עובר מ-`"running"` ל-`"completed"` או ל-`"failed"`.

רק הרצה מרוכזת אחת יכולה להיות בתהליך עבור חשבון בכל פעם — התחלת הרצה שנייה בזמן שאחרת פועלת תחזיר `409` עם `error_code: "auto_tag_run_in_progress"`. סיום הקרדיטים בהרצה של איש קשר יחיד יחזיר `402` עם `error_code: "insufficient_credits"`; הרצה מרוכזת לעומת זאת תעצור את עצמה מוקדם ותדווח עד היכן הגיעה ב-`run`.

---

## מחיקת איש קשר

`DELETE /contacts/{contactId}`

מוחק לצמיתות איש קשר אחד לפי מזהה, יחד עם היסטוריית ההודעות שלו. **פעולה זו אינה ניתנת לביטול.** כדי למחוק מספר אנשי קשר בקריאה אחת, השתמש ב-[מחיקת אנשי קשר](#delete-contacts) להלן.

**cURL**

```bash
curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123", {
  method: "DELETE",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.success);
```

**Python**

```python
import requests

res = requests.delete(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/contact_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["success"])
```

**תגובה**

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

מזהה איש קשר שאינו קיים בחשבונך, או ששייך לחשבון אחר, יחזיר `404`.

---

## מחיקת אנשי קשר

`DELETE /contacts`

מוחק לצמיתות איש קשר אחד או יותר לפי מזהה בקריאה אחת (עד 500 מזהים). מזהים שאינם קיימים בחשבון שלכם ידולגו ויימנו ב-`skipped`. **לא ניתן לבטל פעולה זו.**

| שדה | תיאור |
|---|---|
| `contactIds` | מערך של מזהי אנשי קשר למחיקה (מקסימום 500). |

**cURL**

```bash
curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contactIds": ["contactId1", "contactId2"] }'
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts", {
  method: "DELETE",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ contactIds: ["contactId1", "contactId2"] }),
});
const data = await res.json();
console.log(`Deleted ${data.deleted}, skipped ${data.skipped}`);
```

**Python**

```python
import requests

res = requests.delete(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"contactIds": ["contactId1", "contactId2"]},
)
data = res.json()
print(f"Deleted {data['deleted']}, skipped {data['skipped']}")
```

**תגובה**

```json
{
  "success": true,
  "deleted": 2,
  "skipped": 0
}
```

---

## מחיקת שדה מותאם אישית

`DELETE /contacts/custom-fields/{fieldKey}`

מסיר מפתח שדה מותאם אישית מ**כל** איש קשר בחשבונך. השתמש באפשרות זו כדי לבצע ניקוי לאחר שינוי שם או הוצאה משימוש של שדה מותאם אישית. המפתח יכול להכיל אותיות, מספרים, קווים תחתונים ומקפים בלבד. מחזיר את מספר אנשי הקשר שעודכנו. **פעולה זו אינה ניתנת לביטול.**

**cURL**

```bash
curl -X DELETE "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/custom-fields/webinar_date_nh?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/custom-fields/webinar_date_nh", {
  method: "DELETE",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(`Removed from ${data.updated} contacts`);
```

**Python**

```python
import requests

res = requests.delete(
    "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/contacts/custom-fields/webinar_date_nh",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(f"Removed from {res.json()['updated']} contacts")
```

**תגובה**

```json
{
  "success": true,
  "updated": 42
}
```

::: note
**הערה:** מפתח שדה עם תווים שאינם נתמכים יחזיר `400`.
:::


---

## רשימות

רשימות מקבצות אנשי קשר. רשימה היא או **סטטית** (אתה מחליט מי נמצא בה) או **חכמה** (החברות בה מחושבת מתוך כללים ומתעדכנת אוטומטית — ראה [ארגון רשימות ואנשי קשר](../get-started/list-and-contact-management.md#smart-lists-auto-updating)).

| שדה | תיאור |
|---|---|
| `name` | חובה בעת יצירה. עד 100 תווים. |
| `status` | `live` (ברירת מחדל) או `draft`. אותיות קטנות בלבד. |
| `contact_ids` | מערך של מזהי אנשי קשר להוספה לרשימה. **רשימות סטטיות בלבד.** |
| `type` | `static` (ברירת מחדל) או `smart`. |
| `smart_rules` | קבוצת הכללים — חובה כאשר `type` הוא `smart`. ראה להלן. |

### יצירת רשימה

`POST /lists`

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/lists?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "Hot leads (active)",
        "type": "smart",
        "smart_rules": {
          "match": "all",
          "conditions": [
            { "field": "tags", "op": "has_any", "value": ["tagHotLead"] },
            { "field": "last_activity_at", "op": "within_last", "value": { "amount": 90, "unit": "days" } }
          ]
        }
      }'
```

**תגובה**

```json
{
  "success": true,
  "list_id": "list_abc123",
  "evaluation": { "added": 3, "removed": 0, "total": 3 }
}
```

רשימה חכמה מוערכת **בזמן אמת** (inline), באותה בקשה, כך ש-`evaluation` מציג לך בדיוק מי נכלל בה. ברשימה סטטית, `evaluation` הוא `null`.

### עדכון רשימה

`PUT /lists/{listId}`

שלח רק את השדות שאתה משנה. שינוי `smart_rules` מעריך מחדש את הרשימה באופן מיידי ומחזיר את אותו אובייקט `evaluation`.

```bash
curl -X PUT "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/lists/list_abc123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "smart_rules": { "match": "any", "conditions": [ { "field": "tags", "op": "has_any", "value": ["tagHotLead", "tagWebinar"] } ] } }'
```

ניתן להעביר רשימה בין שני הסוגים:

- **סטטית ← חכמה**: שלח `{ "type": "smart", "smart_rules": { … } }`. הכללים נכנסים לתוקף במקום.
- **חכמה ← סטטית**: שלח `{ "type": "static" }`. הכללים מוסרים וכל מי שנמצא ברשימה נשאר בה.

### המבנה של `smart_rules`

```json
{
  "match": "all",
  "conditions": [
    { "field": "tags", "op": "has_any", "value": ["tagHotLead"] },
    { "field": "channel", "op": "is_any", "value": ["whatsapp", "sms"] },
    { "field": "last_incoming_message_at", "op": "not_within_last", "value": { "amount": 7, "unit": "days" } },
    { "field": "created_at", "op": "after", "value": "2026-01-01" },
    { "field": "is_bot_active", "op": "is", "value": true },
    { "field": "email", "op": "is_set" },
    { "field": "custom_field", "key": "Plan", "op": "eq", "value": "pro" }
  ]
}
```

- `match` — `all` (כל תנאי חייב להיות נכון) או `any` (לפחות אחד).
- `conditions` — 1 עד 20 תנאים, כל אחד עם לכל היותר 100 ערכים, מחרוזות עד 200 תווים.

| `field` | `op` | `value` |
|---|---|---|
| `tags` | `has_any`, `has_all`, `has_none` | מערך של מזהי תגיות |
| `lists` | `in_any`, `not_in_any` | מערך של מזהי רשימות (**רשימות סטטיות בלבד** — לא ניתן לבנות רשימה חכמה מרשימה חכמה אחרת) |
| `channel` | `is_any`, `is_none` | מערך של ערוצים |
| `status` | `is_any`, `is_none` | מערך של סטטוסים של אנשי קשר |
| `created_at`, `last_activity_at`, `last_incoming_message_at`, `last_outgoing_message_at`, `first_ai_interaction_at`, `last_ai_interaction_at` | `within_last`, `not_within_last` | `{ "amount": 1–3650, "unit": "hours" \| "days" }` |
| אותם שדות תאריך | `before`, `after` | תאריך ISO (`"2026-01-01"`, מושווה כימים שלמים) או תאריך-שעה ISO מלא (`"2026-01-01T14:30:00Z"`, מושווה לרגע המדויק) |
| אותם שדות תאריך | `is_set`, `not_set` | — |
| `has_interacted_with_ai` | `is` | `true` / `false` — `true` מתאים לאנשי קשר שה-AI שלח להם הודעה לפחות פעם אחת (אי פעם) |
| `is_bot_active`, `do_not_disturb`, `is_private`, `has_ever_responded` | `is` | `true` / `false` |
| `email`, `phone_number`, `first_name`, `last_name` | `is_set`, `not_set`, `contains`, `not_contains` | מחרוזת עבור טפסי ה-`contains` |
| `current_campaign_id`, `assigned_agent` | `is_any`, `is_none`, `is_set`, `not_set` | מערך של מזהים עבור טפסי ה-`is_any` / `is_none` |
| `custom_field` (בתוספת `key`) | `eq`, `neq`, `contains`, `not_contains`, `is_set`, `not_set` | מחרוזת עבור טפסי הערך |

`not_within_last` תואם גם לאנשי קשר שהתאריך עבורם מעולם לא הוגדר ("לפני יותר מ-N, **או לעולם לא**"), והשוואות טקסט מתעלמות מאותיות גדולות/קטנות.

**מעורבות AI.** `has_interacted_with_ai` הוא דגל לכל אורך החיים: `true` עבור כל איש קשר שה-AI שלך שלח לו הודעה אחת לפחות, `false` עבור כל השאר (כולל אנשי קשר שרק הצוות שלך ענה להם אי פעם). הוא מוטבע בהודעה הראשונה של ה-AI לאיש קשר ולעולם לא מתאפס, לכן כיבוי תשובות ה-AI של איש הקשר או העברתו לקמפיין אחר לא יאפסו אותו. עבור *תקופה* — "אנשי הקשר שה-AI שלי טיפל בהם החודש", שאלת החיוב הרגילה — השתמש בטווחים מעל `last_ai_interaction_at` במקום:

```json
{ "field": "last_ai_interaction_at", "op": "within_last", "value": { "amount": 30, "unit": "days" } }
```

אל תבלבל ביניהם לבין `is_bot_active` (ה-AI *מורשה* להשיב, לא שהוא אכן עשה זאת) או `has_ever_responded` (איש הקשר השיב, לכל אחד). אותן שתי חותמות מוחזרות על כל איש קשר כ-`first_ai_interaction_at` / `last_ai_interaction_at`, וכל מערכת הכללים עובדת גם על `GET /contacts?rules=`, כך שתוכל לספור התאמות מבלי ליצור רשימה.

### תצוגה מקדימה של קבוצת חוקים

`POST /lists/preview`

סופר ודוגם את אנשי הקשר שקבוצת חוקים תתאים להם, מבלי ליצור או לשנות דבר. השתמש בזה כדי לבצע בדיקת תקינות לחוקים לפני שמירתם.

```bash
curl -X POST "<span data-t="apiBaseUrl">https://api.youraiconnector.com</span>/v1/lists/preview?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "smart_rules": { "match": "all", "conditions": [ { "field": "tags", "op": "has_any", "value": ["tagHotLead"] } ] } }'
```

**תגובה**

```json
{
  "success": true,
  "count": 3,
  "sample": [
    {
      "id": "contact_abc123",
      "first_name": "Sofia",
      "last_name": "Martinez",
      "phone_number": "+31600000000",
      "email": "sofia@example.com",
      "channel": "whatsapp"
    }
  ]
}
```

`sample` מכיל עד 10 אנשי קשר, מהפעיל ביותר לראשון.

### הרצה מחדש של רשימה חכמה כעת

`POST /lists/{listId}/evaluate`

מאלץ הערכה מחדש מיידית (זהה לפעולת **רענן כעת** בלוח הבקרה). רשימות חכמות מתעדכנות ממילא כאשר איש קשר משתנה, ובכל 15 דקות עבור חוקים מבוססי זמן, לכן פעולה זו נחוצה רק כאשר ברצונך לקבל את התוצאה *ברגע זה*.

**תגובה**

```json
{
  "success": true,
  "list_id": "list_abc123",
  "evaluation": { "added": 2, "removed": 1, "total": 4 }
}
```

`evaluation.skipped: true` פירושו שהערכה נוספת של אותה רשימה כבר רצה וקריאה זו לא ביצעה דבר.

### רשימות חכמות מסרבות לחברים שנבחרו ידנית

נקודות קצה של חברות מחזירות **`409`** עם `"This is a smart list — its members are computed from its rules. Edit the rules instead."` כאשר רשימת היעד היא חכמה. זה מכסה את `POST /contacts/lists`, `DELETE /contacts/lists`, `POST /contacts/lists/batch`, `contact_ids` ב-`POST /lists` וב-`PUT /lists/{listId}`, ובחירה ברשימה חכמה כיעד לייבוא CSV. שנה את החוקים במקום זאת.

קריאה ל-`POST /lists/{listId}/evaluate` ברשימה **סטטית** היא גם `409` — אין לה חוקים להרצה.

---

## שגיאות ב-API של אנשי קשר

נקודות קצה (endpoints) של אנשי קשר מחזירות את מעטפת השגיאה הסטנדרטית:

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

חלק מנקודות הקצה (endpoints) כוללות גם `error_code`, שבדרך כלל תואם לסטטוס ה-HTTP — החריג היחיד הוא מקרה של איש קשר כפול להלן, שבו סטטוס ה-HTTP הוא `200` ורק `error_code` נושא את ה-`409`. הקודים הספציפיים לנקודות קצה של אנשי קשר:

| קוד | מתי זה קורה בנקודת קצה של איש קשר |
|---|---|
| `400` | בקשה שגויה — שדה חסר/לא תקין, גוף ריק, סמן (cursor) שגוי, או מעל 500 מזהים באצווה. |
| `402` | אין מספיק קרדיטים להשלמת הרצת תיוג AI על איש קשר אחד (`error_code: "insufficient_credits"`). |
| `404` | איש הקשר, הרשימה או התגית לא נמצאו בחשבונך. |
| `409` | איש קשר עם מספר טלפון זה כבר קיים (ביצירה). מוחזר כ-`error_code` בגוף הבקשה עם סטטוס HTTP של `200`, לכן יש לבצע פיצול (branch) לפי `error_code` כאן. מוחזר גם כאשר הרצת תיוג אוטומטי מרוכז כבר נמצאת בעיצומה (`error_code: "auto_tag_run_in_progress"`), או כאשר קישור איש קשר לערוץ אחר יחבר שני אנשי קשר שכבר מקושרים לשני אנשים שונים. |
| `422` | איש הקשר אינו יכול לקבל הודעה כרגע (נא לא להפריע, פרטי, או ערוץ שאינו נתמך). בנקודת הקצה של קישור ערוץ, מכסה גם מצב של חוסר במספר טלפון, זיווג ערוצים לא נתמך, או חוסר בשולח מחובר עבור ערוץ היעד. |

`403` בנקודת קצה של איש קשר יכול גם להצביע על בעיית מגבלת אנשי קשר או הרשאת רשימה, ולאו דווקא על גישה במסגרת התוכנית. הקודים המשותפים שכל נקודת קצה יכולה להחזיר — `401`, `403` (התוכנית שלך אינה כוללת גישת API), `429` (מגבלת קצב) ו-`500` — מפורטים עם הנחיות לניסיון חוזר ב-[שגיאות ועימוד](errors-and-pagination.md).

---

## צעדים הבאים

- [API של הודעות](messages.md) — שליחת הודעות לפי זהות ערוץ וניהול שיחות.
- [תיעוד API](reference.md) — רשימת נקודות קצה מלאה, כולל תגיות ורשימות.
- [גישת API](../integrations/api-access.md) — אימות, מגבלות קצב וטיפול בשגיאות.
