> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kaisupport.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Şablon mesajı gönderme

> Kendi sisteminizden onaylı bir WhatsApp şablonu gönderin; konuşma yoksa Kai konuşmayı açar.

Bu rehber, CRM'inize veya yönetim panelinize bir "WhatsApp'tan gönder"
düğmesi ekler. Düğme, bir telefon numarasına onaylı bir şablon gönderir.
Numaranın Kai'de konuşması yoksa, gönderim konuşmayı açar.

WhatsApp serbest metni yalnızca müşterinin son mesajından sonraki 24 saat
içinde kabul eder. Bu pencerenin dışında ve ilk temasta, WhatsApp yalnızca
Meta'nın onayladığı bir şablonu kabul eder. Bu Meta'nın kuralıdır, Kai'nin
değil.

Bu rehberdeki anahtarın `messages:send` yetkisine ihtiyacı vardır. Bu yetki
`templates:read` ve `conversations:read` yetkilerini de kapsar.

## 1. Kanalı bulun

Kanal listesini bir kez okuyun ve WhatsApp kanalınızın kimliğini saklayın:

```bash theme={null}
curl https://kaisupport.com/api/v1/channels \
  -H "Authorization: Bearer $KAI_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "id": "7c1f4a80-...",
      "kind": "whatsapp_cloud",
      "external_id": "104857923341",
      "enabled": true,
      "supports_templates": true,
      "created_at": "2026-05-11T09:00:00.000Z"
    }
  ]
}
```

<Note>
  Çalışma alanında tek bir WhatsApp kanalı varsa, sonraki adımlarda
  `channel_id` alanını atlayabilirsiniz. Kai kanalı sizin için bulur.
</Note>

## 2. Şablonları ipuçlarıyla listeleyin

Kullanıcınız gönderim penceresini açtığında şablonları isteyin. Mesajı
gönderen ekip arkadaşının e-posta adresini ve müşteriyi de ekleyin:

```bash theme={null}
curl -G "https://kaisupport.com/api/v1/templates" \
  -H "Authorization: Bearer $KAI_API_KEY" \
  --data-urlencode "agent=baran@example.com" \
  --data-urlencode "phone=+905356328781" \
  --data-urlencode "contact_name=Gülsüm Bodur"
```

```json theme={null}
{
  "channel_id": "7c1f4a80-...",
  "agent": { "member_id": "2c9a0d51-...", "name": "Baran Demir", "email": "baran@example.com" },
  "contact": { "contact_id": "4f1d6f2a-...", "name": "Gülsüm Bodur" },
  "data": [
    {
      "name": "consultation_request_cant_be_reached_reschedule_tr",
      "language": "tr",
      "status": "approved",
      "header": "Derece Kampüsü · {{konu}}",
      "body": "Selamlar {{customer_name}} ben Derece Kampüsü'nden {{consultant_name}}, ön görüşme talep etmişsin ancak sana ulaşamadım.",
      "variables": ["header.konu", "customer_name", "consultant_name"],
      "variable_hints": [
        { "address": "header.konu", "key": "konu", "part": "header", "binding": "free", "value": null, "source": null },
        { "address": "customer_name", "key": "customer_name", "part": "body", "binding": "customer_name", "value": "Gülsüm Bodur", "source": "request" },
        { "address": "consultant_name", "key": "consultant_name", "part": "body", "binding": "agent_name", "value": "Baran Demir", "source": "member" }
      ],
      "sendable": true
    }
  ]
}
```

Yanıt yalnızca gönderebileceğiniz şablonları içerir. `variables` alanı, yer
tutucuları gönderiminizin dolduracağı sırayla adlandırır.

### Başlıklı şablonlar

Bir şablonun mesajın üstünde bir başlığı olabilir. WhatsApp başlığı ilk
satırda kalın gösterir. `header` alanı başlığı taşır; şablonun başlığı yoksa
`null` olur.

Başlığın kendi değişkenleri olabilir ve Kai bunları doldurur. WhatsApp,
başlığın ve mesajın değişkenlerini ayrı numaralar ve adlandırır; bu yüzden
başlıktaki `{{1}}` ile mesajdaki `{{1}}` iki ayrı değerdir.

Bu nedenle her değişkenin bir **adresi** vardır; gönderirken bu adı
kullanırsınız:

| Nerede | Yer tutucu | Adres |
| - | - | - |
| Mesaj | `{{customer_name}}` | `customer_name` |
| Başlık | `{{konu}}` | `header.konu` |

`variables` alanı bu adresleri, gönderimin dolduracağı sırayla listeler:
önce başlığın değişkenleri, sonra mesajın değişkenleri. Her ipucu ayrıca
`header` veya `body` olan bir `part` alanı taşır; alanlarınızı buna göre
gruplayabilirsiniz.

