
# פגישות

ממשק ה-API של פגישות (Appointments API) מאפשר לך לקבוע פגישות עבור אנשי הקשר שלך בסוגי האירועים שלך, ולאחר מכן לאחזר, להציג, לעדכן, לבטל או למחוק אותן. הוא גם עונה על השאלה שעולה ראשונה ברוב תהליכי ההזמנה — אילו זמנים הם אכן פנויים — ומכסה את הצד של היומן: הצגת יומני Google שחיברת וייבוא אירועים שכבר קיימים בהם. כאשר חיבור ליומן Google פעיל, אירוע היומן התואם נוצר ומסונכרן באופן אוטומטי ברקע. מסעדות המשתמשות ב-Zenchef, Formitable, OpenTable או TheFork עבור מערכת ההזמנות שלהן יכולות גם הן לעבור אימות וחיבור כאן, כך שהסוכן הבינה המלאכותית (AI Agent) יזמין שולחנות אמיתיים במקום פגישות פנימיות — ועסקים מבוססי פגישות שמנהלים את לוח הזמנים שלהם ב-Trafft יכולים להתחבר באותה דרך.

כל הנתיבים בדף זה הם יחסיים לכתובת ה-URL הבסיסית `https://api.dmchamp.com/v1`. כל בקשה דורשת את מפתח ה-API שלך — ראה [אימות](authentication.md) לרשימה המלאה של הדרכים לשליחתו. הדוגמאות להלן משתמשות בכותרת `X-API-Key`, כאשר דוגמת cURL אחת מציגה גם את טופס השאילתה `?apiKey=`.

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

---

## אובייקט הפגישה

כל נקודת קצה (endpoint) שמחזירה פגישה משתמשת באותו מבנה:

| שדה | תיאור |
|---|---|
| `id` | מזהה ייחודי של הפגישה. |
| `contact_id` | מזהה איש הקשר שעבורו נקבעה הפגישה. |
| `event_id` | מזהה סוג האירוע שעליו נקבעה הפגישה. |
| `status` | `Confirmed` או `Canceled`. |
| `start_time` | תחילת הפגישה, בפורמט ISO 8601 ב-UTC. |
| `end_time` | סיום הפגישה, בפורמט ISO 8601 ב-UTC. |
| `created_at` | מתי נוצרה הפגישה. |
| `last_modified_at` | מתי שונתה הפגישה לאחרונה. |
| `room_name` | חדר או משאב שבו נקבעה הפגישה, כאשר סוג האירוע משתמש בחדרים. |
| `description` | תיאור חופשי של הפגישה. |
| `summary` | סיכום קצר או כותרת. |
| `cancelation_reason` | סיבה שסופקה בעת ביטול הפגישה, אם קיימת. |
| `google_calendar_event_id` | מזהה אירוע Google Calendar המקושר. נקבע ברגע שסנכרון היומן מסתיים; `null` כאשר לא מחובר יומן או בזמן שהסנכרון עדיין בעיצומו. |
| `calendar_synced` | `true` ברגע שהפגישה מקושרת לאירוע יומן. |
| `imported` | `true` כאשר הפגישה יובאה מיומן חיצוני במקום להיקבע ישירות. |
| `is_recurring` | `true` כאשר הפגישה היא חלק מסדרה חוזרת. |
| `recurrence_frequency` | באיזו תדירות הפגישה חוזרת, כאשר היא חוזרת. |
| `recurring_event_id` | מזהה הסדרה החוזרת שאליה שייכת פגישה זו. |
| `recurring_interval` | מרווח בין חזרות, כאשר היא חוזרת. |
| `recurring_sequence` | מיקום פגישה זו בתוך הסדרה החוזרת שלה. |
| `end_after_x_occurrences` | מספר המופעים שלאחריהם הסדרה החוזרת מסתיימת. |
| `booking_provider` | מערכת המקור שממנה הגיעה ההזמנה, כאשר הוזמנה דרך ספק הזמנות מחובר. |

> **אודות סנכרון יומן:** מיד לאחר שאתה קובע או משנה פגישה, `google_calendar_event_id` עשוי עדיין להיות `null` ו-`calendar_synced` עשוי להיות `false` מכיוון שהסנכרון פועל ברקע רגע לאחר מכן. אחזר את הפגישה שוב זמן קצר לאחר מכן כדי לראות את שדות היומן המאוכלסים.

---

## מציאת משבצות פנויות

`GET /appointments/available-slots`

