Talep Yönetimi

8 görüntülenme Markdown

Destek taleplerini açan, güncelleyen, silen ve yeniden düzenleyen dokuz uç.

Genel Bakış

Bu dokuz uç talebin kendisiyle ilgilenir: açmak, okumak, alanlarını değiştirmek, silmek ve geçmişini görmek. Yanıtlar, notlar ve özel alanlar ayrı uçlarda yaşar; detay ucu onları taşımaz.

Yanına üç yeniden düzenleme işlemi girer. Toplu işlem bir seferde çok talebi kapatır ya da siler. Birleştirme dağılmış bir konuşmayı tek talepte toplar. Bölme ise araya karışmış bir konuyu kendi talebine ayırır.

Bu alan müşteriye dokunur. Talep açmak, çözüldü demek ve bölerken haber vermek birer e-posta üretir; personel atamak da atanana haber gider. Toplu bir betik yazarken bunu hesaba katın.

Referans

Talepleri Listeleme

get/api/v1/admin/tickets
Tickets/GetTickets admin

Destek taleplerini süzerek ve sayfalayarak döndürür.

Sorgu 10
pageintKaçıncı sayfa.
limitintSayfa başına kayıt. Bir ile yüz arasına çekilir.
searchstringKonu, talep numarası, iş referansı, müşteri adı ya da e-posta içinde arar.
statusstringDuruma göre süzer: open, waiting, process, replied, solved.
department_idintDepartmana göre süzer.
client_idintMüşteriye göre süzer.
assigned_idintAtanan personele göre süzer.
priorityintÖnceliğe göre süzer.
cdatestringAçılış tarihine göre süzer.
cdate_opstringTarih karşılaştırmasının yönü. Tarih alanıyla birlikte verilir.
Dönen alanlar data[] — 15 + meta
idintTalebin numarası.
referencestring | nullİş referansı.
subjectstringTalebin konusu.
statusstringTalebin durumu: open, waiting, process, replied, solved.
custom_status_idintKuruluma özel durum. Sıfır, standart durum demektir.
priorityintTalebin önceliği.
pipeintTalebin e-postadan gelip gelmediği.
admin_unreadboolPersonel için okunmamış mı.
user_unreadboolMüşteri için okunmamış mı.
created_atstring | nullAçılış anı.
last_reply_atstring | nullSon yanıt anı.
assigned_idintAtanan personel. Sıfır, kimseye atanmadı demektir.
departmentobjectDepartman: numarası ve adı.
clientobjectMüşteri: numarası, adı, şirketi ve e-postası.
last_replyobjectSon yanıtın önizlemesi. Şifreli yanıtta metin boş gelir.
Hatalar 1
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl 'https://panel.ornek.com/api/v1/admin/tickets?status=waiting&limit=25' \
  -H "Authorization: Bearer $API_KEY"
const url = new URL('https://panel.ornek.com/api/v1/admin/tickets');
url.searchParams.set('status', 'waiting');

