# Talep Yanıtları

https://dev.wisecp.com/tr/talep-yanitlari

Talep konuşmasını okuyan, yazan ve yanıtların saklanma biçimini belirleyen sekiz uç.

## Genel Bakış

Talebin konuşması bu sekiz uçta yaşar. Dördü yanıtın kendisiyle ilgilenir, ikisi bir yanıtın **saklanma ve görünme** biçimini değiştirir, ikisi de eklerle uğraşır.

Yanıtlar sayfa numarasıyla değil **imleçle** gezilir. En yeni yanıt önce gelir; daha eskisini istemek için elinizdeki en eski numarayı, yeni gelen var mı diye yoklamak için en yeni numarayı verirsiniz.

İki ayrı gizlilik kavramı vardır ve karıştırılmamalıdır. **Şifreleme** metnin veritabanında nasıl durduğuyla ilgilidir; personel onu yine okur. **Gizlilik** ise müşterinin görüp görmeyeceğini belirler.

## Referans

### Yanıtları Listeleme

get/api/v1/admin/tickets/{id}/messages

`Tickets/GetTicketMessages` admin imleçli sayfalama

Talebin konuşmasını en yeniden eskiye doğru döndürür.

Sorgu 3

before_reply_idintBu yanıttan daha eskilerini getirir. Geriye doğru sayfalamanın yoludur.

after_reply_idintBu yanıttan sonra gelenleri getirir. Yeni yanıt var mı diye yoklamanın yoludur.

limitintKaç yanıt gelsin. Bir ile elli arası, öntanımlı on; aralık dışındaki bir değerde de on yanıt gelir.

Dönen alanlar data[] — 15 + meta — 5

idintYanıtın numarası.

author_idintYazanın numarası.

author_namestringYazanın adı.

is_adminboolPersonel yanıtı mı.

messagestringYanıtın metni. Şifreli saklansa da burada çözülmüş gelir.

encryptedboolŞifreli saklanıp saklanmadığı.

hiddenboolMüşteriden gizli mi. Gizli yanıtlar da bu listede döner.

pipeboolE-postadan gelip gelmediği.

aiboolYapay zekânın yazıp yazmadığı.

contactboolİletişim formundan gelip gelmediği.

ratingint | nullMüşterinin verdiği puan.

rated_atstring | nullPuanlama anı.

ipstring | nullGönderenin adresi.

created_atstring | nullYazılma anı.

attachmentsarrayEkler: numarası, saklanan adı, yüklenen adı ve boyutu. İçerik burada değil, indirme ucunda.

totalintTalepteki toplam yanıt sayısı. Meta altında döner.

countintBu sayfada dönen adet.

oldest_reply_idintSayfadaki en eski yanıt. Bir sonraki geriye sayfalamaya bunu verirsiniz.

newest_reply_idintSayfadaki en yeni yanıt. Yoklamaya bunu verirsiniz.

has_moreboolDaha eskisi var mı.

Hatalar 2

not_found404Talep ya da yanıt bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/tickets/402/messages?limit=10' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const url = new URL(`https://panel.ornek.com/api/v1/admin/tickets/${id}/messages`);
url.searchParams.set('limit', '10');