מחזיר את הזמנים הפנויים באמת עבור סוג אירוע מסוים בין שתי נקודות זמן. זוהי בדרך כלל הקריאה ה**ראשונה** בתהליך הזמנה: הצג משבצות אלו, תן לאדם לבחור אחת, ולאחר מכן שלח (post) את הזמן שנבחר אל [קביעת פגישה](#book-an-appointment).

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

| פרמטר שאילתה | נדרש | תיאור |
|---|---|---|
| `event_id` | כן | סוג האירוע לבדיקה. חייב להיות שייך לחשבון שלך. |
| `start_time` | כן | תחילת הטווח עבורו תרצה משבצות, בתבנית תאריך-שעה ISO 8601. |
| `end_time` | כן | סוף הטווח, בתבנית תאריך-שעה ISO 8601. כל יום הסיום כלול. |

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

| שדה | תיאור |
|---|---|
| `date` | היום שהקבוצה מכסה, כתוב כ-`DD/MM/YYYY`. |
| `day` | שם יום בשבוע באותיות קטנות, לדוגמה `monday`. |
| `room_name` | החדר או המשאב שאליו שייכת קבוצה זו, כאשר סוג האירוע משתמש בחדרים. |
| `available_slots` | המשבצות הניתנות להזמנה באותו יום, מהמוקדמת ביותר. |

לכל רשומה ב-`available_slots` יש:

| שדה | תיאור |
|---|---|
| `start_time` | תחילת המשבצת כ-`HH:mm`. |
| `end_time` | סוף המשבצת כ-`HH:mm`. |
| `available` | `true` — רק זמן פנוי מוחזר. |
| `spots_left` | כמה הזמנות עדיין נכנסות במשבצת זו. מופיע רק בסוגי אירועים המקבלים יותר מהזמנה אחת למשבצת. |

> **הזמנים הם מקומיים לסוג האירוע, לא לפי UTC.** `date`, `start_time`, ו-`end_time` הם ערכי שעון קיר באזור הזמן של סוג האירוע עצמו (ההגדרה העוקפת שלו, או אזור הזמן של החשבון שלך כשאין כזו). [קביעת פגישה](#book-an-appointment) מצפה לזמן UTC בתבנית ISO 8601, לכן המר את המשבצת שבחרת לפני שליחתה.

**cURL**

```bash
curl "https://api.dmchamp.com/v1/appointments/available-slots?event_id=event_xyz789&start_time=2026-06-15T00:00:00.000Z&end_time=2026-06-19T00:00:00.000Z" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const params = new URLSearchParams({
  event_id: "event_xyz789",
  start_time: "2026-06-15T00:00:00.000Z",
  end_time: "2026-06-19T00:00:00.000Z",
});
const res = await fetch(
  `https://api.dmchamp.com/v1/appointments/available-slots?${params}`,
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.data);
```

**Python**

```python
import requests

res = requests.get(
    "https://api.dmchamp.com/v1/appointments/available-slots",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={
        "event_id": "event_xyz789",
        "start_time": "2026-06-15T00:00:00.000Z",
        "end_time": "2026-06-19T00:00:00.000Z",
    },
)
print(res.json()["data"])
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "data": [
    {
      "date": "15/06/2026",
      "day": "monday",
      "room_name": "Room A",
      "available_slots": [
        { "start_time": "10:00", "end_time": "10:30", "available": true },
        { "start_time": "10:30", "end_time": "11:00", "available": true }
      ]
    },
    {
      "date": "16/06/2026",
      "day": "tuesday",
      "room_name": "Room A",
      "available_slots": [
        { "start_time": "09:00", "end_time": "09:30", "available": true, "spots_left": 2 }
      ]
    }
  ]
}
```

יום שאין בו זמן פנוי פשוט לא יופיע. חוסר ב-`event_id`, `start_time`, או `end_time` יחזיר `400`; סוג אירוע שאינו בחשבון שלך יחזיר `404`.

---

## קביעת פגישה

`POST /appointments`

קובע פגישה חדשה עבור איש קשר באחד מסוגי האירועים שלך. זמן הסיום מחושב אוטומטית ממשך המשבצת של סוג האירוע.

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

| שדה | נדרש | תיאור |
|---|---|---|
| `contact_id` | כן | מזהה איש הקשר שעבורו יש לקבוע. חייב להיות שייך לחשבונך. |
| `event_id` | כן | מזהה סוג האירוע שעליו יש לקבוע. חייב להיות שייך לחשבונך. |
| `start_time` | כן | התחלה רצויה כתאריך-שעה בפורמט ISO 8601. |
| `room_name` | לא | שם חדר או משאב, כאשר סוג האירוע משתמש בחדרים. |

**cURL** (באמצעות טופס השאילתה `?apiKey=`)

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": "contact_abc123",
    "event_id": "event_xyz789",
    "start_time": "2026-06-15T10:00:00.000Z",
    "room_name": "Room A"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.dmchamp.com/v1/appointments", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    contact_id: "contact_abc123",
    event_id: "event_xyz789",
    start_time: "2026-06-15T10:00:00.000Z",
    room_name: "Room A",
  }),
});
const data = await res.json();
console.log(data.appointment_id);
```

**Python**

```python
import requests

res = requests.post(
    "https://api.dmchamp.com/v1/appointments",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "contact_id": "contact_abc123",
        "event_id": "event_xyz789",
        "start_time": "2026-06-15T10:00:00.000Z",
        "room_name": "Room A",
    },
)
print(res.json()["appointment_id"])
```

**תגובה** (`201 Created`):

```json
{
  "success": true,
  "appointment_id": "aBcD1234eFgH5678",
  "appointment": {
    "id": "aBcD1234eFgH5678",
    "contact_id": "contact_abc123",
    "event_id": "event_xyz789",
    "status": "Confirmed",
    "start_time": "2026-06-15T10:00:00.000Z",
    "end_time": "2026-06-15T10:30:00.000Z",
    "created_at": "2026-06-10T09:00:00.000Z",
    "last_modified_at": "2026-06-10T09:00:00.000Z",
    "room_name": "Room A",
    "google_calendar_event_id": null,
    "calendar_synced": false
  }
}
```

---

## קבלת פגישה

`GET /appointments/{appointmentId}`

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

**cURL**

```bash
curl "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.appointment);
```

**Python**

```python
import requests

res = requests.get(
    "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["appointment"])
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "appointment": {
    "id": "aBcD1234eFgH5678",
    "contact_id": "contact_abc123",
    "event_id": "event_xyz789",
    "status": "Confirmed",
    "start_time": "2026-06-15T10:00:00.000Z",
    "end_time": "2026-06-15T10:30:00.000Z",
    "room_name": "Room A",
    "google_calendar_event_id": "abc123googleevent",
    "calendar_synced": true
  }
}
```

---

## רשימת פגישות

`GET /appointments`

מציג רשימת פגישות עבור החשבון שלך, מהחדשה לישנה, עם דפדוף מבוסס סמן (cursor-based pagination).