const res  = await fetch(url, {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets?' . http_build_query(['status' => 'waiting', 'limit' => 25]));
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Sifreli yanitta onizleme metni BOS gelir; sifreli metin listeye hic konmaz.
$rows = Api::Tickets()->GetTickets([], ['status' => 'waiting'])['data'];
$prev = $rows[0]['last_reply']['message'] ?? null;

Talep Açma

post/api/v1/admin/tickets
Tickets/CreateTicket admin bildirim gider

Personel adına bir müşteriye talep açar ve ilk mesajı yazar.

Gövde 12
client_idintreqTalebin sahibi müşteri.
subjectstringreqTalebin konusu.
messagestringreqİlk mesaj. Müşteri verisiyle dolan yer tutucular kullanılabilir.
service_idintİlişkili hizmet. Müşterinin kendi hizmeti olmalı.
statusstringAçılış durumu: open, waiting, process, replied, solved.
custom_status_idintKuruluma özel durum.
department_idintTalebin departmanı.
priorityintTalebin önceliği.
assigned_idintAtanacak personel. Atanırsa o kişiye de haber gider.
lockedboolTalebi kilitli açar. Müşteri yanıt yazamaz.
encryptboolİlk mesajı şifreli saklar.
attachmentsstring | object | arrayEklenecek dosyalar.
Dönen alanlar 201 — data
dataobjectAçılan talebin detayı. Detay ucuyla aynı şekildedir.
Hatalar 10
invalid_client422Müşteri geçersiz.
subject_required422Konu boş.
message_required422Mesaj boş.
invalid_custom_status422Özel durum geçersiz.
invalid_service422Hizmet bu müşteriye ait değil.
invalid_department422Departman geçersiz.
invalid_assigned422Personel geçersiz.
blocked_by_gate422Bir kanca açmayı reddetti.
create_failed422Talep açılamadı.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl -X POST 'https://panel.ornek.com/api/v1/admin/tickets' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"client_id":2,"subject":"Hos geldiniz","message":"Merhaba {FULL_NAME}, hizmetiniz hazir.","department_id":4}'
const res = await fetch('https://panel.ornek.com/api/v1/admin/tickets', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    client_id: 2,
    subject: 'Welcome aboard',
    message: 'Hi {FULL_NAME}, your service {SERVICE} is ready.',
    department_id: 4,
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'client_id'     => 2,
        'subject'       => 'Welcome aboard',
        'message'       => 'Hi {FULL_NAME}, your service {SERVICE} is ready.',
        'department_id' => 4,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Talep acmak MUSTERIYE MAIL GONDERIR; ice aktarma dongusunde her kayit bir posta demektir.
Api::Tickets()->CreateTicket([
    'client_id' => $uid,
    'subject'   => $subject,
    'message'   => 'Hi {FULL_NAME}, your service {SERVICE} is ready.',
]);

Talep Detayı

get/api/v1/admin/tickets/{id}
Tickets/GetTicket admin

Tek bir talebi çözülmüş bağlantılarıyla döndürür.

Dönen alanlar data — 20
idintTalebin numarası.
referencestring | nullİş referansı.
subjectstringTalebin konusu.
statusstringTalebin durumu: open, waiting, process, replied, solved.
custom_status_idintKuruluma özel durum.
priorityintTalebin önceliği.
lockedboolKilitli mi. Kilitliyken müşteri yanıt yazamaz.
langstringTalebin dili.
pipeintE-postadan gelip gelmediği.
admin_unreadboolPersonel için okunmamış mı.
user_unreadboolMüşteri için okunmamış mı.
created_atstring | nullAçılış anı.
last_reply_atstring | nullSon yanıt anı.
senderobjectGönderenin ham bilgisi: ad, e-posta, telefon ve adres. Hesabı olmayan gönderenler için doludur.
departmentobjectDepartman: numarası ve adı.
clientobjectMüşteri: numarası, adı, şirketi ve e-postası.
assignedobject | nullAtanan personel: numarası, adı ve e-postası.
serviceobject | nullİlişkili hizmet: numarası, tipi, adı, durumu ve alan adı.
custom_fieldsarrayTalebin özel alan değerleri. Saklanırken şifrelenir, okunurken çözülür.
statsobjectYanıt hızı ve değerlendirme özeti: ortalama yanıt süresi, yanıt sayısı, ortalama puan ve puan sayısı.
Hatalar 2
not_found404Talep bulunamadı.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl 'https://panel.ornek.com/api/v1/admin/tickets/402' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}`, {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Detay MESAJLARI TASIMAZ; yanitlar, notlar ve gecmis ayri uclardan okunur.
$ticket = Api::Tickets()->GetTicket(['id' => $id])['data'];

Talebi Güncelleme

patch/api/v1/admin/tickets/{id}
Tickets/UpdateTicket admin alan başına bildirim

Gönderdiğiniz alanları uygular; her değişen alan kendi izini bırakır.

Gövde 8
statusstringYeni durum: open, waiting, process, replied, solved. Çözüldü ve işlemde durumları müşteriye haber verir.
custom_status_idintKuruluma özel durum.
department_idintTalebi başka departmana taşır.
priorityintYeni öncelik.
assigned_idintPersonel atar. Sıfır atamayı kaldırır; atama personele haber verir.
service_idintİlişkili hizmet. Sıfır bağı kaldırır.
client_idintTalebi başka müşteriye devreder.
lockedboolKilidi açıkça verir. Tersine çevirme değil, doğrudan atamadır.
Dönen alanlar data + meta
dataobjectGüncel talep detayı.
appliedstring[]Gerçekten değişen alanlar. Meta altında döner; aynı değeri göndermek hiçbir şey yapmaz.
Hatalar 9
invalid_status422Durum geçersiz.
invalid_custom_status422Özel durum geçersiz.
invalid_department422Departman geçersiz.
invalid_priority422Öncelik geçersiz.
invalid_assigned422Personel geçersiz.
invalid_service422Hizmet geçersiz.
invalid_client422Hedef müşteri geçersiz.
not_found404Talep bulunamadı.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl -X PATCH 'https://panel.ornek.com/api/v1/admin/tickets/402' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"status":"solved","priority":3}'
const res = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ status: 'solved', priority: 3 }),
});

const { meta } = await res.json();
console.log(meta.applied);
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PATCH',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['status' => 'solved', 'priority' => 3]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Ayni degeri gondermek NO-OP'tur; gercekte neyin degistigini meta.applied soyler.
$r = Api::Tickets()->UpdateTicket(['id' => $id, 'status' => 'solved']);
$changed = $r['meta']['applied'];

Talebi Silme

delete/api/v1/admin/tickets/{id}
Tickets/DeleteTicket admin ekler de gider

Talebi, yanıtlarını ve dosyalarını kaldırır.

Dönen alanlar data — 2
deletedboolSilme çalıştı mı.
idintSilinen talebin numarası.
Hatalar 2
not_found404Talep bulunamadı.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl -X DELETE 'https://panel.ornek.com/api/v1/admin/tickets/404' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}`, {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id);
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);
// Cop kutusu YOK: yanitlar, ekler ve ozel alan dosyalari birlikte gider.
Api::Tickets()->DeleteTicket(['id' => $id]);

