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

# Mesaj şablonları

> Mesaj şablonlarını, sistem şablon adlarını ve birleştirme etiketlerini API ile yönetmeyi anlatır.

Mesaj şablonları, Flextell'in hastalara kendiliğinden gönderdiği mesajların metnini belirler: randevu bildirimi, hatırlatma, form linki gibi. Her şablon bir olaya (`system_name`) bağlıdır ve metin içinde hasta adı, randevu tarihi gibi birleştirme etiketleri taşır. Ekran karşılığı için bkz. [Mesaj şablonları (panel)](/panel/iletisim/mesaj-sablonlari).

Her yeni klinik, 19 olayın tamamı için hazır şablonlarla açılır. Bu yüzden entegrasyonların çoğu yeni şablon oluşturmaz; mevcut şablonun metnini günceller.

## Endpoint özeti

Tüm istekler `Authorization: Bearer <access_token>` ve `X-Tenant: <tenant_id>` başlıklarını gerektirir (bkz. [Klinikler ve X-Tenant](/api/klinikler-ve-x-tenant)). Şablonlar kliniğe aittir; yalnızca kendi kliniğinizin şablonlarını görürsünüz.

| Metot | Endpoint | Açıklama | Scope | İzin |
| - | - | - | - | - |
| `GET` | `/api/v1/message-templates` | Şablonları listeler | `message_templates:read` | `View:MessageTemplate` |
| `GET` | `/api/v1/message-templates/merge-tags` | Olay başına kullanılabilir birleştirme etiketlerini döndürür | `message_templates:read` | `View:MessageTemplate` |
| `GET` | `/api/v1/message-templates/{id}` | Tek şablonu döndürür | `message_templates:read` | `View:MessageTemplate` |
| `POST` | `/api/v1/message-templates` | Şablon oluşturur (`201`) | `message_templates:write` | `Create:MessageTemplate` |
| `PUT` | `/api/v1/message-templates/{id}` | Şablonu günceller | `message_templates:write` | `Update:MessageTemplate` |
| `DELETE` | `/api/v1/message-templates/{id}` | Şablonu siler | `message_templates:write` | `Delete:MessageTemplate` |

Scope'lar için bkz. [Scope'lar](/api/kimlik-dogrulama/scopelar). İzin adları rol editöründe `Görüntüle`, `Oluştur`, `Güncelle`, `Sil` olarak görünür.

### Listeleme parametreleri

Sayfalama için bkz. [Sayfalama](/api/istekler/sayfalama), genel sıralama kuralları için [Filtreleme ve sıralama](/api/istekler/filtreleme-ve-siralama).

| Parametre | Tür | Açıklama |
| - | - | - |
| `search` | string, en çok 255 | `name` ve `subject` alanlarında arar. |
| `is_active` | boolean | Yalnızca etkin ya da pasif şablonları getirir. |
| `sort_by` | string | `name`, `system_name`, `is_active`, `created_at`, `updated_at`. Varsayılan `created_at`. |
| `sort_order` | string | `asc` veya `desc`. Varsayılan `desc`. |
| `per_page` | integer | 1 ile 100 arası. Varsayılan 15. |
| `page` | integer | Sayfa numarası. |

## Şablon nesnesi