const res  = await fetch(url, {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const { data, meta } = await res.json();

// Bir sonraki sayfa: url.searchParams.set('before_reply_id', meta.oldest_reply_id)
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id . '/messages?' . http_build_query(['limit' => 10]));
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// SAYFA NUMARASI YOKTUR: bir sonraki sayfa, elinizdeki en eski yanit numarasiyla istenir.
$page = Api::Tickets()->GetTicketMessages(['id' => $id], ['limit' => 10]);
$next = Api::Tickets()->GetTicketMessages(['id' => $id], [
    'before_reply_id' => $page['meta']['oldest_reply_id'],
]);
```

### Yanıt Yazma

post/api/v1/admin/tickets/{id}/messages

`Tickets/AddTicketMessage` admin müşteriye gider

Talebe yanıt ekler; `keep_status` açık değilse durumunu yanıtlandı yapar, `notify_client` kapalı değilse müşteriye bildirim gönderir.

Gövde 9

messagestringreqYanıtın metni.

signaturestringMetnin sonuna eklenecek imza.

encryptboolYanıtı şifreli saklar.

attachmentsstring | object | arrayEklenecek dosyalar.

aiboolYanıtı yapay zekâ üretimi olarak işaretler.

hiddenboolPersonel-arası yanıt olarak ekler. Müşteri görmez, durum değişmez ve bildirim gitmez.

keep_statusboolYanıt yerine alındı notu ekler. Durum, özel durum ve son yanıt zamanı değişmez; talep personel kuyruğundaki yerini korur, müşteri ise yanıtı okunmamış görür.

notify_clientboolMüşteriye Destek Talebi Yanıtlandı bildirimini gönderir. Öntanımlı olarak açıktır; kapatılırsa yanıt bildirimsiz eklenir. Gizli yanıt bu bildirimi hiç göndermez.

author_namestringMüşteriye gösterilecek yazar adı. Verilmezse anahtarın sahibi görünür.

Dönen alanlar 201 — data

dataobjectEklenen yanıt. Listedeki öğeyle aynı şekildedir.

Hatalar 7

ticket_locked422Talep kilitli.

ticket_claimed422Talep Sahiplenme açık ve talep sizde değil. `details.assigned_id` talebi tutan personeli verir; kimse üstlenmemişse 0 gelir. API anahtarı olmadan yapılan çağrılar bu kapıya takılmaz.

message_required422Mesaj boş.

blocked_by_gate422Bir kanca yanıtı reddetti.

reply_failed422Yanıt eklenemedi.

not_found404Talep ya da yanıt bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X POST 'https://panel.ornek.com/api/v1/admin/tickets/402/messages' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"message":"Sorununuz cozuldu.","signature":"Destek Ekibi"}'
```

```javascript
const res = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}/messages`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    message: 'Your issue is resolved. Please confirm.',
    signature: 'Support Team',
  }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id . '/messages');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'message'   => 'Your issue is resolved. Please confirm.',
        'signature' => 'Support Team',
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Not birakmak istiyorsaniz GIZLI ekleyin: aksi halde musteriye posta gider.
Api::Tickets()->AddTicketMessage([
    'id'      => $id,
    'message' => 'Checked the server logs, nothing unusual.',
    'hidden'  => true,
]);
```

### Yanıtı Düzenleme

patch/api/v1/admin/tickets/{id}/messages/{reply_id}

`Tickets/UpdateTicketMessage` admin

Var olan bir yanıtın metnini değiştirir.

Gövde 1

messagestringreqYeni metin. Yanıt şifreliyse şifreli kalır.

Dönen alanlar data

dataobjectGüncel yanıt. Listedeki öğeyle aynı şekildedir.

Hatalar 3

message_required422Mesaj boş.

not_found404Talep ya da yanıt bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PATCH 'https://panel.ornek.com/api/v1/admin/tickets/402/messages/846' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"message":"Duzeltilmis yanit metni."}'
```