| פרמטר שאילתה | נדרש | תיאור |
|---|---|---|
| `contact_id` | לא | החזר רק פגישות עבור איש קשר זה. רשימות מסוננות לפי איש קשר כוללות **פגישות מאושרות בלבד** |
| `date` | לא | החזר רק פגישות ביום זה ביומן (`YYYY-MM-DD`). **דורש את `contact_id`.** |
| `status` | לא | סינון לפי `Confirmed` או `Canceled`. זמין רק **ללא** `contact_id`. |
| `limit` | לא | גודל דף, מספר שלם בין 1 ל-100. ברירת המחדל היא `50`. |
| `cursor` | לא | הערך `next_cursor` מתגובה קודמת. |

כמה כללים שכדאי לזכור:

- **ללא מסננים**, תקבל את כל הפגישות בחשבון, דף אחר דף.
- **לפי איש קשר** — הגדר את `contact_id` כדי לראות את הפגישות המאושרות של איש קשר אחד. ניתן לצמצם זאת ליום בודד על ידי העברת `date` גם כן.
- **לפי סטטוס** — הגדר את `status` (ללא `contact_id`) כדי להציג רק פגישות `Confirmed` או רק פגישות `Canceled` בכל החשבון.
- המסנן `date` ללא `contact_id`, או `status=Canceled` יחד עם `contact_id`, מחזיר `400`.

**cURL**

```bash
curl "https://api.dmchamp.com/v1/appointments?contact_id=contact_abc123&date=2026-06-15" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const params = new URLSearchParams({
  contact_id: "contact_abc123",
  date: "2026-06-15",
});
const res = await fetch(
  `https://api.dmchamp.com/v1/appointments?${params}`,
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.appointments, data.next_cursor);
```

**Python**

```python
import requests

res = requests.get(
    "https://api.dmchamp.com/v1/appointments",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"contact_id": "contact_abc123", "date": "2026-06-15"},
)
data = res.json()
print(data["appointments"], data["next_cursor"])
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "appointments": [
    {
      "id": "aBcD1234eFgH5678",
      "contact_id": "contact_abc123",
      "event_id": "event_xyz789",
      "status": "Confirmed",
      "start_time": "2026-06-15T10:00:00.000Z",
      "end_time": "2026-06-15T10:30:00.000Z",
      "calendar_synced": true
    }
  ],
  "next_cursor": null
}
```

כדי לדפדף בין התוצאות, העבר את ה-`next_cursor` מתגובה אחת בתור ה-`cursor` של הבקשה הבאה. המשך כך עד ש-`next_cursor` יהיה `null`. עיין ב-[שגיאות ודפדוף](errors-and-pagination.md) עבור תבנית הדפדוף המשותפת.

---

## עדכון פגישה

`PUT /appointments/{appointmentId}`

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

| שדה | תיאור |
|---|---|
| `start_time` | התחלה חדשה, תאריך-שעה בפורמט ISO 8601. |
| `end_time` | סיום חדש, תאריך-שעה בפורמט ISO 8601. חייב להיות לאחר זמן ההתחלה. |
| `room_name` | שם חדש של חדר או משאב. |
| `description` | תיאור חדש, או `null` כדי לנקות אותו. |
| `summary` | סיכום חדש, או `null` כדי לנקות אותו. |

**cURL**

```bash
curl -X PUT "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "start_time": "2026-06-16T10:00:00.000Z",
    "end_time": "2026-06-16T10:30:00.000Z"
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      start_time: "2026-06-16T10:00:00.000Z",
      end_time: "2026-06-16T10:30:00.000Z",
    }),
  }
);
const data = await res.json();
console.log(data.appointment);
```

**Python**

```python
import requests

res = requests.put(
    "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "start_time": "2026-06-16T10:00:00.000Z",
        "end_time": "2026-06-16T10:30:00.000Z",
    },
)
print(res.json()["appointment"])
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "appointment_id": "aBcD1234eFgH5678",
  "appointment": {
    "id": "aBcD1234eFgH5678",
    "contact_id": "contact_abc123",
    "event_id": "event_xyz789",
    "status": "Confirmed",
    "start_time": "2026-06-16T10:00:00.000Z",
    "end_time": "2026-06-16T10:30:00.000Z",
    "calendar_synced": true
  }
}
```

---

## ביטול פגישה

`POST /appointments/{appointmentId}/cancel`

מבטל פגישה מאושרת, עם אפשרות לתיעוד סיבה. הפגישה נשארת בחשבונך עם סטטוס `Canceled`, ואירוע היומן המקושר מוסר אוטומטית ברקע. ביטול פגישה שכבר בוטלה יחזיר `400`.

| שדה | נדרש | תיאור |
|---|---|---|
| `cancellation_reason` | לא | סיבה לביטול, נשמרת על גבי הפגישה. |

**cURL**

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678/cancel" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cancellation_reason": "Client asked to reschedule next month"
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678/cancel",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      cancellation_reason: "Client asked to reschedule next month",
    }),
  }
);
const data = await res.json();
console.log(data.success);
```

**Python**

```python
import requests

res = requests.post(
    "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678/cancel",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={"cancellation_reason": "Client asked to reschedule next month"},
)
print(res.json()["success"])
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "appointment_id": "aBcD1234eFgH5678"
}
```

---

## מחיקת פגישה

`DELETE /appointments/{appointmentId}`