| Alan | Tür | Açıklama |
| - | - | - |
| `id` | integer | Şablon kimliği. |
| `name` | string | Görünen ad. En çok 150 karakter. |
| `system_name` | string | Şablonun bağlı olduğu olay. [Sistem şablonları](#sistem-şablonları) tablosundaki 19 değerden biri. Oluşturulduktan sonra değişmez. |
| `subject` | string | Konu. Zorunlu, en çok 200 karakter. |
| `body` | string | Mesaj metni (HTML). Birleştirme etiketlerini içerir. |
| `is_active` | boolean | `false` ise şablon gönderimlerde kullanılmaz. |
| `created_at`, `updated_at`, `deleted_at` | string | Zaman damgaları. |

## Sistem şablonları

`system_name`, şablonun hangi olayda kullanılacağını söyler. Bir klinikte, silinmemiş şablonlar arasında her `system_name` yalnızca bir kez bulunabilir.

| `system_name` | Etiket |
| - | - |
| `appointment.created` | Randevu Oluşturma (WhatsApp) |
| `appointment.updated` | Randevu Güncelleme |
| `appointment.reminder.tomorrow` | Randevu Hatırlatma (Yarın) |
| `appointment.cancellation.followup` | İptal Sonrası Takip (30 Gün) |
| `reminder.offset.generic` | Randevu Hatırlatma (Offset) |
| `blacklist.blocked.generic` | Engel Bilgilendirme (Genel) |
| `blacklist.blocked.temporary` | Engel Bilgilendirme (Geçici) |
| `tenant.location.sent` | Konum Gönderildi |
| `media.ack` | Dosya Onay Mesajı |
| `session.confirmation.request` | Seans Onay Talebi |
| `reschedule.confirmation.request` | Randevu Taşıma Onay Talebi |
| `form.photo.reminder` | Form Fotoğrafları Eksik/Tamamlanmalı |
| `form.photo.success` | Form Fotoğrafları Tamamlandı |
| `customer.form.link` | Hasta Formu Linki |
| `ticket.resolved` | Destek Talebi Çözüldü |
| `sales.gatekeeping.success` | Satış Yönlendirme Onayı |
| `intake.welcome` | İlk Karşılama Mesajı (Ön Kayıt) |
| `support.handoff.human` | İnsana Devretme Mesajı |
| `data.erasure.verification` | Veri İmha Doğrulama |

<Note>
  Panel, `support.handoff.human` olayını **Flexy Kapatma Mesajı** adıyla gösterir ve `data.erasure.verification` olayını oluşturma listesinde sunmaz. API ise 19 olayın tamamını kabul eder.
</Note>

## Birleştirme etiketleri

Etiketler, mesaj gönderilirken gerçek değerle değiştirilir. Bir olay için hangi etiketlerin kullanılabileceğini `GET /api/v1/message-templates/merge-tags` döndürür. Liste kliniğe göre değişmez. `system_name` parametresiyle tek bir olaya daralabilirsiniz; parametre vermezseniz 19 olayın hepsi gelir.

Yanıtın `data` alanı şu biçimdedir:

```json theme={null}
[
  {
    "system_name": "appointment.reminder.tomorrow",
    "label": "Randevu Hatırlatma (Yarın)",
    "merge_tags": [
      { "id": "customerName", "label": "Hasta Adı" },
      { "id": "appointmentDate", "label": "Randevu Tarihi" }
    ]
  }
]
```

| Etiket (`id`) | Etiket adı | Değer |
| - | - | - |
| `customerName` | Hasta Adı | Hastanın adı soyadı |
| `tenantName` | Klinik Adı | Kliniğin adı |
| `appointmentDate` | Randevu Tarihi | `gg.aa.yyyy` |
| `appointmentTime` | Randevu Saati | `ss:dd` |
| `treatmentName` | Tedavi Adı | Birden fazla tedavi virgülle birleştirilir |
| `doctorName` | Doktor Adı | Randevudaki doktor |
| `sessionType` | Seans Tipi | Örneğin `Kontrol`, `İşlem`, `Konsültasyon`; varsayılan `Seans` |
| `session_order` | Seans Sırası | Seans numarası |
| `planned_date`, `planned_time` | Planlanan Tarih, Planlanan Saat | Planlanan sonraki seans |
| `oldDate`, `oldTime` | Eski Randevu Tarihi, Eski Randevu Saati | Taşımadan önceki zaman |
| `newDate`, `newTime` | Yeni Randevu Tarihi, Yeni Randevu Saati | Önerilen yeni zaman |
| `reasonText` | Engel Nedeni | Engel nedeni açıklaması |
| `mediaCount` | Dosya Sayısı | Alınan dosya veya fotoğraf sayısı |
| `requiredPhotoCount` | Gerekli Fotoğraf Sayısı | İstenen en az sayı |
| `remainingPhotoCount` | Kalan Fotoğraf Sayısı | Gerekli sayıdan alınanın farkı, en az 0 |
| `maxPhotoCount` | Maksimum Fotoğraf Sayısı | İstenen en çok sayı |
| `ticketCode` | Destek Talebi Kodu | Destek talebi kodu |
| `formName`, `formUrl` | Form Adı, Form Linki | Gönderilen form |
| `erasureUrl`, `erasureExpiresAt` | Veri İmha Onay Linki, Onay Linki Son Geçerlilik | Doğrulama linki ve son geçerlilik zamanı |

<Accordion title="Olay başına izin verilen etiketler">
  | `system_name` | Kullanılabilir etiketler |
  | - | - |
  | `appointment.created` | `customerName`, `tenantName`, `appointmentDate`, `appointmentTime`, `treatmentName`, `doctorName`, `session_order`, `sessionType` |
  | `appointment.updated` | `customerName`, `tenantName`, `appointmentDate`, `appointmentTime`, `treatmentName`, `doctorName`, `sessionType` |
  | `appointment.reminder.tomorrow` | `customerName`, `tenantName`, `appointmentDate`, `appointmentTime`, `treatmentName`, `sessionType` |
  | `reminder.offset.generic` | `customerName`, `tenantName`, `appointmentDate`, `appointmentTime`, `treatmentName`, `sessionType` |
  | `appointment.cancellation.followup` | `customerName`, `tenantName`, `treatmentName` |
  | `session.confirmation.request` | `customerName`, `tenantName`, `appointmentDate`, `appointmentTime`, `treatmentName`, `sessionType`, `session_order`, `planned_date`, `planned_time` |
  | `reschedule.confirmation.request` | `customerName`, `tenantName`, `oldDate`, `oldTime`, `newDate`, `newTime` |
  | `blacklist.blocked.generic` | `reasonText` |
  | `media.ack` | `mediaCount` |
  | `form.photo.reminder`, `form.photo.success` | `mediaCount`, `requiredPhotoCount`, `remainingPhotoCount`, `maxPhotoCount` |
  | `customer.form.link` | `formName`, `formUrl` |
  | `ticket.resolved` | `customerName`, `tenantName`, `ticketCode` |
  | `sales.gatekeeping.success` | `customerName`, `tenantName`, `requiredPhotoCount`, `maxPhotoCount` |
  | `intake.welcome`, `support.handoff.human` | `customerName`, `tenantName` |
  | `data.erasure.verification` | `tenantName`, `erasureUrl`, `erasureExpiresAt` |
  | `blacklist.blocked.temporary`, `tenant.location.sent` | Etiket yok |
</Accordion>

<Warning>
  Etiketi `body` içine düz metin olarak (`{{ customerName }}`) yazmayın; değiştirilmez. Etiket şu HTML öğesiyle eklenir: `<span data-type="mergeTag" data-id="customerName"></span>`.
</Warning>

Etiket kuralları:

* Kaydederken etiket listesi denetlenmez. Bir olay için tanımlı olmayan etiket, mesajda boş görünür.
* Tarihler her zaman `gg.aa.yyyy`, saatler `ss:dd` biçimindedir ve klinik saat dilimine göre yazılır. Klinik ayarlarındaki tarih ve saat biçimi bu etiketleri etkilemez.
* Gönderimde HTML, kanala göre çevrilir. WhatsApp'ta kalın, italik ve üstü çizili metin WhatsApp biçimine, Telegram'da `b`, `i`, `u`, `s`, `code`, `pre` öğelerine dönüşür. Web sitesi ve Instagram'da düz metin gider.

## Oluşturma ve güncelleme

Yeni kliniklerde 19 olayın şablonu zaten vardır. Aynı `system_name` ile ikinci bir şablon oluşturmaya çalışırsanız `422` alırsınız. Önce mevcut şablonu güncelleyin. Şablonu sildiyseniz aynı `system_name` ile yeniden oluşturabilirsiniz.

### Şablon metnini güncelleme

`PUT` isteğinde `name`, `subject`, `body` ve `is_active` alanlarının hepsi isteğe bağlıdır; yalnızca değiştirmek istediklerinizi gönderin. `system_name` gönderirseniz yok sayılır.

<CodeGroup>
  ```bash curl theme={null}
  curl -X PUT "https://app.flextell.ai/api/v1/message-templates/123" \
    -H "Authorization: Bearer <access_token>" \
    -H "X-Tenant: <tenant_id>" \
    -H "Content-Type: application/json" \
    -d '{
      "subject": "Randevu Hatırlatması",
      "body": "<p>Merhaba <span data-type=\"mergeTag\" data-id=\"customerName\"></span>, yarın saat <span data-type=\"mergeTag\" data-id=\"appointmentTime\"></span> randevunuz var.</p>",
      "is_active": true
    }'
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch("https://app.flextell.ai/api/v1/message-templates/123", {
    method: "PUT",
    headers: {
      Authorization: "Bearer <access_token>",
      "X-Tenant": "<tenant_id>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      subject: "Randevu Hatırlatması",
      body: '<p>Merhaba <span data-type="mergeTag" data-id="customerName"></span>, yarın saat <span data-type="mergeTag" data-id="appointmentTime"></span> randevunuz var.</p>',
      is_active: true,
    }),
  });
  ```
</CodeGroup>

### Şablon oluşturma

| Alan | Zorunlu | Kural |
| - | - | - |
| `name` | Evet | Metin, en çok 150 karakter. |
| `system_name` | Evet | 19 değerden biri. Kliniğin silinmemiş şablonları arasında benzersiz olmalı. |
| `subject` | Evet | Metin, en çok 200 karakter. |
| `body` | Evet | Metin. Etiketler `mergeTag` öğesiyle yazılır. |
| `is_active` | Hayır | Varsayılan `true`. |

```bash curl theme={null}
curl -X POST "https://app.flextell.ai/api/v1/message-templates" \
  -H "Authorization: Bearer <access_token>" \
  -H "X-Tenant: <tenant_id>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Konum Gönderildi",
    "system_name": "tenant.location.sent",
    "subject": "Konum Bilgisi",
    "body": "<p>Klinik konumumuzu paylaştık.</p>"
  }'
```

Başarılı istek `201` ve oluşturulan şablonu döndürür.

### Silme

`DELETE /api/v1/message-templates/{id}` başarılıysa yanıt `{ "message": "Mesaj şablonu başarıyla silindi" }` olur. Kliniğin o olay için etkin şablonu kalmazsa ilgili otomatik mesaj gönderilmeyebilir; silmek yerine `is_active: false` ile pasife almak da aynı sonucu verir.

<Tip>
  Bir olay için mesajı geçici olarak durdurmak istiyorsanız şablonu silmeyin, `is_active` değerini `false` yapın. Böylece metin ve `id` korunur.
</Tip>

## Hatalar

Genel hata biçimi için bkz. [Hatalar](/api/istekler/hatalar) ve [Hata kodları](/api/istekler/hata-kodlari).

| Kod | HTTP | Ne zaman |
| - | - | - |
| `TENANT_HEADER_REQUIRED` | 400 | `X-Tenant` başlığı gönderilmedi. |
| `FORBIDDEN` | 403 | Token'da ilgili scope var ama kullanıcıda gereken `MessageTemplate` izni yok. |
| `RESOURCE_NOT_FOUND` | 404 | Şablon bu klinikte yok. Mesaj: `Mesaj şablonu bulunamadı`. |
| `VALIDATION_FAILED` | 422 | Alan kuralları sağlanmadı: eksik alan, sınır aşımı, geçersiz `system_name` ya da aynı `system_name` ile ikinci şablon. |

<Note>
  `system_name` benzersizlik hatasının metni şu anda Türkçeleştirilmemiştir ve `errors.system_name` altında İngilizce döner. Hata ayrımını metne göre değil, HTTP durumuna ve `errors` alanına göre yapın.
</Note>


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