Talep Geçmişi

get/api/v1/admin/tickets/{id}/history
Tickets/GetTicketHistory admin

Talepte ne olduğunu zaman sırasıyla döndürür.

Sorgu 4
pageintKaçıncı sayfa.
limitintSayfa başına kayıt.
searchstringOlaylar içinde arar.
cdatestringTarihe göre süzer.
Dönen alanlar data[] — 5 + meta
idintOlayın numarası.
eventstringNe olduğu. Ham anahtardır; okunur metne çevirmek tüketiciye kalır.
dataobjectOlaya özgü ayrıntı.
actorobjectOlayı yapan: numarası, adı ve tipi.
created_atstring | nullOlayın anı.
Hatalar 2
not_found404Talep bulunamadı.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl 'https://panel.ornek.com/api/v1/admin/tickets/402/history' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}/history`, {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id . '/history');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Olay adi HAM anahtardir; kendi ekraninizda okunur metne siz cevirirsiniz.
$events = Api::Tickets()->GetTicketHistory(['id' => $id])['data'];

Toplu İşlem

post/api/v1/admin/tickets/bulk
Tickets/BulkTicketActions admin müşteriyi de engelleyebilir

Birden çok talebi tek çağrıda kapatır ya da siler.

Gövde 2
idsint[]reqİşlenecek talep numaraları.
actionstringreqUygulanacak işlem: close çözüldü yapar, delete siler, block-close ve block-delete ayrıca müşteriyi talep açmaktan engeller.
Dönen alanlar data — 3
actionstringUygulanan işlem.
processedint[]İşlenen talep numaraları.
countintİşlenen adet.
Hatalar 3
ids_required422Hiç talep verilmedi.
invalid_action422İşlem tanınmıyor.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl -X POST 'https://panel.ornek.com/api/v1/admin/tickets/bulk' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"ids":[405,406],"action":"close"}'
const res = await fetch('https://panel.ornek.com/api/v1/admin/tickets/bulk', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ ids: [405, 406], action: 'close' }),
});

const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/bulk');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['ids' => [405, 406], 'action' => 'close']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Panelin sildirmeden once sordugu sifre adimi API'de YOKTUR; kapi yalnizca kapsamdir.
Api::Tickets()->BulkTicketActions(['ids' => $ids, 'action' => 'close']);

Talepleri Birleştirme

post/api/v1/admin/tickets/merge
Tickets/MergeTickets admin en küçük numara ana talep

Birden çok talebi tek talepte toplar.

Gövde 1
idsint[]reqBirleştirilecek talep numaraları. En az iki tane gerekir ve en küçüğü ana talep olur.
Dönen alanlar data + meta — 2
dataobjectAna talebin detayı.
primary_idintAna talebin numarası. Meta altında döner.
merged_idsint[]İçine katılıp silinen talepler.
Hatalar 4
min_two_required422En az iki talep gerekir.
blocked_by_gate422Bir kanca birleştirmeyi reddetti.
not_found404Ana talep bulunamadı.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl -X POST 'https://panel.ornek.com/api/v1/admin/tickets/merge' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"ids":[419,418]}'
const res = await fetch('https://panel.ornek.com/api/v1/admin/tickets/merge', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ ids: [419, 418] }),
});

const { meta } = await res.json();
console.log(meta.primary_id);   // 418
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/merge');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['ids' => [419, 418]]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Ana talebi SIZ SECMEZSINIZ: en kucuk numara kazanir, digerleri icine katilip silinir.
$r = Api::Tickets()->MergeTickets(['ids' => [419, 418]]);
$primary = $r['meta']['primary_id'];   // 418

Talebi Bölme

post/api/v1/admin/tickets/{id}/split
Tickets/SplitTicket admin

Seçtiğiniz yanıtları yeni bir talebe taşır.

Gövde 5
reply_idsint[]reqTaşınacak yanıtlar. Hepsi kaynak talebe ait olmalı.
subjectstringreqYeni talebin konusu.
department_idintYeni talebin departmanı.
priorityintYeni talebin önceliği.
notify_clientboolMüşteriye haber verir.
Dönen alanlar 201 — data + meta — 2
dataobjectYeni talebin detayı.
source_idintKaynak talebin numarası. Meta altında döner.
moved_repliesintTaşınan yanıt sayısı.
Hatalar 7
replies_required422Hiç yanıt seçilmedi.
subject_required422Konu boş.
invalid_department422Departman geçersiz.
invalid_replies422Bazı yanıtlar bu talebe ait değil.
blocked_by_gate422Bir kanca bölmeyi reddetti.
create_failed422Yeni talep açılamadı.
insufficient_scope403Anahtar gerekli kapsamı taşımıyor.
İstek
curl -X POST 'https://panel.ornek.com/api/v1/admin/tickets/402/split' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"reply_ids":[846,847],"subject":"Fatura sorusu","department_id":4}'
const res = await fetch(`https://panel.ornek.com/api/v1/admin/tickets/${id}/split`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    reply_ids: [846, 847],
    subject: 'Billing question split out',
    department_id: 4,
  }),
});

