Webhooks genel bakış
Webhooks, chatbot'larınızda bir şey gerçekleştiği anda ChatLab'in sistemlerinize bildirim göndermesini sağlar. Management API adresini sürekli yoklamak (polling) veya verileri manuel olarak dışa aktarmak yerine, bir HTTPS uç noktası (endpoint) kaydedersiniz ve bir ziyaretçi bir lead bıraktığında, bir iletişim formu gönderdiğinde, bir konuşmayı puanladığında, bir temsilci talep ettiğinde veya bir yapay zeka eylemi çalıştığında ChatLab bu adrese gerçek zamanlı olarak imzalanmış bir HTTP POST gönderir.
Tipik kullanım alanları:
- yeni lead'leri toplandıkları saniye doğrudan CRM'inize aktarmak
- bir ziyaretçi canlı sohbet istediğinde ekibinize Slack üzerinden bildirim göndermek
- konuşma puanlamalarını ve özetlerini kendi analitik araçlarınıza beslemek
- AI action çalıştırmalarını izlemek ve hatalarda uyarı vermek
Kullanılabilirlik: hesabınızın Webhooks özelliğini içermesi gerekir.
Nereden yapılandırılır: yönetici uygulamasında, Account settings -> Webhooks (Hesap ayarları -> Webhooks) bölümünü açın (Management API bölümünün hemen yanında). Webhooks hesap düzeyindedir - tek bir uç nokta tüm botlarınızdan veya seçilen bir bottan gelen etkinlikleri alabilir.
Uç nokta kurulumu
- Account settings -> Webhooks (Hesap ayarları -> Webhooks) bölümünü açın ve Add endpoint (Uç nokta ekle) seçeneğine tıklayın.
- Uç nokta formunu doldurun:
- Name - kendi referansınız için bir etiket, örn. "CRM sync" veya "Slack alerts".
- URL - ChatLab'in etkinlikleri POST edeceği HTTPS adresi.
- Events - bu uç noktanın hangi etkinlik türlerini alacağını seçin (aşağıdaki kataloğa bakın). Yalnızca ihtiyacınız olanları seçin;
ai_action.executedgibi yüksek hacimli etkinlikler çok fazla trafik oluşturabilir. - Bot filter (isteğe bağlı) - tek bir bot seçin veya hesabınızdaki tüm botlar için All bots (Tüm botlar) seçeneğini belirleyin.
- Custom form filter (isteğe bağlı) - belirli bir özel formun gönderimlerini bu uç noktaya yönlendirir. Yalnızca
custom_form.submittedetkinliğini daraltır; abone olduğunuz diğer tüm etkinlikler (lead'ler, iletişim talepleri, konuşmalar, canlı sohbet, AI actions) bu ayardan bağımsız olarak teslim edilir.
- Gönderin. Uç nokta secret bilgisi, başarı iletişim kutusunda tam olarak bir kez gösterilir - şimdi kopyalayın ve güvenli bir şekilde saklayın. İmzaları doğrulamak için buna ihtiyacınız olacak (aşağıdaki Güvenlik bölümüne bakın). Düz metin daha sonra geri alınamaz.
Her uç nokta ayrıca şunlara sahiptir:
- Etkinleştirme/devre dışı bırakma anahtarı - uç noktayı silmeden teslimatları duraklatın. Devre dışı bırakılan uç noktalar etkinlikleri sessizce düşürür (daha sonrası için kuyruğa alınmazlar).
- Send sample event (Örnek etkinlik gönder) - alıcınızı uçtan uca doğrulayabilmeniz için URL'nize imzalı bir test isteği gönderir. Etkinlik türünü seçebilir ve göndermeden önce örnek değerleri düzenleyebilirsiniz, böylece işleyiciniz gerçekçi veriler görür. Test, seçiminize uyan
eventTypedeğeriyle normal bir teslimat olarak (veya basit bir bağlantı kontrolü içinwebhook.testolarak) ulaşır. - Roll secret (Gizli anahtarı yenile) - yeni bir gizli anahtar oluşturur ve eskisini geçersiz kılar. Gizli anahtarın sızdırılmış olabileceğinden şüpheleniyorsanız bunu kullanın. Yeni gizli anahtar da yalnızca bir kez gösterilir. Kontrollü bir rotasyon için uç noktayı duraklatın, yeni gizli anahtarı oluşturup kopyalayın, alıcıyı güncelleyin, ardından yeniden etkinleştirip örnek bir etkinlik gönderin. Duraklatma sırasındaki etkinlikler kuyruğa alınmaz. Rotasyondan önce bu kesintiyi planlayın.
- Delivery log (Teslimat günlüğü) - zaman damgası, etkinlik türü, sunucunuz tarafından döndürülen HTTP durumu ve yanıt süresi ile birlikte uç nokta başına son teslimatların bir listesi. Başarısız teslimatlar ve devre kesici (circuit breaker) duraklamaları burada görünür. Günlük 14 gün boyunca saklanır.
Etkinlik zarfı (envelope)
Her teslimat, Content-Type: application/json içeren bir HTTP POST isteğidir. Gövde her zaman aynı zarfa sahiptir; data nesnesi etkinlik türüne özeldir:
{
"eventId": "9f1c1c8e-6a2b-4b9e-9d2f-3f8a1e2b4c5d",
"eventType": "lead.created",
"timestamp": "2026-08-13T14:22:31Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": { }
}
eventId- etkinlik başına benzersizdir. İşleminizin birim işlemli (idempotent) olması gerekiyorsa bunu tekilleştirme için kullanın.eventType- aşağıda belgelenen türlerden biri; ayrıcaX-ChatLab-Eventbaşlığında da gönderilir.timestamp- teslimat zarfının hazırlandığı ISO 8601 UTC zamanı.botId/botName- etkinliğin ait olduğu bot.conversationId/sessionId- geçerli olduğunda konuşma bağlamı.
Olay kataloğu
lead.created
Bir ziyaretçi iletişim bilgilerini gönderdiğinde tetiklenir - lead toplama formu, canlı sohbet ön formu veya lead toplama için kullanılan özel bir form aracılığıyla.
{
"eventId": "9f1c1c8e-6a2b-4b9e-9d2f-3f8a1e2b4c5d",
"eventType": "lead.created",
"timestamp": "2026-08-13T14:22:31Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {
"email": "jane.doe@example.com",
"name": "Jane Doe",
"phone": "+1 555 0123",
"source": "LEAD_COLLECTION_FORM",
"formCodeName": "lead_form",
"formName": "Lead form",
"fields": [
{"name": "email", "value": "jane.doe@example.com", "type": "email"},
{"name": "company", "value": "Acme Inc.", "type": "text"},
{"name": "topics", "value": ["Billing", "Delivery"], "type": "multichoice"},
{"name": "attachment", "value": "https://api.chatlab.com/aichat/customform/download?key=...&token=...", "type": "file"}
],
"pageUrl": "https://acme.com/pricing"
}
}
source- iletişim bilgilerinin nasıl alındığı:LEAD_COLLECTION_FORM(lead toplama formu),LIVE_CHAT_FORM(canlı sohbet ön formu),CONVERSATION(AI ayrıntıları sohbet sırasında aldı),ADMIN_DATA_UPDATEveyaUPDATE_CLIENT_CONTEXT(ChatLab tarafında düzenlendi). İnsan destek formunun gönderimleri bu olayı asla tetiklemez - bunun yerinecontact_form.submittedolayını tetikler.email,name,phone- lead kaydına eşlenen iletişim bilgileri.- Lead toplama için özel bir form kullanıldığında, bu formda tanımlanan her alan
fieldsiçine dahil edilir, form sırasına göre eklenir veformCodeName/formNameformu tanımlar. Klasik lead formunda her ikisi denulldeğerindedir vefieldsboş bir dizidir. fieldsiçindeki her girdi{name, value, type}şeklindedir.name, etiket düzenlemelerinden etkilenmeyen alanın teknik adıdır; bunu CRM'inize eşleme yapmak için kullanabilirsiniz.multichoicealanları içinvalue, seçilen seçeneklerin bir dizisidir. Onay kutusu alanları,"true"/"false"değerlerine sahip ayrı girişlerdir.filealanları içinvalue, yüklenen dosyanın indirme bağlantısıdır; webhook asla dosya içeriğini taşımaz.pageUrl- ziyaretçinin gönderim yaptığı sırada bulunduğu sayfa.
contact_form.submitted
Bir ziyaretçi insan desteği iletişim formunu veya insan iletişimi için kullanılan özel bir formu gönderdiğinde tetiklenir.
{
"eventId": "3a7b9c2d-1e4f-4a6b-8c0d-5e2f7a9b1c3d",
"eventType": "contact_form.submitted",
"timestamp": "2026-08-13T14:25:02Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {
"email": "jane.doe@example.com",
"message": "I need help with my last invoice.",
"source": "CUSTOM_FORM",
"formCodeName": "contact_form",
"formName": "Contact form",
"fields": [
{"name": "email", "value": "jane.doe@example.com", "type": "email"},
{"name": "order_number", "value": "A-10293", "type": "text"},
{"name": "message", "value": "I need help with my last invoice.", "type": "textarea"}
]
}
}
email- ziyaretçinin bıraktığı ve destek ekibinizin yanıtlaması gereken adres.source- iletişim formunun arkasında özel bir form olduğundaCUSTOM_FORM, yerleşik form içinCONTACT_FORM.formCodeName/formName- isteğin arkasındaki özel formu tanımlar; yerleşik form için her ikisi denulldeğerindedir.- Özel bir form kullanıldığında, bu formda tanımlanan her alan
fieldsiçine dahil edilir (lead.createdile aynı{name, value, type}biçimi). Yerleşik iletişim formunda yalnızcaemailvemessagedoldurulur,fieldsboş bir dizidir ve form tanımlayıcılarınullolur. message- eşlenen mesaj alanı veya form bir mesaj alanı tanımlamadığında doldurulan tüm değerlerin birleştirilmiş halidir.
custom_form.submitted
Formun amacı ne olursa olsun her özel form gönderiminde tetiklenir. Amacı lead toplama veya insan iletişimi olan formların, kendilerine özel lead.created / contact_form.submitted olaylarını da ayrıca tetiklediğini unutmayın; yinelenen iş eylemleri oluşturmak yerine genel veya özelleştirilmiş görünümden hangisini istediğinize bağlı olarak birine ya da diğerine abone olun. İki olay ailesinin olay kimlikleri farklıdır; conversationId ve timestamp kombinasyonu güvenilir bir gönderim tanımlayıcısı değildir.
{
"eventId": "6c1d8e3f-2a5b-4c7d-9e0f-1a4b6c8d0e2f",
"eventType": "custom_form.submitted",
"timestamp": "2026-08-13T14:27:45Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {
"formCodeName": "warranty_claim",
"formName": "Warranty claim",
"fields": [
{"name": "order_number", "value": "A-10293", "type": "text"},
{"name": "issue", "value": "Damaged on arrival", "type": "textarea"},
{"name": "photo", "value": "https://api.chatlab.com/aichat/customform/download?key=...&token=...", "type": "file"}
],
"purpose": "STANDALONE"
}
}
formCodeName- formu yeniden adlandırdığınızda değişmeyen kararlı sistem adı; kendi sisteminizde gönderimleri yönlendirmek için bunu kullanın.formName, ziyaretçilere gösterilen görünen addır.fields,lead.createdile aynı{name, value, type}girdilerini kullanır: çoktan seçmeli değerler dizi, dosya değerleri ise indirme bağlantılarıdır.purpose- formun chatbota nasıl bağlandığına bağlı olarakSTANDALONE,LEAD_COLLECTIONveyaHUMAN_CONTACT.
conversation.started
Bir ziyaretçi yeni bir konuşmanın ilk mesajını gönderdiğinde tetiklenir.
{
"eventId": "8e2f0a4b-3c6d-4e8f-a1b2-2c5d7e9f1a3b",
"eventType": "conversation.started",
"timestamp": "2026-08-13T14:20:11Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {
"firstMessage": "Do you ship to Canada?",
"chatSource": "WIDGET",
"byAdmin": false,
"countryCode": "PL",
"ipAddress": "83.12.44.7"
}
}
firstMessage- ziyaretçinin açılış mesajının tam metni. Konuşma mesaj içeriği olmadan açıldıysanulldeğerini alır.chatSource- konuşmanın geldiği kanal:WIDGET,WHATSAPP,MESSENGER,VOICE,VOICE_PHONE,API,BOOKING,AIRBNBveyaIDOBOOKING.byAdmin- konuşma gerçek bir ziyaretçi yerine ChatLab yönetim paneli içindeki chatbot önizlemesinden geldiğindetruedeğerini alır. Kendi test sohbetlerinizi CRM'inizden uzak tutmak için bunu kullanın.countryCode- ziyaretçinin IP adresinden çözümlenen ISO ülke kodu; belirlenemediğindenullolur.ipAddress- ChatLab tarafından görülen ziyaretçi IP adresi; kullanılamadığındanullolur. Bunu GDPR kapsamında kişisel veri olarak değerlendirin ve yalnızca yasal bir dayanağınız varsa saklayın.
conversation.rated
Bir ziyaretçi olumlu veya olumsuz bir konuşma değerlendirmesi gönderdiğinde tetiklenir (bkz. Konuşma değerlendirmesi).
{
"eventId": "1b4c6d8e-5f0a-4b2c-8d3e-4f7a9b1c3d5e",
"eventType": "conversation.rated",
"timestamp": "2026-08-13T14:31:09Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {
"rating": "POSITIVE"
}
}
rating-POSITIVEveyaNEGATIVE. Bir değerlendirmenin temizlenmesi olayı tetiklemez, bu nedenle hiçbir zaman nötr bir değer almazsınız.
conversation.summarized
ChatLab tamamlanan bir konuşmanın özetini oluşturduğunda tetiklenir.
{
"eventId": "4d7e9f1a-6b2c-4d4e-9f0a-5b8c0d2e4f6a",
"eventType": "conversation.summarized",
"timestamp": "2026-08-13T14:45:00Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {
"summary": "Visitor asked about shipping to Canada and delivery times. The bot confirmed availability and quoted 5-7 business days. Visitor left satisfied.",
"language": "en_US"
}
}
summary- oluşturulan özet metni. Özet oluşturma işlemi asenkron çalışır ve botun özet yapılandırmasına ve işleme planına bağlıdır; sabit bir teslimat gecikmesi varsaymayın.language- botun özetleme işlemine iletilen dahili yerel ayarıdır (örneğinen_US); bunun ziyaretçinin konuşma diliyle eşleştiğini varsaymayın.
client.summarized
ChatLab bir müşterinin yapay zeka profilini yenilediğinde tetiklenir. Profil, önceki profil ile yeni biten konuşmanın özetinin birleştirilmesiyle yeniden oluşturulur ve conversation.summarized sonrasında oluşturulabilir. Teslimat sırası garanti edilmez. Yük, bilindiğinde bir e-posta içerir, ancak ChatLab e-posta adresi olmayan müşterileri de tutabilir.
{
"eventId": "b5d8f1a3-7c2e-4d9b-a6f0-1e3c5a7b9d2f",
"eventType": "client.summarized",
"timestamp": "2026-08-18T09:12:04Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {
"clientEmail": "jane.doe@example.com",
"client": {
"email": "jane.doe@example.com",
"name": "Jane Doe",
"phone": "+1 555 0123",
"countryCode": "PL",
"ipAddress": "83.12.44.7"
},
"clientSummary": "Returning customer interested in international shipping. Asked about delivery times to Canada twice and about return costs once."
}
}
clientEmail- müşteriyi kendi CRM'inizle eşleştirmek için kullanılan tanımlayıcı. Hiçbir zaman adres bırakmamış anonim ziyaretçiler içinnulldeğerindedir ve olay onlar için de tetiklenir - entegrasyonunuz e-posta adresine bağlıysa bu teslimatları atlayın.client- ChatLab'in bu kişi için tuttuğu iletişim kaydı:email,name,phone,countryCodeveipAddress. Her anahtar her zaman mevcuttur; bilinmeyen değerlernullolur.clientSummary- bir fark (diff) değil, düz metin olarak tam profil metni. Önceki özetin yerine geçer, bu nedenle sonuna eklemek yerine üzerine yazarak kaydedin.- Profil yalnızca sohbet hafızası etkin olan botlar için ve yalnızca özetlenecek kadar boşta kalan konuşmalar için yeniden oluşturulur - bu olayı konuşma biter bitmez değil, birkaç dakika sonra bekleyin.
live_chat.requested
Ziyaretçi bir insan talep ettiği için veya bot bir insanın gerekli olduğuna karar verdiği için yapay zeka konuşmayı Live Chat (canlı sohbet) özelliğine devrettiğinde tetiklenir.
{
"eventId": "7a0b2c4d-8e3f-4a5b-b0c1-6d9e1f3a5b7c",
"eventType": "live_chat.requested",
"timestamp": "2026-08-13T14:33:20Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {
"requestedBy": "AI"
}
}
requestedBy- şu anda her zamanAIdeğerindedir; çünkü devir işlemi, ziyaretçi bunu açık ifadelerle talep ettiğinde bile her zaman botun canlı sohbet eylemi tarafından başlatılır. Bunu açık bir enum olarak ele alın: yalnızcaAIbeklemek yerine bilinmeyen değerleri de yönetin.- Bu olay, bir ziyaretçinin canlı sohbeti başlatabileceği tüm yolları değil, devir talep eden AI eylemini kapsar. Bir temsilcinin sohbete katıldığını kanıtlamaz.
live_chat.started
Ziyaretçinin devir formu gönderildikten sonra canlı sohbet oturumu oluşturulduğunda tetiklenir. Bu, bir temsilcinin mutlaka katıldığı veya yanıt verdiği anlamına gelmez; bunu insan etkileşiminin kanıtı olarak kabul etmeyin.
{
"eventId": "0c3d5e7f-9a4b-4c6d-a1b2-7e0f2a4b6c8d",
"eventType": "live_chat.started",
"timestamp": "2026-08-13T14:33:55Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {}
}
datakasıtlı olarak boştur. İhtiyacınız olan her şey zarftadır:botIdchatbotu tanımlar veconversationId/sessionIdolayı konuşmaya bağlar. Örneğin ziyaretçi widget'ın canlı sohbet denetimini kullandığında, bunu daha önce birlive_chat.requestedolmadan da alabilirsiniz.
live_chat.ended
Canlı sohbet oturumu sona erdiğinde tetiklenir.
{
"eventId": "2e5f7a9b-0c5d-4e7f-b2c3-8f1a3b5c7d9e",
"eventType": "live_chat.ended",
"timestamp": "2026-08-13T14:52:41Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {
"durationSeconds": 1126
}
}
durationSeconds- oturum oluşturulmasından itibaren geçen ve temsilciyi bekleme süresini de içeren canlı sohbet oturumu süresi. Bir oturumun hiç başlatılmadan sona erdiği nadir durumlarda bu alan atlanır.
ai_action.executed
Bot bir AI eylemi (yönetilen bir entegrasyon çağrısı veya özel bir API işlevi) yürüttüğünde her defasında tetiklenir. Bu yüksek hacimli bir olaydır: aktif bir e-ticaret botu günde yüzlerce eylem yürütebilir ve tek bir ziyaretçi mesajı birkaçını tetikleyebilir. Buna özel bir uç noktada abone olun veya alıcınızın bu hacmi kaldırabileceğinden emin olun.
{
"eventId": "5f8a0b2c-1d6e-4f8a-c3d4-9a2b4c6d8e0f",
"eventType": "ai_action.executed",
"timestamp": "2026-08-13T14:21:03Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {
"actionName": "search_products",
"status": "SUCCESS",
"durationMs": 842,
"errorMessage": null
}
}
actionName- yönetilen bir entegrasyon için örneğinsearch_productsveya özel bir API eylemine verdiğiniz ad gibi, yürütülen eylemin yapay zeka tarafından görülen adı.status-SUCCESSveyaERROR.durationMs- eylemin milisaniye cinsinden ne kadar sürdüğü. Ziyaretçiler şikayet etmeden önce yavaş bir entegrasyonu tespit etmek için kullanışlıdır.errorMessage- yalnızcastatusdeğeriERRORolduğunda doldurulan hata nedeni; aksi haldenull.
webhook.test
Basit bir bağlantı testi çalıştırdığınızda Send sample event (Örnek olay gönder) düğmesi tarafından gönderilir. Tıpkı gerçek bir olay gibi imzalanır.
{
"eventId": "9b2c4d6e-3f8a-4b0c-d5e6-0b3c5d7e9f1a",
"eventType": "webhook.test",
"timestamp": "2026-08-13T14:10:00Z",
"botId": 1234,
"botName": "Support Bot",
"conversationId": "conv_a1b2c3",
"sessionId": "sess_x9y8z7",
"data": {
"message": "Test delivery from ChatLab"
}
}
message- sabit metindir, her zaman aynıdır. Zarf alanları örnek değerler taşır, bu nedenle hiçbir zaman birwebhook.testteslimatını gerçek veri olarak değerlendirmeyin.- Bu, bir uç noktada abone olamayacağınız tek olay türüdür: yönetim panelinden isteğe bağlı olarak gönderilir ve hangi olayları dinlediğine bakılmaksızın tıkladığınız uç noktaya her zaman ulaşır.
Güvenlik: teslimatları doğrulama
Her teslimat dört başlık taşır:
| Başlık | Değer |
|---|---|
X-ChatLab-Signature |
sha256=<hex hmac> - Gövdenin HMAC-SHA256 imzası |
X-ChatLab-Timestamp |
Teslimatın imzalandığı saniye cinsinden Unix zamanı |
X-ChatLab-Event |
Olay türü, örn. lead.created |
X-ChatLab-Delivery |
Gövdedeki eventId değerine eşit benzersiz teslimat kimliği |
İmza, uç nokta gizli anahtarınız kullanılarak {timestamp}.{rawBody} dizesi üzerinden HMAC-SHA256 olarak hesaplanır; burada {timestamp} değeri X-ChatLab-Timestamp değeridir ve {rawBody} ham, ayrıştırılmamış istek gövdesidir. Her zaman ham baytlara göre doğrulama yapın - ayrıştırılmış JSON'ın yeniden serileştirilmesi bayt dizilimini değiştirir ve imzayı bozar.
Tekrar oynatma (replay) saldırılarına karşı korunmak için X-ChatLab-Timestamp değeri 5 dakikadan daha eski olan teslimatları reddedin.
Node.js
const crypto = require('crypto');
function verifyChatLabSignature(req, secret) {
const signature = req.headers['x-chatlab-signature'];
const timestamp = req.headers['x-chatlab-timestamp'];
if (typeof signature !== 'string' || typeof timestamp !== 'string') return false;
if (!/^\d+$/.test(timestamp) || !Number.isSafeInteger(Number(timestamp))) return false;
if (!Buffer.isBuffer(req.rawBody)) return false;
// Reject stale deliveries (older than 5 minutes)
const ageSeconds = Math.abs(Date.now() / 1000 - Number(timestamp));
if (ageSeconds > 300) return false;
// rawBody must be the raw request body bytes, not re-serialized JSON.
// With Express: app.use(express.json({ verify: (req, res, buf) => { req.rawBody = buf; } }))
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(timestamp + '.')
.update(req.rawBody)
.digest('hex');
const a = Buffer.from(signature);
const b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
PHP
<?php
function verifyChatLabSignature(string $secret): bool
{
$signature = $_SERVER['HTTP_X_CHATLAB_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_CHATLAB_TIMESTAMP'] ?? '';
if ($signature === '' || $timestamp === '' || !ctype_digit($timestamp)) {
return false;
}
// Reject stale deliveries (older than 5 minutes)
if (abs(time() - (int) $timestamp) > 300) {
return false;
}
$rawBody = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
return hash_equals($expected, $signature);
}
Doğrulama başarısız olursa 401 yanıtı verin ve veriyi atın. Doğrulanmamış teslimatları asla işlemeyin - URL'nizi keşfeden herhangi biri bu adrese rastgele JSON gönderebilir.
İletim davranışı
Webhook'lar üzerine geliştirme yapmadan önce bu iletim kurallarını inceleyin:
- Hızlı yanıt verin. Uç noktanız 3 saniye içinde yanıt vermelidir, aksi takdirde iletim başarısız sayılır. İmzayı doğrulayın, olayı kalıcı olarak kuyruğa alın ve bu zaman aralığı içinde
2xxile onay verin. Daha yavaş CRM çağrılarını ve iş mantığı süreçlerini eşzamansız olarak yürütün. - Gönder ve unut, en fazla bir kez. Eşleşen etkin uç noktalar en fazla bir iletim denemesi alır - yeniden deneme yoktur. Duraklatılan uç noktalar ve açık devreler bu denemeyi bile engelleyebilir. Uç noktanız kapalıysa, zaman aşımına uğrarsa veya 2xx harici bir durum dönerse, o olay kaybolur ve yeniden iletilmez. Webhook'lar bildirim işlevi görür, verilerin kopyalandığı bir veri deposu değildir: Desteklenen durumlarda saklanan verileri eşleştirmek için Bot Talk API konuşma uç noktalarını veya lead dışa aktarmalarını kullanın. Management API bot ayarlarını ve kullanım verilerini kapsar, eksiksiz bir olay arşivi değildir. Bazı olaylar bu arayüzler üzerinden yeniden oluşturulamaz.
- Devre kesici (Circuit breaker). Bir uç nokta/bot çifti için art arda 5 başarısız iletimden sonra, o çift için iletimler 5 dakika boyunca duraklatılır. Duraklatma sırasında gerçekleşen olaylar bırakılır ve iletim günlüğünde engellenen denemeleri belirtmek için
CIRCUIT_OPENkayıtları görüntülenir. Açık devre nedeniyle atlanan iletimler otomatik devre dışı bırakma sınırına dahil edilmez. - Otomatik devre dışı bırakma. Bu denetim bir iletim başarısız olduğu anda çalışır, asla bir zamanlayıcıyla tetiklenmez. Bir iletim başarısız olursa ve - son başarılı iletimden veya daha önce hiç başarılı olmadıysa uç noktanın oluşturulma tarihinden itibaren sayılmak üzere - 7 gün boyunca başarılı bir iletim gerçekleşmemişse uç nokta kapatılır ve size bir e-posta bildirimi gönderilir. Herhangi bir noktada alınan tek bir
2xxbu süreyi sıfırlar. Hiç trafik almayan bir uç nokta asla devre dışı bırakılmaz çünkü başarısız olan bir işlem yoktur. Alıcınız düzeltildiğinde Account settings (Hesap ayarları) bölümünden uç noktayı tekrar etkinleştirin; tekrar açtığınızda hata sayacı ile otomatik devre dışı bırakma işareti temizlenir ve kapalıyken kaçırılan olaylar geçmişe dönük olarak tamamlanmaz. - 410 Gone. Uç noktanız HTTP
410 Goneile yanıt verirse ChatLab uç noktayı hemen devre dışı bırakır. Bu yöntemi, alıcı tarafındaki bir uç noktayı programatik olarak kullanımdan kaldırmak için kullanabilirsiniz. - Eşkuvvetlilik (Idempotency). Normal çalışma koşullarında yinelenen iletimler beklenmez; ancak işlemlerinizin kesinlikle eşkuvvetli olması gerekiyorsa
eventIdile tekilleştirme yapın (bu bilgiX-ChatLab-Deliverybaşlığında da mevcuttur).
İletim sırası garanti edilmez. Olay kimliğini (event ID) saklayın ve iş süreçlerinizi eşkuvvetli olacak şekilde kurgulayın. Kişisel veriler ve dosya indirme bağlantıları içerebilecek webhook yükleri için kendi veri saklama ve erişim denetimlerinizi uygulayın.
İmza örneklerinde Node.js crypto ve PHP'nin hash_equals işlevi kullanılmaktadır. İstek gövdesini ayrıştırmadan önce ham (raw) halini yakalayın.
Sınırlar
- Hesap başına en fazla 10 webhook uç noktası.
- İletim günlüğü saklama süresi: 14 gün. Daha eski kayıtlar otomatik olarak silinir.
İlgili makaleler
- Lead collection -
lead.createdolayının arkasındaki form - Human Support Contact form -
contact_form.submittedolayının arkasındaki form - Live Chat -
live_chat.*olaylarının arkasındaki akış - Conversation rating -
conversation.ratedolayının arkasındaki olumlu/olumsuz değerlendirme - AI Actions -
ai_action.executedolayının arkasındaki entegrasyonlar - Chat API - tarayıcı içi widget geri çağırma işlevleri (webhook'ların istemci tarafındaki karşılığı)
- Management API - bot yönetimi ve kullanım verileri için REST API