
# Randevular

Randevu API'si, kişileriniz için etkinlik türleriniz üzerinden randevu almanıza, ardından bunları getirmenize, listelemenize, güncellemenize, iptal etmenize veya silmenize olanak tanır. Ayrıca çoğu rezervasyon akışında ilk sorulan soruyu — hangi zamanların gerçekten boş olduğunu — yanıtlar ve takvim tarafını kapsar: bağlı Google Takvimlerinizi listeler ve halihazırda içinde bulunan etkinlikleri içe aktarır. Bir Google Takvim bağlantısı aktif olduğunda, eşleşen takvim etkinliği oluşturulur ve arka planda otomatik olarak senkronize tutulur. Kendi rezervasyon sistemleri için Zenchef, Formitable, OpenTable veya TheFork kullanan restoranlar da burada doğrulanabilir ve bağlanabilir; böylece Yapay Zeka Temsilcisi dahili randevular yerine gerçek masalar için rezervasyon yapar — programlarını Trafft üzerinde yürüten randevu işletmeleri de aynı şekilde bağlanabilir.

Bu sayfadaki tüm yollar `https://api.dmchamp.com/v1` temel URL'sine göredir. Her istek API anahtarınızı gerektirir — gönderme yollarının tam listesi için [Kimlik Doğrulama](authentication.md) bölümüne bakın. Aşağıdaki örnekler `X-API-Key` başlığını kullanır; bir cURL örneği ise `?apiKey=` sorgu biçimini de gösterir.

> **Etkinlikler ve randevular:** *Etkinlik türü*, rezerve edilebilir bir zaman dilimi tanımıdır (toplantı türü, süresi, odaları). *Randevu*, belirli bir kişi için bir etkinlik türünün rezerve edilmiş bir örneğidir. Bir kişiye ve etkinlik türüne referans vererek bir randevu alırsınız.

---

## Randevu nesnesi

Randevu döndüren her uç nokta aynı yapıyı kullanır:

| Alan | Açıklama |
|---|---|
| `id` | Randevunun benzersiz kimliği. |
| `contact_id` | Randevunun alındığı kişinin kimliği. |
| `event_id` | Randevunun alındığı etkinlik türünün kimliği. |
| `status` | `Confirmed` veya `Canceled`. |
| `start_time` | Randevunun başlangıcı, UTC cinsinden ISO 8601. |
| `end_time` | Randevunun bitişi, UTC cinsinden ISO 8601. |
| `created_at` | Randevunun oluşturulduğu zaman. |
| `last_modified_at` | Randevunun en son değiştirildiği zaman. |
| `room_name` | Etkinlik türü oda kullandığında, randevunun alındığı oda veya kaynak. |
| `description` | Randevunun serbest biçimli açıklaması. |
| `summary` | Kısa özet veya başlık. |
| `cancelation_reason` | Varsa, randevu iptal edildiğinde sağlanan neden. |
| `google_calendar_event_id` | Bağlantılı Google Takvim etkinliğinin kimliği. Takvim senkronizasyonu tamamlandığında ayarlanır; takvim bağlı olmadığında veya senkronizasyon devam ederken `null` değerini alır. |
| `calendar_synced` | Randevu bir takvim etkinliğine bağlandığında `true` değerini alır. |
| `imported` | Randevu doğrudan alınmak yerine harici bir takvimden içe aktarıldığında `true` değerini alır. |
| `is_recurring` | Randevu yinelenen bir serinin parçası olduğunda `true` değerini alır. |
| `recurrence_frequency` | Yinelenen randevuların ne sıklıkla tekrarlandığı. |
| `recurring_event_id` | Bu randevunun ait olduğu yinelenen serinin kimliği. |
| `recurring_interval` | Yinelenen randevularda tekrarlar arasındaki aralık. |
| `recurring_sequence` | Bu randevunun yinelenen serisi içindeki konumu. |
| `end_after_x_occurrences` | Yinelenen serinin sona erdiği oluşum sayısı. |
| `booking_provider` | Bağlı bir rezervasyon sağlayıcısı aracılığıyla alındığında, rezervasyonun geldiği kaynak sistem. |

> **Takvim senkronizasyonu hakkında:** Bir randevu aldıktan veya değiştirdikten hemen sonra, senkronizasyon arka planda bir an sonra gerçekleştiği için `google_calendar_event_id` hala `null` olabilir ve `calendar_synced` değeri `false` olabilir. Doldurulmuş takvim alanlarını görmek için kısa bir süre sonra randevuyu tekrar getirin.

---

## Müsait zaman dilimlerini bulma

`GET /appointments/available-slots`