מוחק לצמיתות פגישה ואת ההפניות אליה. אם ברצונך רק לבטל את ההזמנה תוך שמירה על התיעוד, השתמש ב-[ביטול](#cancel-an-appointment) במקום זאת.

**cURL**

```bash
curl -X DELETE "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
  { 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(
    "https://api.dmchamp.com/v1/appointments/aBcD1234eFgH5678",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["success"])
```

**תגובה** (`200 OK`):

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

---

## הצגת יומני Google המחוברים שלך

`GET /appointments/google-calendars`

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

זה עובד רק לאחר שהחשבון חיבר את Google Calendar (הגדרות ← אינטגרציות) עם הרשאת קריאה לפחות. אם לא, או אם הגישה שניתנה כבר לא כוללת את טווח הקריאה ליומן (calendar-read scope), תקבל `400` שינחה אותך לחבר (או לחבר מחדש) אותו.

**cURL**

```bash
curl "https://api.dmchamp.com/v1/appointments/google-calendars" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.dmchamp.com/v1/appointments/google-calendars", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.data);
```

**Python**

```python
import requests

res = requests.get(
    "https://api.dmchamp.com/v1/appointments/google-calendars",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["data"])
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "data": [
    {
      "id": "primary",
      "summary": "jane@example.com",
      "timeZone": "America/New_York",
      "accessRole": "owner",
      "primary": true
    },
    {
      "id": "abcdefg1234567890@group.calendar.google.com",
      "summary": "Bookings",
      "timeZone": "America/New_York",
      "accessRole": "writer"
    }
  ]
}
```

כל רשומה היא במבנה ה-[`CalendarListEntry`](https://developers.google.com/calendar/api/v3/reference/calendarList) של גוגל עצמה, לכן שמות השדות עוקבים אחר ה-`camelCase` של גוגל, ולא אחר ה-`snake_case` הרגיל של ה-API הזה — מדובר בנתונים של גוגל שעוברים כפי שהם, ולא שלנו. חיבור חסר או מבוטל יחזיר `400` עם שגיאה שמסבירה שיש לחבר (או לחבר מחדש) את Google Calendar.

---

## ייבוא אירועים מיומן Google Calendar

`POST /appointments/import-calendar-events`

מושך את האירועים שכבר קיימים ביומן/יומני Google המחוברים לקמפיין או לסוכן AI והופך אותם לפגישות — שימושי בפעם הראשונה שאתה מחבר יומן שכבר מכיל הזמנות. זה עלול לקחת זמן (כל אירוע עובר תהליך חילוץ כדי להבין למי הוא מיועד), לכן זה לעולם לא רץ באופן מיידי (inline): הבקשה מכניסה לתור משימת רקע ומחזירה לך `job_id` לבדיקת סטטוס (polling).

| שדה | חובה | תיאור |
|---|---|---|
| `campaign_id` | אחד משניים אלו | הקמפיין שממנו יש לייבא את היומן/יומנים המחוברים. |
| `agent_id` | אחד משניים אלו | סוכן ה-AI שממנו יש לייבא את היומן/יומנים המחוברים. |
| `identifier` | כן | `"EMAIL"` או `"PHONE_NUMBER"` — איזה פרט איש קשר לחלץ מכל אירוע ביומן כדי להתאים או ליצור את איש הקשר שאליו הוא שייך. |

שלח בדיוק אחד מבין `campaign_id` / `agent_id`, לעולם לא את שניהם ולעולם לא אף אחד מהם — כל שילוב אחר יחזיר `400`. כל אחד מהם שתשלח חייב להיות שייך לחשבון שלך, אחרת תקבל `404`.

**cURL**

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/import-calendar-events?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agent_abc123",
    "identifier": "EMAIL"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.dmchamp.com/v1/appointments/import-calendar-events", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    agent_id: "agent_abc123",
    identifier: "EMAIL",
  }),
});
const data = await res.json();
console.log(data.job_id);
```

**Python**

```python
import requests

res = requests.post(
    "https://api.dmchamp.com/v1/appointments/import-calendar-events",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={"agent_id": "agent_abc123", "identifier": "EMAIL"},
)
print(res.json()["job_id"])
```

**תגובה** (`202 Accepted`):

```json
{
  "success": true,
  "job_id": "jK9mQ2xR7pL4wN1t",
  "status": "queued",
  "campaign_id": null,
  "agent_id": "agent_abc123"
}
```

`campaign_id` ו-`agent_id` מחזירים את הערך ששלחת; השני תמיד יהיה `null`.

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

`GET /appointments/import-calendar-events/{jobId}`

```bash
curl "https://api.dmchamp.com/v1/appointments/import-calendar-events/jK9mQ2xR7pL4wN1t" \
  -H "X-API-Key: YOUR_API_KEY"
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "job_id": "jK9mQ2xR7pL4wN1t",
  "status": "completed",
  "message": "Imported 12 events as appointments.",
  "error": null
}
```

| `status` | משמעות |
|---|---|
| `queued` | טרם נאסף. המשך לבדוק. |
| `processing` | הייבוא מתבצע. המשך לבדוק. |
| `completed` | הושלם — `message` מכיל סיכום קצר וקריא. |
| `failed` | משהו השתבש — `error` מכיל את הסיבה. |

`GET` על `jobId` שלא קיים (או ששייך לחשבון אחר) יחזיר `404`.

---

<a id="restaurant-booking-integrations-zenchef-formitable"></a>

## אינטגרציות הזמנה חיצוניות (Zenchef / Formitable / OpenTable / TheFork / Trafft)

Zenchef ו-Formitable הן מערכות להזמנת מקומות במסעדות שדרכן סוכן ה-AI שלך יכול להזמין שולחנות אמיתיים; [Trafft](#trafft) היא פלטפורמת תזמון לעסקים מבוססי פגישות, המחוברת פעם אחת לכל חשבון ולא לכל מסעדה. לשתי פלטפורמות המסעדות יש **ווידג'ט הזמנות ציבורי ללא אימות** (`https://api.dmchamp.com/v1/zenchef-widget/...` ו-`https://api.dmchamp.com/v1/formitable-widget/...`) שמוצג בתוך הצ'אט עבור הסועד — נתיבי הווידג'ט הללו הם דפי HTML פשוטים שנועדו להיפתח בדפדפן, ולא נקודות קצה של JSON API, לכן הם אינם מתועדים כאן. להלן נקודות הקצה לניהול חשבון: אימות שמזהה מסעדה שייך לבעל החשבון, ולאחר מכן הוספה, עדכון או הסרה שלו.

### Zenchef

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

**שלב 1 — בדיקת קיום מזהה מסעדה**

