Talep Yanıtları

1.7k görüntülenme Markdown

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 'https://panel.ornek.com/api/v1/admin/tickets/402/messages?limit=10' \
  -H "Authorization: Bearer $API_KEY"
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)
$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);
// 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 -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"}'
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();
$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);
// 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 -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."}'
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();
$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);
// 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 -X DELETE 'https://panel.ornek.com/api/v1/admin/tickets/402/messages/846' \
  -H "Authorization: Bearer $API_KEY"
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();
$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);
// 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 -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}'
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();
$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);
// 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 -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}'
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();
$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);
// 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 'https://panel.ornek.com/api/v1/admin/tickets/402/attachments/202' \
  -H "Authorization: Bearer $API_KEY"
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));
$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);
// 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 -X DELETE 'https://panel.ornek.com/api/v1/admin/tickets/402/attachments/202' \
  -H "Authorization: Bearer $API_KEY"
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();
$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);
// 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.

Faydalı oldu mu?

Geri bildiriminiz için teşekkürler!

Hâlâ Yardıma mı İhtiyacınız Var?

Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.