İki zaman dilimi arasında bir etkinlik türü için gerçekten boş olan zamanları döndürür. Bu normalde bir rezervasyon akışındaki **ilk** çağrıdır: bu zaman dilimlerini gösterin, kişinin birini seçmesine izin verin, ardından seçilen zamanı [Randevu al](#book-an-appointment) kısmına gönderin.

Yanıt, etkinlik türünün kendi açılış saatlerini ve zaman dilimi uzunluğunu, odalarını, üzerinde halihazırda ayırttığınız randevuları ve bağlı Google Takvimlerinde engellenen her şeyi hesaba katar; bu nedenle buradan dönen bir zaman dilimi, rezerve edebileceğiniz bir zaman dilimidir.

| Sorgu parametresi | Gerekli | Açıklama |
|---|---|---|
| `event_id` | Evet | Kontrol edilecek etkinlik türü. Hesabınıza ait olmalıdır. |
| `start_time` | Evet | Zaman dilimleri için istediğiniz pencerenin başlangıcı, ISO 8601 tarih-saat formatı. |
| `end_time` | Evet | Pencerenin sonu, ISO 8601 tarih-saat formatı. Günün tamamı dahildir. |

Sonuçlar güne göre gruplandırılmış olarak gelir — ve etkinlik türü odaları kullandığında, oda başına ve gün başına bir grup olacak şekilde:

| Alan | Açıklama |
|---|---|
| `date` | Grubun kapsadığı gün, `DD/MM/YYYY` olarak yazılır. |
| `day` | Küçük harflerle hafta içi adı, örneğin `monday`. |
| `room_name` | Etkinlik türü odaları kullandığında, bu grubun ait olduğu oda veya kaynak. |
| `available_slots` | O gün için rezerve edilebilir bloklar, en erken olandan başlayarak. |

`available_slots` içindeki her giriş şunlara sahiptir:

| Alan | Açıklama |
|---|---|
| `start_time` | `HH:mm` olarak blok başlangıcı. |
| `end_time` | `HH:mm` olarak blok bitişi. |
| `available` | `true` — yalnızca boş zaman döndürülür. |
| `spots_left` | Bu bloğa hala kaç randevunun sığabileceği. Yalnızca zaman dilimi başına birden fazla randevu alan etkinlik türlerinde bulunur. |

> **Zamanlar UTC değil, etkinlik türüne göre yereldir.** `date`, `start_time` ve `end_time`, etkinlik türünün kendi saat dilimindeki (geçersiz kılınmışsa o, yoksa hesap saat diliminizdeki) duvar saati değerleridir. [Randevu al](#book-an-appointment) bir ISO 8601 UTC anı bekler, bu nedenle seçtiğiniz zaman dilimini göndermeden önce dönüştürün.

**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"])
```

**Yanıt** (`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 }
      ]
    }
  ]
}
```

Boş zamanı olmayan bir gün görünmez. Eksik `event_id`, `start_time` veya `end_time`, `400` döndürür; hesabınızda olmayan bir etkinlik türü `404` döndürür.

---

## Randevu al

`POST /appointments`

Etkinlik türlerinizden biri üzerinden bir kişi için yeni bir randevu alır. Bitiş zamanı, etkinlik türünün zaman dilimi süresinden otomatik olarak hesaplanır.

Rezervasyon çakışma kontrolüne tabidir: İstenen zaman dilimi, aynı etkinlik türündeki mevcut onaylanmış bir randevu ile çakışırsa, istek `409` hatasıyla başarısız olur ve hiçbir şey oluşturulmaz.

| Alan | Gerekli | Açıklama |
|---|---|---|
| `contact_id` | Evet | Randevu alınacak kişinin kimliği. Hesabınıza ait olmalıdır. |
| `event_id` | Evet | Randevu alınacak etkinlik türünün kimliği. Hesabınıza ait olmalıdır. |
| `start_time` | Evet | ISO 8601 tarih-saat formatında istenen başlangıç zamanı. |
| `room_name` | Hayır | Etkinlik türü oda kullandığında, oda veya kaynak adı. |

**cURL** (`?apiKey=` sorgu formunu kullanarak)

```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"])
```

**Yanıt** (`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
  }
}
```

---

## Randevu al

`GET /appointments/{appointmentId}`

Takvim senkronizasyon durumu dahil olmak üzere, kimliğine göre tek bir randevuyu döndürür.

**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"])
```