`POST /appointments/zenchef-restaurants/check`

| שדה | נדרש | תיאור |
|---|---|---|
| `restaurant_id` | כן | מזהה המסעדה ב-Zenchef לבדיקה. |

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/zenchef-restaurants/check?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "12345" }'
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "data": { "exists": true, "requiresNameVerification": true }
}
```

`exists: false` פירושו שאף מסעדת Zenchef אינה מחזיקה במזהה זה — אין מה לעשות מעבר לכך. מוגבל ל-10 בדיקות לכל 5 דקות לכל חשבון; חריגה מכך תחזיר `429`.

**שלב 2 — אימות שם המסעדה**

`POST /appointments/zenchef-restaurants/verify-name`

| שדה | נדרש | תיאור |
|---|---|---|
| `restaurant_id` | כן | מזהה המסעדה ב-Zenchef משלב 1. |
| `user_input_name` | כן | השם שבעל החשבון הקליד — מושווה מול השם האמיתי של המסעדה ב-Zenchef (ללא רגישות לאותיות גדולות/קטנות או רווחים). |

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/zenchef-restaurants/verify-name?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "12345", "user_input_name": "The Blue Door Bistro" }'
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "data": {
    "verified": true,
    "restaurantDetails": {
      "id": "12345",
      "name": "The Blue Door Bistro",
      "address": "1 Rue de Rivoli, Paris",
      "status": "active"
    }
  }
}
```

`verified: false` פירושו שהשם לא תאם — `restaurantDetails` מושמט, בקש מבעל החשבון לנסות שוב. מוגבל ל-3 ניסיונות לכל 5 דקות (מחמיר יותר מבדיקת הקיום, כיוון שזהו שלב ההוכחה בפועל). `restaurant_id` שכבר לא קיים ב-Zenchef יחזיר `404`.

**שלב 3 — שמירת המסעדה**

`POST /appointments/zenchef-restaurants`

| שדה | נדרש | תיאור |
|---|---|---|
| `restaurant_id` | כן | 1–64 תווים, אותיות/מספרים/קו תחתון/מקף. |
| `restaurant_name` | כן | שם המסעדה המאומת משלב 2. |

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/zenchef-restaurants?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "12345", "restaurant_name": "The Blue Door Bistro" }'
```

**תגובה** (`201 Created`):

```json
{ "success": true, "data": { "restaurantId": "12345" } }
```

**עדכון מסעדת Zenchef שמורה**

`PUT /appointments/zenchef-restaurants/{restaurantId}`

| שדה | נדרש | תיאור |
|---|---|---|
| `restaurant_name` | לא | שם תצוגה חדש. |
| `is_active` | לא | הגדר את `false` כדי למנוע מהבוט לבצע הזמנות מול מסעדה זו מבלי להסיר אותה. |

```bash
curl -X PUT "https://api.dmchamp.com/v1/appointments/zenchef-restaurants/12345" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'
```

**תגובה** (`200 OK`): בעלת מבנה זהה לתגובת השמירה לעיל.

**הסרת מסעדת Zenchef**

`DELETE /appointments/zenchef-restaurants/{restaurantId}`

```bash
curl -X DELETE "https://api.dmchamp.com/v1/appointments/zenchef-restaurants/12345" \
  -H "X-API-Key: YOUR_API_KEY"
```

**תגובה** (`200 OK`): `{ "success": true, "data": { "restaurantId": "12345" } }`

`restaurantId` שאינו נמצא כרגע בחשבון יחזיר `404` בעת עדכון או מחיקה.

### Formitable

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

**אימות מזהה מסעדה**

`POST /appointments/formitable-restaurants/verify`

| שדה | נדרש | תיאור |
|---|---|---|
| `restaurant_id` | כן | מזהה המסעדה ב-Formitable. |
| `language` | לא | תג שפה עבור בקשת הבדיקה. ברירת המחדל היא `"nl"`. |

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/formitable-restaurants/verify?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "the-blue-door", "language": "en" }'
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "data": {
    "verified": true,
    "restaurantDetails": {
      "restaurantId": "the-blue-door",
      "productCount": 4,
      "sampleProductTitle": "Dinner for two",
      "language": "en"
    }
  }
}
```

עבור `restaurant_id` ש-Formitable אינה מזהה, תוחזר שגיאת `404`. מוגבל ל-10 ניסיונות לכל 5 דקות לכל חשבון.

**קבלת פרטי מסעדה**

`GET /appointments/formitable-restaurants/{restaurantId}/details?language=en`

שולף את הפרופיל הציבורי של המסעדה מ-Formitable, כולל אתר האינטרנט שלה — משמש לשמירה במטמון של כתובת האתר בזמן הגדרת המסעדה. `language` הוא פרמטר שאילתה אופציונלי, שברירת המחדל שלו היא `"en"`.

```bash
curl "https://api.dmchamp.com/v1/appointments/formitable-restaurants/the-blue-door/details?language=en" \
  -H "X-API-Key: YOUR_API_KEY"
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "data": {
    "uid": "the-blue-door",
    "name": "The Blue Door Bistro",
    "website": "https://thebluedoorbistro.com",
    "email": "info@thebluedoorbistro.com",
    "telephone": "+31201234567",
    "streetAddress": "Prinsengracht 1",
    "zipcode": "1015 AB",
    "city": "Amsterdam",
    "country": "Netherlands",
    "countryCode": "NL",
    "currency": "EUR"
  }
}
```

**שמור את המסעדה**

`POST /appointments/formitable-restaurants`