<Note>
  Kai, görsel, video veya belge başlığı olan bir şablonu gönderemez; çünkü o
  başlık bir değer değil bir dosya ister. Kai, bir düğmesinde değişken bağlantı
  olan şablonu da gönderemez. Bu şablonlar yanıtta yer almaz. Onları görmek
  için `status=all` ekleyin; orada `sendable` alanı `false` olur.
</Note>

### İpuçlarını kullanın

`variable_hints` içindeki her kayıt, bir alanı nasıl dolduracağınızı söyler:

* `null` olmayan bir `value`, Kai'nin kullanacağı değerdir. Alanınızı bu
  değerle önden doldurun. Kullanıcınız göndermeden önce bunu değiştirebilir.
* `null` olan bir `value`, Kai'nin bu değişkeni dolduramadığı anlamına gelir.
  Kullanıcınızdan bu değeri isteyin ve o yanıtlamadan göndermeyin.

`binding` alanı, değerin nereden geldiğini söyler. `agent_name`, `agent`
alanındaki ekip arkadaşının profilini okur. `customer_name` kişiyi okur.
`free`, her seferinde bir insanın yazdığı anlamına gelir. Çalışma alanı bir
bağlamayı **Ayarlar (Settings) → Kanallar (Channels)** altında yapılandırır.
Kimse yapılandırmadığında Kai bunu değişkenin adından tahmin eder; bu yüzden
`{{consultant_name}}` ve `{{customer_name}}` kurulum olmadan çalışır.

Hiçbir üyenin taşımadığı bir `agent` adresi, `"agent": null` ve boş ipuçları
döndürür. Boş bir alanı incelerken bu alanı okuyun.

<Note>
  Kai gönderim anında hiçbir değişkeni doldurmaz. Gönderim bütün değerleri
  ister. Mesaj çıkmadan önce kişinin okuduğu şey sizin formunuzdur; bu ekranın
  ardından Kai'nin eklediği bir değeri kimse onaylamamış olur.
</Note>

Kai, kanalın şablon kitaplığının bir kopyasını tutar. Şablon eklemek veya
değiştirmek için Meta'nın WhatsApp Manager'ını kullanın, sonra Kai'de
**Ayarlar (Settings) → Kanallar (Channels)** altında eşitleyin.

## 3. Şablonu gönderin

```bash theme={null}
curl -X POST https://kaisupport.com/api/v1/conversations/outbound \
  -H "Authorization: Bearer $KAI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: crm-reachout-8842" \
  -d '{
    "to": { "phone": "+905356328781" },
    "contact": { "name": "Gülsüm Bodur" },
    "template": {
      "name": "consultation_request_cant_be_reached_reschedule_tr",
      "language": "tr",
      "variables": {
        "header.konu": "Ön görüşme",
        "customer_name": "Gülsüm Bodur",
        "consultant_name": "Baran Demir"
      }
    },
    "assignee": "baran@example.com",
    "opt_in_confirmed": true
  }'
```

Değerleri formunuzdan gönderin; form, ipuçlarını veya kullanıcınızın yaptığı
değişiklikleri taşır. Her değişken zorunludur.

### Değerler için iki biçim

Değişkenlerini adlandıran bir şablon, yukarıdaki gibi bir nesne kabul eder.
Anahtarlar, 2. adımdaki adreslerdir. Kai değerleri şablonun sırasına koyar,
yani bu sırayı bilmeniz gerekmez.

Bütün değişkenlerini numaralayan bir şablon (`{{1}}`, `{{2}}`), 2. adımdaki
`variables` alanının sırasıyla bir dizi kabul eder. Başlığın değerleri önce
gelir:

```json theme={null}
"variables": ["Ön görüşme", "Gülsüm Bodur", "Baran Demir"]
```

Adlandırılmış bir şablon için de dizi çalışır. Ama o zaman değerleriniz
şablonun sırasını izler ve birisi bu sırayı Meta'nın WhatsApp Manager'ında
değiştirebilir. Yer değiştiren iki değer yine iki metindir, bu yüzden hiçbir
şey hata vermez ve müşteri yanlış ismi okur. Adlandırılmış bir şablon için
nesneyi kullanın.

Kai, şablonun taşımadığı bir değişken adını reddeder ve hatada o adı belirtir.
Yanlış yazılmış bir ad, atılacak bir değer değil, entegrasyonunuzdaki bir
hatadır. Sade bir ad her zaman mesajın değişkenidir: başlığın bir değişkenini
doldurmak için adın önüne `header.` yazmanız gerekir.