**Yanıt** (`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
  }
}
```

---

## Randevuları listele

`GET /appointments`

Hesabınızdaki randevuları, en yeniden başlayarak ve imleç tabanlı sayfalama ile listeler.

| Sorgu parametresi | Gerekli | Açıklama |
|---|---|---|
| `contact_id` | Hayır | Yalnızca bu kişi için olan randevuları döndürür. Kişi bazlı listelemeler **yalnızca onaylanmış randevuları** içerir. |
| `date` | Hayır | Yalnızca bu takvim günündeki (`YYYY-MM-DD`) randevuları döndürür. **`contact_id` gerektirir.** |
| `status` | Hayır | `Confirmed` veya `Canceled` ile filtreleyin. Yalnızca `contact_id` **olmadan** kullanılabilir. |
| `limit` | Hayır | Sayfa boyutu, 1 ile 100 arasında bir tam sayı. Varsayılan `50`. |
| `cursor` | Hayır | Önceki bir yanıttan gelen `next_cursor` değeri. |

Aklınızda bulundurmanız gereken birkaç kural:

- **Filtre olmadan**, hesaptaki her randevuyu sayfa sayfa alırsınız.
- **Kişiye göre** — bir kişinin onaylanmış randevularını görmek için `contact_id` değerini ayarlayın. Ayrıca `date` parametresini göndererek bunu tek bir günle sınırlandırabilirsiniz.
- **Duruma göre** — hesap genelinde yalnızca `Confirmed` veya yalnızca `Canceled` randevuları listelemek için `status` değerini ( `contact_id` olmadan) ayarlayın.
- `contact_id` olmadan `date` filtresi veya `contact_id` ile birlikte `status=Canceled`, bir `400` döndürür.

**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"])
```

**Yanıt** (`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
}
```

Sonuçlar arasında gezinmek için, bir yanıttan gelen `next_cursor` değerini bir sonraki isteğin `cursor` parametresi olarak gönderin. `next_cursor` değeri `null` olana kadar devam edin. Paylaşılan sayfalama düzeni için [Hatalar ve Sayfalama](errors-and-pagination.md) bölümüne bakın.

---

## Randevuyu güncelle

`PUT /appointments/{appointmentId}`

Bir randevuyu yeniden planlayın veya ayrıntılarını değiştirin. Yalnızca değiştirmek istediğiniz alanları gönderin; en az bir alan gereklidir. Birleşik başlangıç ve bitiş zamanları kronolojik sırada kalmalıdır (`end_time`, `start_time` değerinden sonra olmalıdır). Değişiklikler, bağlantılı takvim etkinliği ile otomatik olarak senkronize edilir.

| Alan | Açıklama |
|---|---|
| `start_time` | Yeni başlangıç, ISO 8601 tarih-saat formatı. |
| `end_time` | Yeni bitiş, ISO 8601 tarih-saat formatı. Başlangıç zamanından sonra olmalıdır. |
| `room_name` | Yeni oda veya kaynak adı. |
| `description` | Yeni açıklama veya temizlemek için `null`. |
| `summary` | Yeni özet veya temizlemek için `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"])
```

**Yanıt** (`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
  }
}
```

---

## Bir randevuyu iptal et

`POST /appointments/{appointmentId}/cancel`

Onaylanmış bir randevuyu, isteğe bağlı olarak bir neden belirterek iptal eder. Randevu, `Canceled` durumuyla hesabınızda kalır ve bağlantılı takvim etkinliği arka planda otomatik olarak kaldırılır. Zaten iptal edilmiş bir randevuyu iptal etmek `400` döndürür.

| Alan | Gerekli | Açıklama |
|---|---|---|
| `cancellation_reason` | Hayır | Randevuda saklanacak iptal nedeni. |

**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"])
```

**Yanıt** (`200 OK`):

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

---

## Bir randevuyu sil

`DELETE /appointments/{appointmentId}`