| שדה | חובה | תיאור |
|---|---|---|
| `restaurant_id` | כן | 1–64 תווים, אותיות/מספרים/קו תחתון/מקף. |
| `restaurant_name` | כן | שם תצוגה. |
| `language` | כן | תג שפה בתקן ISO, למשל `"en"` או `"en-GB"`. |
| `website_url` | לא | אתר האינטרנט של המסעדה, מתוך בדיקת הפרטים לעיל. חייב להיות `http(s)://`. |

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/formitable-restaurants?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "restaurant_id": "the-blue-door",
    "restaurant_name": "The Blue Door Bistro",
    "language": "en",
    "website_url": "https://thebluedoorbistro.com"
  }'
```

**תגובה** (`201 Created`): `{ "success": true, "data": { "restaurantId": "the-blue-door" } }`

**עדכן מסעדת Formitable שמורה**

`PUT /appointments/formitable-restaurants/{restaurantId}`

| שדה | חובה | תיאור |
|---|---|---|
| `restaurant_name` | לא | שם תצוגה חדש. |
| `language` | לא | תג שפה חדש בתקן ISO. |
| `is_active` | לא | הגדר את `false` כדי למנוע מהבוט לבצע הזמנות עבור מסעדה זו מבלי להסיר אותה. |
| `website_url` | לא | כתובת אתר חדשה. |

```bash
curl -X PUT "https://api.dmchamp.com/v1/appointments/formitable-restaurants/the-blue-door" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'
```

**תגובה** (`200 OK`): בעלת מבנה זהה לתגובת השמירה לעיל.

**הסר מסעדת Formitable**

`DELETE /appointments/formitable-restaurants/{restaurantId}`

```bash
curl -X DELETE "https://api.dmchamp.com/v1/appointments/formitable-restaurants/the-blue-door" \
  -H "X-API-Key: YOUR_API_KEY"
```

**תגובה** (`200 OK`): `{ "success": true, "data": { "restaurantId": "the-blue-door" } }`

`restaurantId` שאינו נמצא כרגע בחשבון יחזיר `404` בעת עדכון או מחיקה.

### OpenTable

אל מסעדות OpenTable מגיעים דרך אישורי השותף של OpenTable בפלטפורמה, ו-OpenTable מאפשרת לאישורים אלו לראות רק מסעדות שחיברו את הרישום של הפלטפורמה בתוך ה-Integrations Marketplace של OpenTable. לכן, בדומה ל-Formitable, קריאת אימות אחת מספיקה: מזהה מסעדה (Restaurant ID) נגיש (המספר "RID") מוכיח גם שהמסעדה קיימת וגם שהיא חיברה את האינטגרציה. עד שרישום השותף של OpenTable יופעל בפלטפורמה, קריאת האימות תחזיר `503`.

**אימות מסעדת OpenTable**

`POST /appointments/opentable-restaurants/verify`

| שדה | נדרש | תיאור |
| --- | --- | --- |
| `restaurant_id` | כן | מזהה מסעדת OpenTable (RID), מספר כגון `1038007`. |

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/opentable-restaurants/verify?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "1038007" }'
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "data": {
    "verified": true,
    "restaurantDetails": {
      "restaurantId": "1038007",
      "diningAreaCount": 2,
      "diningAreaNames": ["Main Room", "Garden"],
      "tableTypes": ["default", "outdoor", "bar"]
    }
  }
}
```

`verified: false` פירושו שאף מסעדת OpenTable אינה מחזיקה במזהה זה. `403` פירושו שהמסעדה קיימת אך טרם חיברה את האינטגרציה של הפלטפורמה בתוך OpenTable. מוגבל ל-10 ניסיונות לכל 5 דקות לכל חשבון.

**הוספת מסעדת OpenTable**

`POST /appointments/opentable-restaurants`

| שדה | נדרש | תיאור |
| --- | --- | --- |
| `restaurant_id` | כן | מזהה המסעדה המאומת. |
| `restaurant_name` | כן | שם תצוגה (תווית; זהו גם השם שבו ה-AI משתמש כדי לקרוא למסעדה). |
| `website_url` | לא | כתובת http(s) המוצגת לאורחים כאשר ה-AI מעביר אותם למסעדה. |

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/opentable-restaurants?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "1038007", "restaurant_name": "The Blue Door", "website_url": "https://thebluedoor.example" }'
```

**תגובה** (`201 Created`): `{ "success": true, "data": { "restaurantId": "1038007" } }`

**עדכון מסעדת OpenTable שמורה**

`PUT /appointments/opentable-restaurants/{restaurantId}`

שלח כל אחד מ-`restaurant_name`, `is_active` (השהיה עם `false`) או `website_url` (מחרוזת ריקה מנקה אותו); שדות שהושמטו נותרים ללא שינוי.

```bash
curl -X PUT "https://api.dmchamp.com/v1/appointments/opentable-restaurants/1038007" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'
```

**תגובה** (`200 OK`): `{ "success": true, "data": { "restaurantId": "1038007" } }`

**הסרת מסעדת OpenTable**

`DELETE /appointments/opentable-restaurants/{restaurantId}`

```bash
curl -X DELETE "https://api.dmchamp.com/v1/appointments/opentable-restaurants/1038007" \
  -H "X-API-Key: YOUR_API_KEY"
```

**תגובה** (`200 OK`): `{ "success": true, "data": { "restaurantId": "1038007" } }`

עבור `restaurantId` שאינו נמצא כרגע בחשבון, תוחזר השגיאה `404` בעת עדכון.

### TheFork

הגישה למסעדות TheFork מתבצעת באמצעות אישורי השותף של TheFork בפלטפורמה, ו-TheFork מאפשרת לאישורים אלו לראות רק מסעדות שהפעילו את השותף של הפלטפורמה בחשבון ה-TheFork שלהן. לכן, בדומה ל-Formitable ו-OpenTable, קריאת אימות אחת מספיקה: מזהה מסעדה (Restaurant ID) נגיש מוכיח גם שהמסעדה קיימת וגם שהשותף מופעל בה. המזהה הוא ה-UUID ש-TheFork מעניקה למסעדה ב-TheFork Manager, ונשלח כמחרוזת. עד ש-TheFork תאשר את הפלטפורמה כשותפה ותנפיק את האישורים, קריאת האימות תענה `503` — ראה [TheFork](../integrations/thefork.md) למה זה אומר כיום.

**אימות מסעדת TheFork**

`POST /appointments/thefork-restaurants/verify`

| שדה | נדרש | תיאור |
| --- | --- | --- |
| `restaurant_id` | כן | מזהה מסעדת TheFork, UUID כגון `9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60`. |

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/thefork-restaurants/verify?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" }'
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "data": {
    "verified": true,
    "restaurantDetails": {
      "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60",
      "partySizes": [1, 2, 3, 4, 5, 6, 7, 8]
    }
  }
}
```