const body = await res.json();
$ch = curl_init('https://panel.ornek.com/api/v1/admin/tickets/' . $id . '/split');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'reply_ids'     => [846, 847],
        'subject'       => 'Billing question split out',
        'department_id' => 4,
    ]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Yanitlar TASINIR, kopyalanmaz: kaynak talepte artik gorunmezler.
$new = Api::Tickets()->SplitTicket([
    'id'        => $id,
    'reply_ids' => $ids,
    'subject'   => 'Billing question split out',
])['data'];

Tuzaklar

Ana talebi siz seçmezsiniz

Birleştirmede en küçük numaralı talep ana talep olur; dizideki sıra hiçbir şey değiştirmez. Diğerlerinin yanıtları oraya taşınır ve kendileri silinir. Listenin başına yazdığınız numaranın kazanacağını sanmak, konuşmayı beklediğinizin tersi yönde toplar. Sonucu doğrulamak için dönen ana numaraya bakın.

Şifreli yanıt listede boş görünür

Talep listesindeki son yanıt önizlemesi, yanıt şifreliyse boş gelir. Şifreli metin listeye hiç konmaz, bu kasti bir sınırdır. Önizlemeyi olduğu gibi ekrana basan bir istemci o satırda boşluk gösterir; boş değeri "şifreli" diye işaretlemek doğru davranıştır.

Alan değiştirmek posta gönderir

Güncellemede her alan kendi yolunu işletir: durumu çözüldü yapmak müşteriye, personel atamak atanan kişiye bildirim gönderir. Aynı değeri yeniden göndermek hiçbir şey yapmaz, yani bir kayıt gerçekten değiştiğinde posta çıkar. Neyin gittiğini görmek için dönen uygulanan alan listesine bakın.

Engelleyen toplu işlemler talebin ötesine geçer

Toplu işlemin engelleyen iki seçeneği yalnız talepleri kapatıp silmez; müşteriyi de talep açmaktan alıkoyar. Bu, o hesabın destek yolunu kapatan kalıcı bir karardır ve talep silmekle aynı şey değildir. Spam temizliği yazarken engelleyen değil düz seçeneği kullanın.

Silmenin geri dönüşü yok

Talep silindiğinde yanıtları, ekleri, not ekleri ve özel alan dosyaları birlikte gider. Çöp kutusu ya da geri alma yoktur. Kapatmak isteyip silen bir betik, müşterinin geçmişini de götürür; kapatmak için durumu çözüldü yapan güncelleme yeterlidir.

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.