Bir randevuyu ve referanslarını kalıcı olarak siler. Eğer sadece kaydı tutarak rezervasyonu iptal etmek istiyorsanız, bunun yerine [iptal](#cancel-an-appointment) işlemini kullanın.

**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"])
```

**Yanıt** (`200 OK`):

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

---

## Bağlı Google Takvimlerinizi listeleme

`GET /appointments/google-calendars`

Doğrudan Google'dan, bu hesapta mevcut olan Google Takvimlerini döndürür — hesap sahibine aşağıdan hangi takvimin içe aktarılacağını seçmesi için bir seçici göstermek veya sadece bağlantının canlı olduğunu doğrulamak için kullanışlıdır.

Bu, yalnızca hesap Google Takvim'i (Ayarlar → Entegrasyonlar) en az okuma erişimiyle bağladığında çalışır. Eğer bağlanmadıysa veya verilen erişim artık takvim-okuma kapsamını içermiyorsa, onu (yeniden) bağlamanızı söyleyen bir `400` alırsınız.

**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"])
```

**Yanıt** (`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"
    }
  ]
}
```

Her girdi Google'ın kendi [`CalendarListEntry`](https://developers.google.com/calendar/api/v3/reference/calendarList) şeklindedir, bu nedenle alan adları bu API'nin olağan `snake_case` yapısını değil, Google'ın `camelCase` yapısını takip eder — bu, bizim verimiz değil, olduğu gibi aktarılan Google verisidir. Eksik veya iptal edilmiş bir bağlantı, Google Takvim'in (yeniden) bağlanması gerektiğini açıklayan bir hata ile `400` döndürür.

---

## Google Takvim'den etkinlikleri içe aktarma

`POST /appointments/import-calendar-events`

Bir kampanyanın veya Yapay Zeka Temsilcisinin bağlı Google Takvim(ler)inde halihazırda bulunan etkinlikleri çeker ve bunları randevulara dönüştürür — üzerinde zaten rezervasyonlar bulunan bir takvimi ilk kez bağladığınızda kullanışlıdır. Bu işlem biraz zaman alabilir (her etkinlik, kime ait olduğunu anlamak için ayıklama sürecinden geçer), bu nedenle asla satır içi çalışmaz: istek bir arka plan işini kuyruğa alır ve size sorgulamanız için bir `job_id` döndürür.

| Alan | Gerekli | Açıklama |
|---|---|---|
| `campaign_id` | Bu ikisinden biri | İçe aktarılacak bağlı takvim(ler)in ait olduğu kampanya. |
| `agent_id` | Bu ikisinden biri | İçe aktarılacak bağlı takvim(ler)in ait olduğu Yapay Zeka Temsilcisi. |
| `identifier` | Evet | `"EMAIL"` veya `"PHONE_NUMBER"` — her takvim etkinliğinden, ait olduğu kişiyi eşleştirmek veya oluşturmak için hangi iletişim bilgisinin çıkarılacağı. |

`campaign_id` / `agent_id` öğelerinden tam olarak birini gönderin, asla ikisini birden veya hiçbirini göndermeyin — her iki kombinasyon da bir `400` döndürür. Gönderdiğiniz öğe hesabınıza ait olmalıdır, aksi takdirde bir `404` alırsınız.

**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"])
```

**Yanıt** (`202 Accepted`):

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

`campaign_id` ve `agent_id`, gönderdiğiniz hangisiyse onu geri yansıtır; diğeri her zaman `null` olur.

### İçe aktarma işini sorgulama

`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"
```

**Yanıt** (`200 OK`):

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

| `status` | Anlamı |
|---|---|
| `queued` | Henüz alınmadı. Sorgulamaya devam edin. |
| `processing` | İçe aktarma çalışıyor. Sorgulamaya devam edin. |
| `completed` | Tamamlandı — `message` kısa ve insan tarafından okunabilir bir özet içerir. |
| `failed` | Bir şeyler ters gitti — `error` nedenini içerir. |

Var olmayan (veya başka bir hesaba ait olan) bir `jobId` üzerinde `GET` işlemi `404` döndürür.

---

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

## Harici rezervasyon entegrasyonları (Zenchef / Formitable / OpenTable / TheFork / Trafft)

Zenchef ve Formitable, yapay zeka temsilcinizin gerçek masalar ayırtabileceği restoran rezervasyon sistemleridir; [Trafft](#trafft) ise randevu işletmeleri için kullanılan bir planlama platformudur ve restoran başına değil, hesap başına bir kez bağlanır. İki restoran platformunun her birinin, yemek yiyen kişi için sohbet içinde görüntülenen **herkese açık, kimlik doğrulaması gerektirmeyen bir rezervasyon aracı** (`https://api.dmchamp.com/v1/zenchef-widget/...` ve `https://api.dmchamp.com/v1/formitable-widget/...`) vardır — bu araç rotaları, tarayıcıda açılması amaçlanan düz HTML sayfalarıdır, JSON API uç noktaları değildir, bu nedenle burada belgelenmemiştir. Aşağıdakiler hesap yönetimi uç noktalarıdır: bir restoran kimliğinin hesap sahibine ait olduğunu doğrulama ve ardından ekleme, güncelleme veya kaldırma işlemleri.

### Zenchef

Bir Zenchef restoranını bağlamak iki aşamalı bir doğrulama gerektirir; böylece hesap sahibi, bot ile bağlantı kurulmadan önce restoranı gerçekten kendisinin yönettiğini kanıtlar: önce kimliğin var olup olmadığını kontrol edin (ismi açıklamadan), ardından restoranın adını kendilerinin yazmasını isteyin ve eşleşip eşleşmediğini doğrulayın.

**1. Adım — Bir restoran kimliğinin var olup olmadığını kontrol etme**

`POST /appointments/zenchef-restaurants/check`

| Alan | Gerekli | Açıklama |
|---|---|---|
| `restaurant_id` | Evet | Kontrol edilecek Zenchef restoran kimliği. |

```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" }'
```

**Yanıt** (`200 OK`):

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

`exists: false`, o kimliğe sahip bir Zenchef restoranı olmadığını belirtir; yapılacak başka bir işlem yoktur. Hesap başına 5 dakikada 10 kontrol ile sınırlandırılmıştır; aşılması durumunda `429` döner.

**2. Adım — Restoranın adını doğrulama**

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

| Alan | Gerekli | Açıklama |
|---|---|---|
| `restaurant_id` | Evet | 1. adımdaki Zenchef restoran kimliği. |
| `user_input_name` | Evet | Hesap sahibinin yazdığı isim — Zenchef'teki gerçek restoran ismiyle karşılaştırılır (büyük/küçük harf ve boşluk duyarsızdır). |

```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" }'
```

**Yanıt** (`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`, ismin eşleşmediği anlamına gelir — `restaurantDetails` atlanır, hesap sahibinden tekrar denemesini isteyin. 5 dakikada 3 deneme ile sınırlandırılmıştır (bu gerçek kanıtlama adımı olduğu için varlık kontrolünden daha sıkıdır). Artık Zenchef'te çözümlenmeyen bir `restaurant_id`, `404` döndürür.

**3. Adım — Restoranı kaydetme**

`POST /appointments/zenchef-restaurants`

| Alan | Gerekli | Açıklama |
|---|---|---|
| `restaurant_id` | Evet | 1–64 karakter, harfler/sayılar/alt çizgi/tire. |
| `restaurant_name` | Evet | 2. adımdan gelen doğrulanmış restoran ismi. |

```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" }'
```

**Yanıt** (`201 Created`):

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

**Kayıtlı bir Zenchef restoranını güncelleme**

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

| Alan | Gerekli | Açıklama |
|---|---|---|
| `restaurant_name` | Hayır | Yeni görünen ad. |
| `is_active` | Hayır | Botun bu restoran için rezervasyon yapmasını, restoranı kaldırmadan durdurmak için `false` değerini ayarlayın. |

```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 }'
```

**Yanıt** (`200 OK`): yukarıdaki kaydetme yanıtı ile aynı biçimdedir.

**Bir Zenchef restoranını kaldırın**

`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"
```

**Yanıt** (`200 OK`): `{ "success": true, "data": { "restaurantId": "12345" } }`

Hesapta bulunmayan bir `restaurantId`, güncelleme veya silme işleminde `404` döndürür.

### Formitable

Formitable, Zenchef'in gerektirdiği iki aşamalı isim kanıtına ihtiyaç duymaz; restoran kimlikleri zaten işletme bazında kapsamlandırılmıştır, bu nedenle tek bir doğrulama çağrısı yeterlidir. Ayrıca, kurulum sırasında restoranın web sitesi URL'sini önbelleğe almak için kullanılan bir detay sorgulaması da mevcuttur.

**Bir restoran kimliğini doğrulayın**

`POST /appointments/formitable-restaurants/verify`

| Alan | Gerekli | Açıklama |
|---|---|---|
| `restaurant_id` | Evet | Formitable restoran kimliği. |
| `language` | Hayır | İnceleme isteği için dil etiketi. Varsayılan değer `"nl"`'dir. |

```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" }'
```

**Yanıt** (`200 OK`):

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

Formitable tarafından tanınmayan bir `restaurant_id`, `404` döndürür. Hesap başına 5 dakikada 10 deneme ile hız sınırlandırılmıştır.

**Restoran detaylarını alın**

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

Restoranın web sitesi dahil olmak üzere Formitable'daki herkese açık profilini getirir; restoran kurulumu sırasında web sitesi URL'sini önbelleğe almak için kullanılır. `language`, varsayılan değeri `"en"` olan isteğe bağlı bir sorgu parametresidir.

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

**Yanıt** (`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"
  }
}
```

**Restoranı kaydet**

`POST /appointments/formitable-restaurants`

| Alan | Zorunlu | Açıklama |
|---|---|---|
| `restaurant_id` | Evet | 1–64 karakter, harfler/sayılar/alt çizgi/tire. |
| `restaurant_name` | Evet | Görünen ad. |
| `language` | Evet | ISO dil etiketi, örn. `"en"` veya `"en-GB"`. |
| `website_url` | Hayır | Yukarıdaki detay sorgulamasından restoranın web sitesi. `http(s)://` olmalıdır. |

```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"
  }'
```

**Yanıt** (`201 Created`): `{ "success": true, "data": { "restaurantId": "the-blue-door" } }`

**Kaydedilmiş bir Formitable restoranını güncelle**

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

| Alan | Zorunlu | Açıklama |
|---|---|---|
| `restaurant_name` | Hayır | Yeni görünen ad. |
| `language` | Hayır | Yeni ISO dil etiketi. |
| `is_active` | Hayır | Botun bu restoranı kaldırmadan rezervasyon yapmasını durdurmak için `false` değerini ayarlayın. |
| `website_url` | Hayır | Yeni web sitesi URL'si. |

```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 }'
```

**Yanıt** (`200 OK`): yukarıdaki kaydetme yanıtı ile aynı biçimdedir.

**Bir Formitable restoranını kaldır**

`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"
```

**Yanıt** (`200 OK`): `{ "success": true, "data": { "restaurantId": "the-blue-door" } }`

Hesapta bulunmayan bir `restaurantId`, güncelleme veya silme işleminde `404` döndürür.

### OpenTable

OpenTable restoranlarına, platformun OpenTable iş ortağı kimlik bilgileri aracılığıyla ulaşılır ve OpenTable, bu kimlik bilgilerinin yalnızca OpenTable'ın Entegrasyon Pazaryeri içindeki platform listesini bağlayan restoranları görmesine izin verir. Dolayısıyla, Formitable'da olduğu gibi, tek bir doğrulama çağrısı yeterlidir: ulaşılabilir bir Restoran Kimliği (sayısal "RID"), hem restoranın var olduğunu hem de entegrasyonu bağladığını kanıtlar. OpenTable iş ortağı listesi platformda etkinleştirilene kadar, doğrulama çağrısı `503` yanıtını verir.

**Bir OpenTable restoranını doğrulayın**

`POST /appointments/opentable-restaurants/verify`

| Alan | Gerekli | Açıklama |
| --- | --- | --- |
| `restaurant_id` | Evet | OpenTable Restoran Kimliği (RID), `1038007` gibi bir sayı. |

```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" }'
```

**Yanıt** (`200 OK`):

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

`verified: false`, hiçbir OpenTable restoranının bu kimliğe sahip olmadığı anlamına gelir. `403`, restoranın var olduğu ancak platformun entegrasyonunu henüz OpenTable içinde bağlamadığı anlamına gelir. Hesap başına 5 dakikada 10 deneme ile hız sınırlandırılmıştır.

**Bir OpenTable restoranı ekleyin**

`POST /appointments/opentable-restaurants`

| Alan | Gerekli | Açıklama |
| --- | --- | --- |
| `restaurant_id` | Evet | Doğrulanmış Restoran Kimliği. |
| `restaurant_name` | Evet | Görünen ad (bir etiket; ayrıca yapay zekanın restorana hitap etme şekli). |
| `website_url` | Hayır | Yapay zeka konukları restorana yönlendirdiğinde onlara gösterilen bir http(s) URL'si. |

```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" }'
```

**Yanıt** (`201 Created`): `{ "success": true, "data": { "restaurantId": "1038007" } }`

**Kayıtlı bir OpenTable restoranını güncelleyin**

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

`restaurant_name`, `is_active` (`false` ile duraklatın) veya `website_url` (boş dize temizler) değerlerinden herhangi birini gönderin; atlanan alanlar değiştirilmeden bırakılır.

```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 }'
```

**Yanıt** (`200 OK`): `{ "success": true, "data": { "restaurantId": "1038007" } }`

**Bir OpenTable restoranını kaldırın**

`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"
```

**Yanıt** (`200 OK`): `{ "success": true, "data": { "restaurantId": "1038007" } }`

Şu anda hesapta olmayan bir `restaurantId`, güncelleme sırasında `404` döndürür.

### TheFork

TheFork restoranlarına, platformun TheFork iş ortağı kimlik bilgileri aracılığıyla ulaşılır ve TheFork, bu kimlik bilgilerinin yalnızca TheFork hesaplarında platformun iş ortağı özelliği etkinleştirilmiş restoranları görmesine izin verir. Bu nedenle, Formitable ve OpenTable'da olduğu gibi, tek bir doğrulama çağrısı yeterlidir: ulaşılabilir bir Restoran Kimliği, hem restoranın var olduğunu hem de iş ortağının üzerinde etkinleştirildiğini kanıtlar. Kimlik, TheFork'un TheFork Manager'da restorana verdiği ve dize olarak gönderilen UUID'dir. TheFork platformu iş ortağı olarak onaylayıp kimlik bilgilerini verene kadar, doğrulama çağrısı `503` yanıtını verir — bunun bugün ne anlama geldiği hakkında bilgi için [TheFork](../integrations/thefork.md) bölümüne bakın.

**Bir TheFork restoranını doğrulayın**

`POST /appointments/thefork-restaurants/verify`

| Alan | Gerekli | Açıklama |
| --- | --- | --- |
| `restaurant_id` | Evet | TheFork Restoran Kimliği, `9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60` gibi bir UUID. |

```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" }'
```

**Yanıt** (`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`, restoranın önümüzdeki 30 gün boyunca çevrimiçi olarak kabul ettiği grup boyutlarıdır. `404` veya `403`, TheFork'un bize o kimliğe sahip bir restoran vermeyeceği anlamına gelir — ya kimlik yanlıştır ya da platformun iş ortağı o restoranda henüz etkinleştirilmemiştir; `400` ise kimliğin bir UUID olmadığı anlamına gelir. Hesap başına 5 dakikada 10 deneme ile hız sınırlandırılmıştır.

**Bir TheFork restoranı ekleyin**

`POST /appointments/thefork-restaurants`

| Alan | Gerekli | Açıklama |
| --- | --- | --- |
| `restaurant_id` | Evet | Doğrulanmış Restoran Kimliği (UUID). |
| `restaurant_name` | Evet | Görünen ad (bir etiket; ayrıca yapay zekanın restorana hitap şekli). |
| `website_url` | Hayır | Yapay zeka konukları restorana yönlendirdiğinde onlara gösterilen bir http(s) URL'si. |

```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" }'
```

**Yanıt** (`201 Created`): `{ "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }`

**Kayıtlı bir TheFork restoranını güncelleyin**

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

`restaurant_name`, `is_active` (`false` ile duraklatın) veya `website_url` (boş dize temizler) değerlerinden herhangi birini gönderin; atlanan alanlar değiştirilmeden bırakılır.

```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 }'
```

**Yanıt** (`200 OK`): `{ "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }`

**Bir TheFork restoranını kaldırın**

`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"
```

**Yanıt** (`200 OK`): `{ "success": true, "data": { "restaurantId": "9f2a1c34-5b6d-4e7f-8a90-1b2c3d4e5f60" } }`

Hesapta bulunmayan bir `restaurantId`, güncelleme veya silme işleminde `404` döndürür.

### Trafft

Trafft, konum başına değil, tüm hesap için bir kez bağlanır: bir şirket adresi ve Trafft yönetici panelinden (**Features & Integrations → API & Connectors**, Trafft'ın Business planının bir parçası) alınan API kimlik bilgileri. Bağlantı çağrısı, herhangi bir şeyi depolamadan önce bu kimlik bilgilerini Trafft'a karşı kontrol eder, bu nedenle yanlış bir adres, yanlış kimlik bilgileri veya API erişimi olmayan bir plan, müşteri görüşmesi sırasında değil burada başarısız olur. İstemci gizli anahtarı (client secret) şifrelenmiş olarak saklanır ve hiçbir uç nokta tarafından geri döndürülmez.

Her üç yazma çağrısı da (`POST`, `PUT`, `DELETE`) Entegrasyonlar **düzenleme** izni gerektirir; `GET` durumu ise Entegrasyonlar **görüntüleme** izni gerektirir.

**Trafft'ı Bağla**

`POST /appointments/trafft/connect`

| Alan | Gerekli | Açıklama |
|---|---|---|
| `subdomain` | Evet | Şirket adresi — giriş yaptığınız URL'deki `.admin.trafft.com` kısmından önceki bölüm, örn. `acme`. Tam bir adres kabul edilir ve aynı değere indirgenir. |
| `client_id` | Evet | Trafft'ın API & Connectors sayfasından alınan İstemci Kimliği (Client ID). |
| `client_secret` | Evet | Aynı sayfadan alınan İstemci Gizli Anahtarı (Client Secret). Şifrelenmiş olarak saklanır, asla geri döndürülmez. |
| `company_name` | Hayır | Kendi listeniz için bir etiket. |

```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"
  }'
```

**Yanıt** (`200 OK`):

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

Sayılar, kontrol sırasında Trafft'tan geri döner — bunlar, kimlik bilgilerinin amaçladığınız hesabı işaret ettiğini doğrulamanın en hızlı yoludur.

**Bağlantı durumunu al**

`GET /appointments/trafft`

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

**Yanıt** (`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`, henüz hiçbir şeyin ayarlanmadığı anlamına gelir. İstemci gizli anahtarı bu yanıta asla dahil edilmez.

**Bağlantıyı güncelle**

`PUT /appointments/trafft`

| Alan | Gerekli | Açıklama |
|---|---|---|
| `is_active` | Hayır | Duraklatmak için `false` değerini ayarlayın — yapay zeka Trafft'a rezervasyon yapmayı durdurur, bağlantı kalır. `true` bunu devam ettirir. |
| `company_name` | Hayır | Yeni etiket. |

```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 }'
```

**Yanıt** (`200 OK`): yukarıdaki `GET` ile aynı bağlantı nesnesi.

**Trafft Bağlantısını Kes**

`DELETE /appointments/trafft`

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

**Yanıt** (`200 OK`): `{ "success": true }`

Bağlantıyı kesmek yalnızca depolanan kimlik bilgilerini kaldırır. Trafft'ta halihazırda bulunan randevulara dokunulmaz.

> **Tüm Zenchef/Formitable/OpenTable/TheFork uç noktalarındaki hata biçimi:** bu sayfanın geri kalanından farklı olarak, buradaki hatalar durumlarını iki kez taşır — bir kez HTTP durumu olarak ve bir kez de gövdede `error_code` olarak — örneğin `{ "success": false, "error": "Restaurant not found", "error_code": 404 }`. Bunu diğer tüm hatalarla aynı şekilde ele alın: `success` öğesini kontrol edin, mesaj için `error` öğesini okuyun.

---

## Randevular API hataları

Randevu uç noktaları standart hata zarfını döndürür:

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

| Durum | Bir randevu uç noktasında ne zaman gerçekleşir |
|---|---|
| `400` | Gerekli bir alan eksik veya geçersiz — örneğin hatalı bir `start_time`, `start_time` sonrasında olmayan bir `end_time`, geçersiz bir filtre kombinasyonu, güncellenecek alan olmaması veya halihazırda iptal edilmiş bir randevu. |
| `404` | Randevu, kişi veya etkinlik türü bulunamadı. |
| `409` | İstenen zaman dilimi zaten dolu (rezervasyon çakışması). |

Her uç noktanın döndürebileceği ortak kodlar — `401`, `403` (planınız API erişimini içermiyor), `429` (hız sınırı) ve `500` — yeniden deneme rehberliği ile birlikte [Hatalar ve Sayfalandırma](errors-and-pagination.md) bölümünde listelenmiştir.

---

::: master-only
## Kendi Google OAuth istemcinizi kullanın (Takvim onay ekranı)

Bir hesap Google Takvim'i bağladığında, Google'ın oturum açma penceresi OAuth istemcisinin projesini adlandırır; varsayılan olarak platformunkini kullanır. Bir ajans, ajans hesabında kendi Google OAuth 2.0 istemcisini kaydedebilir; o andan itibaren, o hesap ve altındaki her alt hesap için takvim bağlantısı bu istemci üzerinden çalışır, böylece onay ekranında ajansın adı ve logosu görünür. Başka hiçbir şey değişmez: bağlantı akışı, çift yönlü senkronizasyon ve yukarıdaki randevu uç noktaları eskisi gibi çalışmaya devam eder.

> **Yalnızca Google Takvim.** E-posta kanalı için Gmail posta kutusu OAuth'u bundan etkilenmez.

### Müşterinizin öncelikle nelere ihtiyacı var

1. Google Cloud projenizde Web uygulaması türünde **bir OAuth 2.0 istemcisi** ve bu projede **Google Calendar API** etkinleştirilmiş olmalıdır.
2. **Her `redirect_uris` girişi** (aşağıdaki uç noktalar tarafından döndürülen), istemcinin Yetkili yönlendirme URI'leri altına eklenmelidir. İlk giriş, sahip olduğunuzda doğrulanmış `api.` alan adınızdır — Google yalnızca yönlendirmesi sahip olduğunuz bir alan adında bulunan bir markayı doğrular — ardından o zamana kadar kullanılan yedek olarak platformun tarafsız ana bilgisayarı gelir.
3. Markanızın, Yetkili alan adları altında alan adınızın ve beyan edilen iki Takvim kapsamının (yanıtta `scopes`) bulunduğu **onay ekranı**. Uygulama yayınlanıp Google tarafından doğrulanana kadar, kullanıcılar doğrulanmamış uygulama uyarısı görür ve istemci 100 kullanıcı ile sınırlandırılır.

### İstemcinizi kaydedin

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

| Alan | Gerekli | Açıklama |
|---|---|---|
| `client_id` | Evet | `.apps.googleusercontent.com` ile biten OAuth 2.0 istemci kimliği. |
| `client_secret` | Evet | İstemci gizli anahtarı. Saklanmadan önce Google'da doğrulanır, ardından şifrelenir. Hiçbir uç nokta tarafından geri döndürülmez. |

```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"
  }'
```

**Yanıt**

```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": ["…"]
}
```

Yanlış bir gizli anahtar veya bilinmeyen bir istemci kimliği, `400` ve `error` içindeki Google'ın kendi nedeni ile reddedilir ve hiçbir şey saklanmaz.

### Oku veya kaldır

`GET /account-config/google-oauth-client` herhangi bir zamanda aynı özeti döndürür — `configured: false` artı herhangi bir şey kaydedilmeden önce `redirect_uris` ve `scopes`, böylece önce Google tarafını ayarlayabilirsiniz. `DELETE /account-config/google-oauth-client` istemciyi kaldırır: yeni bağlantılar platform istemcisine geri döner ve kaldırılan istemci aracılığıyla bağlanan takvimlerin yeniden bağlanması gerekir, çünkü yalnızca bağlantıyı oluşturan istemci onu yenileyebilir.

Ekip üyelerinin `GET` için **Entegrasyonlar: görüntüle** ve `PUT` / `DELETE` için **Entegrasyonlar: düzenle** yetkisine sahip olması gerekir.
:::

---

## Sonraki adımlar

- [Kişiler](contacts.md) — rezervasyon yaptığınız kişileri oluşturun ve arayın.
- [Mesajlar ve Konuşmalar](messages.md) — bir kişiye onay veya hatırlatıcı gönderin.
- [Web kancaları](webhooks.md) — randevular değiştiğinde bildirim alın.