`partySizes` הם גדלי הקבוצות שהמסעדה מקבלת באופן מקוון במהלך 30 הימים הקרובים. `404` או `403` פירושם ש-TheFork לא סיפקה לנו מסעדה עם המזהה הזה — או שהמזהה שגוי, או שהשותף של הפלטפורמה עדיין לא מופעל במסעדה זו; `400` פירושו שהמזהה אינו UUID. מוגבל ל-10 ניסיונות לכל 5 דקות לכל חשבון.

**הוספת מסעדת TheFork**

`POST /appointments/thefork-restaurants`

| שדה | נדרש | תיאור |
| --- | --- | --- |
| `restaurant_id` | כן | מזהה המסעדה המאומת (UUID). |
| `restaurant_name` | כן | שם תצוגה (תווית; זה גם השם שבו ה-AI קורא למסעדה). |
| `website_url` | לא | כתובת http(s) המוצגת לאורחים כאשר ה-AI מעביר אותם למסעדה. |

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/thefork-restaurants?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "restaurant_id": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60", "restaurant_name": "The Blue Door", "website_url": "https://thebluedoor.example" }'
```

**תגובה** (`201 Created`): `{ "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }`

**עדכון מסעדת TheFork שמורה**

`PUT /appointments/thefork-restaurants/{restaurantId}`

שלח כל אחד מ-`restaurant_name`, `is_active` (השהיה עם `false`) או `website_url` (מחרוזת ריקה מנקה אותו); שדות שהושמטו נותרים ללא שינוי.

```bash
curl -X PUT "https://api.dmchamp.com/v1/appointments/thefork-restaurants/9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'
```

**תגובה** (`200 OK`): `{ "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }`

**הסרת מסעדת TheFork**

`DELETE /appointments/thefork-restaurants/{restaurantId}`

```bash
curl -X DELETE "https://api.dmchamp.com/v1/appointments/thefork-restaurants/9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" \
  -H "X-API-Key: YOUR_API_KEY"
```

**תגובה** (`200 OK`): `{ "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }`

`restaurantId` שאינו נמצא כרגע בחשבון יחזיר `404` בעת עדכון או מחיקה.

### Trafft

Trafft מחובר פעם אחת עבור כל החשבון, לא לכל מיקום: כתובת חברה אחת בתוספת אישורי ה-API מלוח הבקרה של מנהל Trafft (**Features & Integrations → API & Connectors**, חלק מהתוכנית העסקית של Trafft). קריאת החיבור בודקת את האישורים הללו מול Trafft לפני אחסון כל דבר, כך שכתובת שגויה, אישורים שגויים או תוכנית ללא גישת API ייכשלו כאן ולא במהלך שיחה עם לקוח. ה-client secret מאוחסן בצורה מוצפנת ולעולם אינו מוחזר על ידי אף נקודת קצה.

כל שלוש קריאות הכתיבה (`POST`, `PUT`, `DELETE`) דורשות הרשאת **עריכה** (edit) של אינטגרציות; הסטטוס `GET` דורש הרשאת **צפייה** (view) של אינטגרציות.

**חיבור Trafft**

`POST /appointments/trafft/connect`

| שדה | נדרש | תיאור |
|---|---|---|
| `subdomain` | כן | כתובת החברה — החלק שלפני `.admin.trafft.com` בכתובת ה-URL שדרכה אתה מתחבר, למשל `acme`. כתובת מלאה מתקבלת ומצומצמת לאותו ערך. |
| `client_id` | כן | מזהה לקוח (Client ID) מדף ה-API & Connectors של Trafft. |
| `client_secret` | כן | סוד לקוח (Client Secret) מאותו דף. מאוחסן בצורה מוצפנת, לעולם אינו מוחזר. |
| `company_name` | לא | תווית עבור הרשימה שלך. |

```bash
curl -X POST "https://api.dmchamp.com/v1/appointments/trafft/connect?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subdomain": "acme",
    "client_id": "YOUR_TRAFFT_CLIENT_ID",
    "client_secret": "YOUR_TRAFFT_CLIENT_SECRET",
    "company_name": "Acme Salon"
  }'
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "data": {
    "subdomain": "acme",
    "service_count": 12,
    "employee_count": 4,
    "location_count": 2
  }
}
```

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

**קבלת סטטוס החיבור**

`GET /appointments/trafft`

```bash
curl "https://api.dmchamp.com/v1/appointments/trafft" \
  -H "X-API-Key: YOUR_API_KEY"
```

**תגובה** (`200 OK`):

```json
{
  "success": true,
  "data": {
    "connected": true,
    "subdomain": "acme",
    "hostname": "acme.admin.trafft.com",
    "client_id": "YOUR_TRAFFT_CLIENT_ID",
    "company_name": "Acme Salon",
    "is_active": true,
    "service_count": 12,
    "employee_count": 4,
    "location_count": 2
  }
}
```

`connected: false` אומר ששום דבר עדיין לא הוגדר. ה-client secret לעולם אינו נכלל בתגובה זו.

**עדכון החיבור**

`PUT /appointments/trafft`

| שדה | נדרש | תיאור |
|---|---|---|
| `is_active` | לא | הגדר את `false` כדי להשהות — ה-AI מפסיק לבצע הזמנות ב-Trafft, אך החיבור נשאר. `true` מחדש אותו. |
| `company_name` | לא | תווית חדשה. |

```bash
curl -X PUT "https://api.dmchamp.com/v1/appointments/trafft" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'
```

**תגובה** (`200 OK`): אותו אובייקט חיבור כמו ה-`GET` לעיל.

**ניתוק Trafft**

`DELETE /appointments/trafft`

```bash
curl -X DELETE "https://api.dmchamp.com/v1/appointments/trafft" \
  -H "X-API-Key: YOUR_API_KEY"
```

**תגובה** (`200 OK`): `{ "success": true }`

ניתוק מסיר רק את פרטי ההתחברות השמורים. פגישות שכבר נמצאות ב-Trafft נשארות ללא שינוי.

> **מבנה שגיאה בכל נקודות הקצה של Zenchef/Formitable/OpenTable/TheFork:** בניגוד לשאר דף זה, שגיאות כאן נושאות את הסטטוס שלהן פעמיים — פעם אחת כסטטוס HTTP ופעם אחת כ-`error_code` בגוף התגובה — לדוגמה `{ "success": false, "error": "Restaurant not found", "error_code": 404 }`. יש לטפל בכך באותו אופן כמו בכל שגיאה אחרת: בדוק את `success`, וקרא את `error` עבור ההודעה.

---

## שגיאות ב-API של פגישות

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

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

| סטטוס | מתי זה קורה בנקודת קצה של פגישה |
|---|---|
| `400` | שדה חובה חסר או לא תקין — לדוגמה, `start_time` שגוי, `end_time` שאינו אחרי `start_time`, שילוב מסננים לא תקין, אין שדות לעדכון, או פגישה שכבר בוטלה. |
| `404` | הפגישה, איש הקשר או סוג האירוע לא נמצאו. |
| `409` | משבצת הזמן המבוקשת כבר תפוסה (התנגשות בזימון). |

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

---

::: master-only
## השתמש בלקוח Google OAuth משלך (מסך הסכמה של יומן Google)

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

> **יומן Google בלבד.** אימות ה-OAuth של תיבת הדואר ב-Gmail עבור ערוץ האימייל אינו מושפע מכך.

### מה הלקוח שלך צריך קודם

1. **לקוח OAuth 2.0** מסוג יישום אינטרנט בפרויקט Google Cloud שלך, כאשר ה-**Google Calendar API** מופעל באותו פרויקט.
2. **כל רשומה של `redirect_uris`** (המוחזרת על ידי נקודות הקצה להלן) שנוספה תחת ה-Authorized redirect URIs של הלקוח. הרשומה הראשונה היא הדומיין המאומת שלך `api.` כאשר יש לך כזה — Google מאמתת רק מותג שההפניה שלו מתבצעת לדומיין שבבעלותך — ולאחריו המארח הנייטרלי של הפלטפורמה כחלופה המשמשת עד אז.
3. **מסך ההסכמה** עם המותג שלך, הדומיין שלך תחת Authorized domains, ושני טווחי הגישה (Scopes) של היומן שהוצהרו (`scopes` בתגובה). עד שהאפליקציה תפורסם ותאומת על ידי Google, משתמשים יראו אזהרת אפליקציה לא מאומתת והלקוח יוגבל ל-100 משתמשים.

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

`PUT /account-config/google-oauth-client`

| שדה | נדרש | תיאור |
|---|---|---|
| `client_id` | כן | מזהה לקוח ה-OAuth 2.0, מסתיים ב-`.apps.googleusercontent.com`. |
| `client_secret` | כן | סוד הלקוח (Client secret). מאומת מול Google לפני שהוא נשמר, ולאחר מכן מוצפן. לעולם לא מוחזר על ידי אף נקודת קצה. |

```bash
curl -X PUT "https://api.dmchamp.com/v1/account-config/google-oauth-client?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "123456789012-abcdefghijklmnop.apps.googleusercontent.com",
    "client_secret": "GOCSPX-your-client-secret"
  }'
```

**תגובה**

```json
{
  "success": true,
  "configured": true,
  "client_id": "123456789012-abcdefghijklmnop.apps.googleusercontent.com",
  "redirect_uris": [
    "https://api.youragency.com/v1/auth-google-callback",
    "https://api.dmchamp.com/v1/auth-google-callback"
  ],
  "scopes": [
    "https://www.googleapis.com/auth/calendar.events",
    "https://www.googleapis.com/auth/calendar.readonly"
  ],
  "setup": ["…"]
}
```

סוד שגוי או מזהה לקוח לא ידוע יידחו עם `400` והסיבה של Google ב-`error`, ושום דבר לא יישמר.

### קריאה או הסרה שלה

`GET /account-config/google-oauth-client` מחזיר את אותו סיכום בכל עת — `configured: false` בתוספת ה-`redirect_uris` וה-`scopes` לפני שדבר מה נשמר, כך שתוכל להגדיר את הצד של Google תחילה. `DELETE /account-config/google-oauth-client` מסיר את הלקוח: חיבורים חדשים חוזרים ללקוח הפלטפורמה, ויומנים שחוברו דרך הלקוח שהוסר חייבים לעבור חיבור מחדש, מכיוון שרק הלקוח שהנפיק חיבור יכול לרענן אותו.

חברי צוות זקוקים להרשאת **Integrations: view** עבור `GET` ולהרשאת **Integrations: edit** עבור `PUT` / `DELETE`.
:::

---

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

- [אנשי קשר](contacts.md) — צור וחפש את אנשי הקשר עבורם אתה מבצע הזמנות.
- [הודעות ושיחות](messages.md) — שלח לאיש קשר אישור או תזכורת.
- [Webhooks](webhooks.md) — קבל התראות כאשר פגישות משתנות.
