Web sitesi sohbeti API'si
Web sitesi sohbeti API'si, Peki sohbet balonunun sitenizde kullandığı API'dir. Bilerek herkese açıktır: API anahtarı olmadan, ziyaretçilerinizin tarayıcısında çalışır. Hazır widget tasarımınıza uymuyorsa bu uç noktalar üzerine kendi sohbet arayüzünüzü kurabilirsiniz. Çoğu site için kod parçacığını kullanmak daha iyidir; bkz. Web sitesi sohbeti.
Temel adres: https://peki.ai/api/widget/{key}
Kimlik doğrulama: yok. Yoldaki widget anahtarı ve bir x-visitor-id başlığı.
Bir web sayfasına asla API anahtarı (psk_…) koymayın. Web sitesi sohbeti API'si anahtar gerektirmez. Sayfanızın bir ziyaretçinin kendi sohbetinden fazlasına ihtiyacı varsa, sunucunuzdan Sessions API'yi çağırın.
Başlamadan önce
-
Agent için web sitesi sohbetini açın: Channels → Web sitesi sohbeti bölümünde Sohbeti web sitenizde göster seçeneğini açın.
-
Kod parçacığından widget anahtarını kopyalayın. Şu parçacıkta
<script src="https://peki.ai/widget.js" data-key="pw_Xk3n9QeR7tLm2vBc" async></script>anahtar
pw_Xk3n9QeR7tLm2vBc'dir. -
Sitenize izin verin. Sitenizin adresini, ör.
https://magaza.example.com, İzin verilen web siteleri altına Site ekle ile ekleyin. Liste boşsa her web sitesi sohbeti kullanabilir. -
Agent'ı yayınlayın. O zamana kadar sohbet
409 This assistant is not available yetcevabını verir.
Ziyaretçi kimliği
Her istek bir x-visitor-id başlığı ister: ziyaretçinin tarayıcısında bir kez oluşturup sakladığınız rastgele bir kimlik, ör. localStorage içinde. Bu, ziyaretçinin tek kimlik bilgisidir: ona sahip olan, o ziyaretçinin konuşmasını okuyabilir, başka hiçbir şeyi değil.
- 16 ile 64 karakter arası: harfler, rakamlar,
-ve_. - Rastgele ve tahmin edilemez olsun, ör. tireleri atılmış bir UUID.
- Her tarayıcı için ayrı tutun. Yeni bir kimlik yeni, boş bir sohbet demektir.
function visitorId() {
let id = localStorage.getItem('peki-visitor');
if (!id) {
id = crypto.randomUUID().replaceAll('-', '');
localStorage.setItem('peki-visitor', id);
}
return id;
}
Kimlik yoksa ya da biçimi bozuksa 400 Missing or invalid visitor id döner.
İzin verilen siteler (CORS)
Tarayıcı sayfanızın adresini Origin başlığında gönderir. Widget'ta İzin verilen web siteleri tanımlıysa yalnızca bu adresler birebir eşleştiğinde (şema, alan adı ve port, ör. https://magaza.example.com) geçer; diğer her şey şunu alır:
{ "statusCode": 403, "message": "This website may not use this chat" }
Sohbetin çalıştığı her adresi ekleyin; https://www. sürümleri ve test siteleri dahil. En fazla 20.
İzin verilen yöntemler GET, POST ve OPTIONS; izin verilen istek başlıkları content-type ve x-visitor-id'dir.
Uç noktalar
| Yöntem | Yol | Ne yapar |
|---|---|---|
GET | /config | Sohbetin adı, rengi, karşılama metni ve kullanılabilir olup olmadığı |
GET | /messages | Ziyaretçinin mevcut konuşması |
POST | /messages | Mesaj gönderir |
POST | /files | Dosya yükler |
GET | /files/{id} | Ziyaretçinin kendi konuşmasındaki bir dosyayı indirir |
POST | /sessions | Yeni bir konuşma başlatır |
GET | /feedback | Şimdi puan istenip istenmeyeceği |
POST | /feedback | Konuşmayı puanlar |
Kapalı bir widget ya da bilinmeyen bir anahtar her uç noktaya 404 This chat is not available ile cevap verir.
Yapılandırmayı alma
GET /config
curl https://peki.ai/api/widget/pw_Xk3n9QeR7tLm2vBc/config
{
"name": "Gülüş Diş Kliniği",
"color": "#1C1A17",
"welcome": { "en": "Hi! How can we help you today?", "tr": "Merhaba! Size nasıl yardımcı olabiliriz?" },
"available": true,
"layout": "bubble"
}
| Alan | Açıklama |
|---|---|
name | Agent'ın adı. |
color | Sohbetin rengi, #RRGGBB biçiminde. |
welcome | Dile göre karşılama metni (en, tr). Ziyaretçinize uyanı gösterin. |
available | Agent yayınlanana kadar false. |
layout | bubble (köşede bir düğme) ya da inline (sayfa içinde bir sohbet kutusu). |
/config ziyaretçi kimliği gerektirmez.
Konuşmayı okuma
GET /messages
x-visitor-id: {visitorId}
Ziyaretçinin mevcut konuşmasını en eskiden başlayarak döner. Yeni konuşma sonrasında ya da bir konuşma bitecek kadar uzun süre sessiz kaldıktan sonra liste boş başlar.
[
{ "id": "671ca0a1a1b2c3d4e5f60720", "from": "visitor", "text": "Yarın için boş randevunuz var mı?", "at": "2026-10-26T14:05:40.102Z" },
{ "id": "671ca0b3a1b2c3d4e5f60722", "from": "agent", "text": "", "at": "2026-10-26T14:05:40.230Z", "pending": true }
]
| Alan | Açıklama |
|---|---|
id | Mesaj kimliği. |
from | visitor, agent ya da team (Inbox'ta devralan bir kişi). |
text | Metin. pending iken boştur. |
at | Yazıldığı an. |
pending | Agent hâlâ yazarken true. Bir "yazıyor" göstergesi gösterin. |
author | team mesajlarında ekip üyesinin adı. |
attachments | Dosyalar: { fileId, name, contentType, size }. |
Cevaplar yoklama (polling) ile gelir. Peki widget'ı bir cevap beklerken 1,2 saniyede bir, diğer zamanlarda 4 saniyede bir kontrol eder; siz de aynısını yapın.
Mesaj gönderme
POST /messages
x-visitor-id: {visitorId}
Content-Type: application/json
| Alan | Tür | Zorunlu | Kurallar |
|---|---|---|---|
text | string | İkisinden biri | En fazla 2.000 karakter. |
attachments | string[] | İkisinden biri | Dosya yükleme ile alınmış en fazla 5 farklı dosya kimliği. |
const KEY = 'pw_Xk3n9QeR7tLm2vBc';
const API = `https://peki.ai/api/widget/${KEY}`;
async function send(text) {
const res = await fetch(`${API}/messages`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-visitor-id': visitorId() },
body: JSON.stringify({ text }),
});
if (!res.ok) throw new Error((await res.json()).message);
}
Yanıt 202 { "ok": true }. Ardından cevap için GET /messages uç noktasını yoklayın.
İlk mesaj bir konuşma başlatır; sonrakiler, konuşma çözüldü olarak kapatılana ya da agent'ın yeni oturum süresi boyunca sessiz kalana kadar onu sürdürür.
Dosya yükleme
POST /files
x-visitor-id: {visitorId}
Content-Type: multipart/form-data
file adlı tek bir parça. Fotoğraflar (JPEG, PNG, WebP, GIF) ve belgeler (PDF, TXT, Markdown, CSV), en fazla 10 MB. Tür içerikten kontrol edilir. Ardından dönen id değerini 24 saat içinde bir mesajın attachments alanında gönderin.
const form = new FormData();
form.append('file', input.files[0]);
const res = await fetch(`${API}/files`, { method: 'POST', headers: { 'x-visitor-id': visitorId() }, body: form });
const file = await res.json(); // { id, name, contentType, size, kind: "chat" }
Dosya indirme
GET /files/{id}
x-visitor-id: {visitorId}
Ziyaretçinin kendi konuşmalarındaki bir dosyayı döner: kendi yüklemeleri ve ekibinizin ona gönderdiği dosyalar. Diğer her şey, var olsun ya da olmasın, 404 File not found (file_missing) döner. Başlık gerektiği için dosyaları düz bir <img src> ile değil, fetch ile yükleyip bir blob'dan gösterin.
Yeni konuşma başlatma
POST /sessions
x-visitor-id: {visitorId}
Ziyaretçinin sonraki mesajları yeni bir konuşmaya gider. Eskisi Inbox'unuzda kalır. Yanıt { "ok": true }.
Puanlar
GET /feedback
x-visitor-id: {visitorId}
{ "ask": true, "rating": null }
Beğen ve beğenme düğmelerini göstermek mantıklıysa ask değeri true olur: agent cevap vermiştir ve konuşma çözüldü olarak kapatılmıştır ya da 2 dakikadır sessizdir. rating, varsa daha önce verilmiş puandır.
POST /feedback
x-visitor-id: {visitorId}
Content-Type: application/json
| Alan | Tür | Zorunlu | Kurallar |
|---|---|---|---|
rating | string | Evet | up ya da down. |
comment | string | Hayır | En fazla 500 karakter. |
Başka alana izin verilmez. Yanıt { "ok": true }. Son verilen puan geçerlidir. Son 24 saatte cevaplanmış bir konuşma yoksa 409 Nothing to rate yet.
Sınırlar
Sohbet kendini aşırı yüke karşı korur. Sınır aşıldığında istek, ziyaretçiye gösterebileceğiniz bir mesajla 429 alır.
| Ne | Sınır | Mesaj |
|---|---|---|
| Ziyaretçi başına mesaj | dakikada 20 | You are sending messages too fast. Please wait a moment. |
| Tek bir ağdan tek bir sohbete mesaj | saatte 200 | Too many messages from this network. Please try again later. |
| Tek bir sohbete toplam mesaj | dakikada 120 | This chat is very busy right now. Please try again in a minute. |
| Tek bir ağdan yeni konuşma | saatte 20 | Too many new chats from this network. Please try again later. |
| Ziyaretçi başına dosya | saatte 20 | file_rate |
| Tek bir ağdan dosya | sohbet başına saatte 60, toplamda saatte 150 | file_rate |
| Dosya indirme | ziyaretçi başına dakikada 60, ağ başına dakikada 600 | Too many files opened. Please wait a moment. |
| Puanlar | ziyaretçi başına dakikada 10, ağ başına saatte 100, sohbet başına dakikada 120 | Too many taps. Please wait a moment. |
Dosyalar ayrıca mesaj başına 5 ve konuşma başına 30 ile sınırlıdır; çalışma alanının da günlük bir yayındaki cevap sınırı vardır.
Hatalar
| Durum | Mesaj ya da code | Neden |
|---|---|---|
400 | Missing or invalid visitor id | x-visitor-id yok ya da 16–64 harf, rakam, -, _ değil. |
400 | Write a message or attach a file | Boş mesaj. |
400 | file_count, file_type, conversation_full | Çok fazla dosya, kabul edilmeyen bir tür ya da zaten 30 dosya var. |
403 | This website may not use this chat | Siteniz İzin verilen web siteleri arasında değil. |
404 | This chat is not available | Bilinmeyen anahtar ya da sohbet kapalı. |
409 | This assistant is not available yet | Agent yayınlanmamış. |
409 | file_taken | Bir dosya zaten eklenmiş ya da bulunamıyor. |
413 | file_size | Dosya 10 MB'tan büyük. |
429 | bkz. Sınırlar | Çok fazla istek. |