Tek çağrı her şeyi yapar. Kai numaranın konuşmasını bulur veya oluşturur.
Arkasındaki kişiyi bulur veya oluşturur. Şablonun başlığını ve gövdesini
kendi kopyasından doldurur ve gönderir. Sonra konuşmayı `assignee` alanındaki ekip arkadaşına
atar.

Her çağrıda `opt_in_confirmed` alanını `true` yapmanız gerekir. Bu, kişinin
sizden mesaj almayı kabul ettiğine dair sizin beyanınızdır. Kai bu beyanı
mesajın üzerinde saklar.

```json theme={null}
{
  "data": {
    "conversation": {
      "id": "9d2b1c44-...",
      "status": "human",
      "assigned_member_id": "2c9a0d51-...",
      "assigned_via": "api",
      "contact_id": "4f1d6f2a-..."
    },
    "existing_conversation": false,
    "message": {
      "external_id": "wamid.HBgL...",
      "text": "Derece Kampüsü · Ön görüşme\n\nSelamlar Gülsüm Bodur ben Derece Kampüsü'nden Baran Demir, ön görüşme talep etmişsin ancak sana ulaşamadım.",
      "delivery_status": "sent",
      "ts": "2026-08-11T11:02:07.000Z"
    }
  }
}
```

`existing_conversation` alanı `true` ise konuşma zaten vardı. Mesaj o
konuşmaya eklendi ve ikinci bir konuşma açılmadı.

Kişiyi `"to": { "contact_id": "..." }` ile de adlandırabilirsiniz. Kai o
zaman kişinin kayıtlı telefon numarasını kullanır. Telefonu olmayan bir kişi
`no_phone` hatası döndürür.

## 4. Güvenle yeniden deneyin

Bir gönderim para tutar ve bir insana ulaşır. Her mesaj niyeti için benzersiz
bir değerle `Idempotency-Key` başlığı gönderin.

* Aynı anahtarla bir çağrı zaten başarılı olduysa, Kai saklanan yanıtı
  döndürür ve tekrar göndermez.
* İlk çağrı başarısız olduysa, Kai anahtarı serbest bırakır. Yeniden
  denemeniz çalışır.
* İlk çağrı hâlâ çalışıyorsa, Kai 409 `idempotency_in_flight` hatası
  döndürür. Kısa bir süre sonra yeniden deneyin.
* Aynı anahtar farklı bir gövdeyle 422 `idempotency_mismatch` hatası
  döndürür. Yeni bir mesaj için yeni bir anahtar kullanın.

## 5. Yanıtı kimin karşılayacağına karar verin

Gönderimin kendisi konuşmayı kimin yöneteceğine karar vermez. Buna
`assignee` alanı karar verir.

* `assignee` ile konuşma o ekip arkadaşına ait olur. Kai atanmış bir
  konuşmada yanıt vermez. Müşterinin yanıtı, o ekip arkadaşının gelen
  kutusunda ve Element X odalarında bekler.
* `assignee` olmadan konuşma, kanalın yanıt politikasında kalır. Kanal
  otopilotta çalışıyorsa, müşteriye Kai yanıt verebilir.

Dönen yanıtı bir insanın karşılaması gerekiyorsa bir `assignee` adlandırın,
örneğin bir satış görüşmesinde. Yanıtı Kai karşılayabilirse alanı atlayın,
örneğin bir ödeme hatırlatmasında.

## Hatalar

| `error.type` | Anlamı |
| - | - |
| `template_missing` | Kanal bu şablonu içermiyor. Eşitleyin ve yeniden deneyin. |
| `template_unapproved` | Meta bu şablonu onaylamadı veya onayı kaldırdı. |
| `variables_missing` | Bir değişken boş veya eksik. İpucu taşıyanlar dahil, her değişken zorunludur. |
| `variables_unknown` | Değerler, bu şablonun taşımadığı bir değişkeni adlandırıyor. Başlığın değişkeni `header.` öneki ister. |
| `variables_not_named` | Değerler bir nesne, ama bu şablon değişkenlerini numaralıyor. Dizi gönderin. |
| `no_phone` | `to.contact_id` alanındaki kişinin telefon numarası yok. |
| `identity_conflict` | Numara, farklı bir kişinin konuşmasına ait. |
| `recipient_undeliverable` | WhatsApp, son 7 gün içinde bu numaraya son mesajı iletemedi. Bu süre dolana veya müşteri yazana kadar Kai tekrar göndermez. Müşteriyi arayın. |
| `send_failed` | WhatsApp gönderimi reddetti. Mesaj, Meta'nın gerekçesini içerir. |

Hata biçimi ve genel kodlar için
[Hata yönetimi](/tr/guides/errors) sayfasına bakın.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.