```javascript
const res = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}/messages/${replyId}`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ message: 'Updated reply text.' }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id . '/messages/' . $replyId);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['message' => 'Updated reply text.']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Duzenleme musteriye HABER VERMEZ: gonderilmis postadaki eski metin oylece kalir.
Api::Tickets()->UpdateTicketMessage([
    'id'       => $id,
    'reply_id' => $replyId,
    'message'  => 'Updated reply text.',
]);
```

### Yanıtı Silme

delete/api/v1/admin/tickets/{id}/messages/{reply_id}

`Tickets/DeleteTicketMessage` admin

Bir yanıtı ve eklerini kaldırır; talebin son mesajıysa talebi de siler.

Gövde 1

block_userboolGöndereni de engeller, paneldeki Göndereni Engelle gibi. Hesaplı talepte hesap yeni talep açamaz; misafirin adresi Yasak Listesi'ndeki E-posta Listesi'ne eklenir. Gönderen var olan taleplerine yanıt vermeye devam edebilir.

Dönen alanlar data — 5

deletedboolSilme çalıştı mı.

reply_idintSilinen yanıtın numarası.

blockedboolEngelleme istendi mi. `block_user` değerini geri verir.

remaining_repliesintTalepte kalan mesaj sayısı.

ticket_deletedboolTalep de silindi mi. Silinen yanıt son mesajsa doğru gelir.

Hatalar 2

not_found404Talep ya da yanıt bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X DELETE 'https://panel.ornek.com/api/v1/admin/tickets/402/messages/846' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}/messages/${replyId}`, {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id . '/messages/' . $replyId);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Yanitin ekleri de gider; talebin son yanit ozeti bir sonraki okumada degisir.
Api::Tickets()->DeleteTicketMessage(['id' => $id, 'reply_id' => $replyId]);
```

### Şifrelemeyi Değiştirme

put/api/v1/admin/tickets/{id}/messages/{reply_id}/encryption

`Tickets/SetTicketMessageEncryption` admin

Bir yanıtın şifreli saklanıp saklanmayacağını belirler.

Gövde 1

encryptedboolreqŞifreli saklar ya da şifrelemeyi kaldırır.

Dönen alanlar data — 3

reply_idintYanıtın numarası.

encryptedboolYeni durum.

changedboolBir şey değişti mi. Yanlışsa yanıt zaten o durumdaydı.

Hatalar 2

not_found404Talep ya da yanıt bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PUT 'https://panel.ornek.com/api/v1/admin/tickets/402/messages/846/encryption' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"encrypted":true}'
```

```javascript
const res = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}/messages/${replyId}/encryption`, {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ encrypted: true }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id . '/messages/' . $replyId . '/encryption');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['encrypted' => true]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Sifreleme yalniz SAKLAMAYI degistirir: personel metni her iki durumda da okur.
$r = Api::Tickets()->SetTicketMessageEncryption([
    'id' => $id, 'reply_id' => $replyId, 'encrypted' => true,
])['data'];
```

### Görünürlüğü Değiştirme

put/api/v1/admin/tickets/{id}/messages/{reply_id}/visibility

`Tickets/SetTicketMessageVisibility` admin

Bir personel yanıtını müşteriden gizler ya da tekrar gösterir.

Gövde 1

hiddenboolreqGizler ya da gösterir. Yalnız personel yanıtları gizlenebilir.

Dönen alanlar data — 3

reply_idintYanıtın numarası.

hiddenboolYeni durum.

changedboolBir şey değişti mi.

Hatalar 3

hide_only_staff422Müşteri yanıtı gizlenemez.

not_found404Talep ya da yanıt bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X PUT 'https://panel.ornek.com/api/v1/admin/tickets/402/messages/848/visibility' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"hidden":true}'
```

```javascript
const res = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}/messages/${replyId}/visibility`, {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ hidden: true }),
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id . '/messages/' . $replyId . '/visibility');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['hidden' => true]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Gizlemek gecmise donuk calisir ama GONDERILMIS postayi geri getirmez.
Api::Tickets()->SetTicketMessageVisibility([
    'id' => $id, 'reply_id' => $replyId, 'hidden' => true,
]);
```

### Eki İndirme

get/api/v1/admin/tickets/{id}/attachments/{att_id}

`Tickets/GetTicketAttachment` admin gövde metne çevrilir

Bir yanıt ekinin bilgilerini ve içeriğini döndürür.

Dönen alanlar data — 6

idintEkin numarası.

namestringDiskte saklanan rastgele adı.

file_namestringYüklendiği andaki özgün adı.

file_sizeintDosyanın boyutu.

mimestringDosyanın türü.

content_base64stringDosyanın içeriği. Metne çevrilmiş hâlde gelir, çünkü yanıt bir belgedir.

Hatalar 2

not_found404Ek bulunamadı ya da dosyası eksik.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl 'https://panel.ornek.com/api/v1/admin/tickets/402/attachments/202' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res  = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}/attachments/${attId}`, {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const { data } = await res.json();

const bytes = Uint8Array.from(atob(data.content_base64), (c) => c.charCodeAt(0));
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id . '/attachments/' . $attId);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Icerik metne cevrildigi icin govde dosyadan yaklasik UCTE BIR daha buyuk gelir.
$att = Api::Tickets()->GetTicketAttachment(['id' => $id, 'att_id' => $attId])['data'];
file_put_contents($path, base64_decode($att['content_base64']));
```

### Eki Silme

delete/api/v1/admin/tickets/{id}/attachments/{att_id}

`Tickets/DeleteTicketAttachment` admin

Bir yanıt ekini kaydından ve diskten kaldırır.

Dönen alanlar data — 2

deletedboolSilme çalıştı mı.

attachment_idintSilinen ekin numarası.

Hatalar 2

not_found404Talep ya da ek bulunamadı.

insufficient_scope403Anahtar gerekli kapsamı taşımıyor.

İstek cURL JavaScript PHP (HTTP) PHP (Dahili)

```bash
curl -X DELETE 'https://panel.ornek.com/api/v1/admin/tickets/402/attachments/202' \
  -H "Authorization: Bearer $API_KEY"
```

```javascript
const res = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}/attachments/${attId}`, {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
```

```php
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id . '/attachments/' . $attId);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
```

```php
// Bu uc YANIT eklerini kaldirir; not ekleri kendi uclarindan silinir.
Api::Tickets()->DeleteTicketAttachment(['id' => $id, 'att_id' => $attId]);
```

## Tuzaklar

> **Sayfa numarası yoktur**
> 
> Bu liste imleçle gezilir: bir sonraki sayfayı elinizdeki **en eski yanıt numarasıyla** istersiniz. Sayfa numarası göndermek hiçbir işe yaramaz ve aynı ilk sayfayı sonsuza kadar döndürür. Dönen meta bloğu size hem en eski hem en yeni numarayı verir; ikisini de saklayın.

> **Aynı mesaj bir uçta boş, burada açıktır**
> 
> Talep listesindeki son yanıt önizlemesi şifreli mesajlarda boş gelir; bu uç ise metni **çözülmüş** verir. İkisi çelişmiyor: liste birçok talebi tarayan bir ekrandır ve şifreli metni oraya koymaz. Şifrelemenin anlamı depolamadır, personelden gizlemek değil.

> **Gizli yanıtlar da bu listede döner**
> 
> Personel-arası yanıtlar müşteriye görünmez, ama bu uç onları **diğerleriyle birlikte döndürür**. Konuşmayı olduğu gibi müşteriye gösteren bir entegrasyon dahili notları da sızdırır. Müşteriye dönük her ekranda gizli işaretli yanıtları kendiniz ayıklayın.

> **Yanıt yazmak bildirimi hemen gönderir**
> 
> Öntanımlı olarak yanıt eklemek talebi yanıtlandı durumuna taşır ve müşteriye **bildirim gönderir**. Sonradan düzeltmek gönderilmiş bildirimi geri getirmez; gizlemek de öyle. Yalnız kayıt tutmak istiyorsanız yanıtı gizli ekleyin: o zaman durum değişmez ve kimseye bildirim çıkmaz. `keep_status` ile eklenen alındı notu da müşteriye bildirim gönderir; durdurmak için `notify_client: false` ekleyin.

> **Ek indirmek gövdeyi büyütür**
> 
> Yanıt bir belge olduğu için dosya içeriği **metne çevrilerek** gelir ve gövde dosyadan yaklaşık üçte bir daha büyük olur. Yüz megabaytlık bir ek, yüz otuz megabaytlık bir yanıt demektir; belleğe tümünü alan bir istemci orada durur. Büyük ekleri akışa alarak işleyin ve gerekmedikçe indirmeyin.

## İlgili Makaleler

- [Talep Yönetimi](https://dev.wisecp.com/tr/talep-yonetimi)
- [Dahili Notlar ve Gizli Bilgiler](https://dev.wisecp.com/tr/dahili-notlar-ve-gizli-bilgiler)
- [Talep Ayarları](https://dev.wisecp.com/tr/talep-ayarlari)
