Pregled vebhukova
Vebhukovi omogućavaju da ChatLab obavesti Vaše sisteme onog trenutka kada se nešto dogodi u Vašim četbotovima. Umesto periodičnog slanja upita ka Management API ili ručnog izvoza podataka, Vi registrujete HTTPS krajnju tačku (endpoint), a ChatLab šalje potpisan HTTP POST zahtev u realnom vremenu - kada posetilac ostavi lead, pošalje kontakt formu, oceni razgovor, zatraži ljudskog agenta ili kada se izvrši AI akcija.
Uobičajene primene:
- prosleđivanje novih leadova direktno u Vaš CRM u sekundi kada su prikupljeni
- obaveštavanje Vašeg tima na platformi Slack kada posetilac zatraži Live Chat (ćaskanje uživo)
- slanje ocena i sažetaka razgovora u Vaš analitički sistem
- praćenje izvršavanja AI akcija i slanje upozorenja u slučaju grešaka
Dostupnost: Vaš nalog mora sadržati funkciju Webhooks.
Gde se podešava: u administratorskoj aplikaciji otvorite Account settings -> Webhooks (Podešavanja naloga -> Vebhukovi; odmah pored odeljka za Management API). Vebhukovi funkcionišu na nivou celog naloga - jedna krajnja tačka može primati događaje iz svih Vaših botova ili iz jednog izabranog bota.
Podešavanje krajnje tačke
- Otvorite Account settings -> Webhooks i kliknite na Add endpoint (Dodaj krajnju tačku).
- Popunite obrazac za krajnju tačku:
- Name (Naziv) - oznaka za Vašu ličnu referencu, npr. "CRM sinhronizacija" ili "Slack obaveštenja".
- URL - HTTPS adresa na koju će ChatLab slati POST zahteve sa događajima.
- Events (Događaji) - izaberite koje tipove događaja ova krajnja tačka prima (pogledajte katalog u nastavku). Izaberite samo ono što Vam je potrebno; događaji sa velikim obimom saobraćaja, poput
ai_action.executed, mogu generisati mnogo mrežnog saobraćaja. - Bot filter (opciono) - izaberite jednog bota ili All bots (Svi botovi) za sve botove na Vašem nalogu.
- Custom form filter (opciono) - usmerava prosleđivanje jedne prilagođene forme na ovu krajnju tačku. Ovo sužava samo događaj
custom_form.submitted; svi ostali događaji na koje ste pretplaćeni (leadovi, zahtevi za kontakt, razgovori, Live Chat, AI akcije) biće isporučeni bez obzira na ovo podešavanje.
- Potvrdite unos. Tajni ključ (secret) krajnje tačke se prikazuje samo jednom u prozoru za potvrdu - kopirajte ga odmah i sačuvajte na bezbednom mestu. Biće Vam potreban za proveru potpisa (pogledajte odeljak Bezbednost u nastavku). Tekst ključa u čistom formatu ne može se naknadno preuzeti.
Svaka krajnja tačka takođe ima:
- Prekidač za omogućavanje/onemogućavanje - pauzirajte isporuke bez brisanja krajnje tačke. Onemogućene krajnje tačke tiho odbacuju događaje (oni se ne stavljaju u red čekanja za kasnije).
- Send sample event (Pošalji probni događaj) - šalje potpisan testni zahtev na Vaš URL kako biste mogli da proverite prijemnik od početka do kraja. Možete odabrati tip događaja i izmeniti probne vrednosti pre slanja, tako da Vaš program za obradu vidi realistične podatke. Test stiže kao redovna isporuka gde
eventTypeodgovara Vašem izboru (ili kaowebhook.testza jednostavnu proveru povezivanja). - Roll secret (Zameni tajni ključ) - generiše novi tajni ključ i poništava stari. Koristite ovo ako postoji sumnja da je ključ kompromitovan. Novi tajni ključ se ponovo prikazuje samo jednom. Za kontrolisanu zamenu ključa, pauzirajte krajnju tačku, zamenite i kopirajte novi tajni ključ, ažurirajte prijemnik, a zatim ponovo omogućite krajnju tačku i pošaljite probni događaj. Događaji nastali tokom pauze ne stavljaju se u red čekanja. Isplanirajte ovaj prekid pre zamene ključa.
- Delivery log (Evidencija isporuka) - lista nedavnih isporuka za datu krajnju tačku sa vremenskom oznakom, tipom događaja, HTTP statusom koji je vratio Vaš server i vremenom odziva. Neuspele isporuke i pauze usled automatskog prekidača (circuit breaker) vidljive su ovde. Evidencija se čuva 14 dana.
Omotač događaja
Svaka isporuka je HTTP POST zahtev sa zaglavljem Content-Type: application/json. Telo zahteva uvek ima isti omotač (envelope); objekat data je specifičan za tip događaja:
{
"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- jedinstven za svaki događaj. Koristite ga za deduplikaciju ukoliko Vaša obrada mora biti idempotentna.eventType- jedan od tipova dokumentovanih u nastavku; takođe se šalje u zaglavljuX-ChatLab-Event.timestamp- ISO 8601 UTC vreme kada je omotač isporuke pripremljen.botId/botName- bot kome događaj pripada.conversationId/sessionId- kontekst razgovora, kada je primenljivo.
Katalog događaja
lead.created
Aktivira se kada posetilac pošalje svoje kontakt podatke - putem obrasca za prikupljanje lidova, obrasca pre početka ćaskanja uživo ili prilagođenog obrasca koji se koristi za prikupljanje lidova.
{
"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- način na koji su kontakt podaci prikupljeni:LEAD_COLLECTION_FORM(obrazac za prikupljanje lidova),LIVE_CHAT_FORM(obrazac pre početka ćaskanja uživo),CONVERSATION(AI je preuzeo podatke tokom razgovora),ADMIN_DATA_UPDATEiliUPDATE_CLIENT_CONTEXT(uređeno na strani ChatLab-a). Slanje obrasca za podršku ljudskog operatera nikada ne aktivira ovaj događaj - umesto toga aktiviracontact_form.submitted.email,name,phone- kontakt podaci mapirani na zapis lida.- Kada se za prikupljanje lidova koristi prilagođeni obrazac, svako polje definisano u tom obrascu uključeno je u
fields, redosledom iz obrasca, aformCodeName/formNameidentifikuju obrazac. Kod klasičnog obrasca za lidove oba sunull, afieldsje prazan niz. - Svaki unos u
fieldsima format{name, value, type}.nameje tehnički naziv polja, nepromenljiv pri izmenama oznaka - koristite ga za mapiranje u vaš CRM. - Za polja tipa
multichoicevrednostvalueje niz izabranih opcija. Polja sa poljem za potvrdu (checkbox) su pojedinačni unosi sa vrednostima"true"/"false". - Za polja tipa
filevrednostvalueje link za preuzimanje otpremljene datoteke; webhook nikada ne prenosi sam sadržaj datoteke. pageUrl- stranica na kojoj se posetilac nalazio u trenutku slanja.
contact_form.submitted
Aktivira se kada posetilac pošalje kontakt obrazac za podršku ljudskog operatera ili prilagođeni obrazac koji se koristi za kontakt sa čovekom.
{
"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- adresa koju je posetilac ostavio i na koju vaš tim za podršku treba da odgovori.source-CUSTOM_FORMkada iza kontakt obrasca stoji prilagođeni obrazac,CONTACT_FORMza ugrađeni obrazac.formCodeName/formName- identifikuju prilagođeni obrazac koji stoji iza zahteva; oba sunullza ugrađeni obrazac.- Kada se koristi prilagođeni obrazac, svako polje definisano u tom obrascu je uključeno u
fields(isti format{name, value, type}kao kodlead.created). Kod ugrađenog kontakt obrasca popunjeni su samoemailimessage,fieldsje prazan niz, a identifikatori obrasca sunull. message- mapirano polje poruke ili sve popunjene vrednosti spojene zajedno kada u obrascu nije definisano polje za poruku.
custom_form.submitted
Aktivira se za svako slanje prilagođenog obrasca, bez obzira na svrhu obrasca. Imajte na umu da obrasci čija je svrha prikupljanje lidova ili kontakt sa čovekom takođe aktiviraju sopstveni namenski događaj lead.created / contact_form.submitted - pretplatite se na jedan ili drugi u zavisnosti od toga da li želite opšti ili specijalizovani prikaz, umesto da kreirate duplirane poslovne akcije. Ove dve porodice događaja imaju različite ID-jeve događaja; kombinacija conversationId i timestamp nije pouzdan identifikator slanja.
{
"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- stabilan mašinski naziv obrasca, nepromenjen kada preimenujete obrazac; koristite ga za usmeravanje poslatih podataka u vašem sistemu.formNameje naziv koji se prikazuje posetiocima.fieldskoristi iste unose formata{name, value, type}kaolead.created: multichoice vrednosti su nizovi, a vrednosti datoteka su linkovi za preuzimanje.purpose-STANDALONE,LEAD_COLLECTIONiliHUMAN_CONTACT, u zavisnosti od toga kako je obrazac povezan sa četbotom.
conversation.started
Aktivira se kada posetilac pošalje prvu poruku u novom razgovoru.
{
"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- tačan tekst uvodne poruke posetioca. Vrednost jenullako je razgovor otvoren bez sadržaja poruke.chatSource- kanal preko kojeg je razgovor pristigao:WIDGET,WHATSAPP,MESSENGER,VOICE,VOICE_PHONE,API,BOOKING,AIRBNBiliIDOBOOKING.byAdmin- ima vrednosttruekada razgovor potiče iz pregleda četbota u ChatLab kontrolnoj tabli, a ne od stvarnog posetioca. Koristite ovo kako biste sprečili ulazak sopstvenih test ćaskanja u CRM.countryCode- ISO kod države određen na osnovu IP adrese posetioca, ilinullkada ga nije bilo moguće utvrditi.ipAddress- IP adresa posetioca kako je vidi ChatLab, ilinullkada nije dostupna. Tretirajte je kao lični podatak u skladu sa GDPR-om i čuvajte je samo ako imate pravni osnov.
conversation.rated
Aktivira se kada posetilac pošalje pozitivnu ili negativnu ocenu razgovora (pogledajte Ocenjivanje razgovora).
{
"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-POSITIVEiliNEGATIVE. Poništavanje ocene ne aktivira ovaj događaj, tako da nikada ne dobijate neutralnu vrednost.
conversation.summarized
Aktivira se kada ChatLab generiše rezime završenog razgovora.
{
"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- tekst generisanog rezimea. Generisanje rezimea je asinhrono i zavisi od konfiguracije rezimea za bota i rasporeda obrade; nemojte pretpostavljati fiksno vreme isporuke.language- interni locale bota prosleđen u proces rezimiranja, na primeren_US; nemojte pretpostavljati da se ovo poklapa sa jezikom na kojem je posetilac vodio razgovor.
client.summarized
Aktivira se kada ChatLab osveži AI profil klijenta. Profil se ponovo gradi na osnovu prethodnog profila i rezimea razgovora koji se upravo završio, i može biti generisan nakon događaja conversation.summarized. Redosled isporuke nije garantovan. Telo poruke sadrži imejl kada je poznat, ali ChatLab može čuvati i klijente bez imejla.
{
"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- identifikator za povezivanje klijenta sa vašim CRM-om. Ima vrednostnullza anonimne posetioce koji nikada nisu ostavili adresu, pri čemu se događaj i dalje aktivira za njih - preskočite te isporuke ako se vaša integracija oslanja na imejl.client- kontakt zapis koji ChatLab čuva za ovu osobu:email,name,phone,countryCodeiipAddress. Svaki ključ je uvek prisutan; nepoznate vrednosti sunull.clientSummary- pun tekst profila kao običan tekst, a ne diff. On zamenjuje prethodni rezime bez obzira na to kakav je bio, pa ga sačuvajte prepisivanjem umesto dopisivanjem.- Profil se ponovo gradi samo za botove sa omogućenom funkcijom chat memory (memorija ćaskanja), i samo za razgovore koji su bili neaktivni dovoljno dugo da bi se generisao rezime - očekujte ovaj događaj nekoliko minuta nakon završetka razgovora, a ne odmah.
live_chat.requested
Aktivira se kada AI preda razgovor na Live Chat (čat uživo), bilo zato što je posetilac zatražio čoveka ili zato što je bot odlučio da je potreban ljudski operater.
{
"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- trenutno uvekAI, jer preusmeravanje uvek pokreće akcija ćaskanja uživo samog bota, uključujući i situaciju kada posetilac to zatraži običnim rečima. Tretirajte ovo kao otvoreni enum: obradite nepoznate vrednosti umesto da strogo očekujete samoAI.- Ovaj događaj pokriva situaciju kada AI akcija zahteva preusmeravanje, ali ne i svaki način na koji posetilac može otvoriti ćaskanje uživo. On nije dokaz da se operater pridružio.
live_chat.started
Aktivira se kada se sesija ćaskanja uživo kreira nakon što posetilac pošalje obrazac za preusmeravanje. Ovo se dešava pre nego što se operater nužno pridruži ili odgovori; nemojte ovo tretirati kao dokaz uključenja čoveka.
{
"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": {}
}
dataje namerno prazno. Sve što vam je potrebno nalazi se u koverti:botIdidentifikuje četbota, aconversationId/sessionIdpovezuju događaj sa razgovorom. Možete ga primiti i bez prethodnog događajalive_chat.requested, na primer kada je posetilac upotrebio kontrolu za ćaskanje uživo u samom vidžetu.
live_chat.ended
Aktivira se kada se sesija ćaskanja uživo završi.
{
"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- proteklo trajanje sesije ćaskanja uživo u sekundama, računato od kreiranja sesije, uključujući i vreme čekanja na operatera. Polje se izostavlja u retkom slučaju kada se sesija završi a da nikada nije zapravo započeta.
ai_action.executed
Aktivira se svaki put kada bot izvrši AI action (AI akciju) - poziv upravljane integracije ili prilagođenu API funkciju. Ovo je događaj visokog obima: aktivan e-commerce bot može izvršiti stotine akcija dnevno, a jedna jedina poruka posetioca može pokrenuti nekoliko njih. Pretplatite se na njega na posebnoj krajnjoj tački ili se uverite da vaš prijemnik može da podnese toliki obim.
{
"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- naziv izvršene akcije kako je vidi AI, na primersearch_productsza upravljanu integraciju ili naziv koji ste dali prilagođenoj API akciji.status-SUCCESSiliERROR.durationMs- koliko je akcija trajala, u milisekundama. Korisno za uočavanje spore integracije pre nego što se posetioci požale na nju.errorMessage- razlog neuspeha, popunjen samo kada jestatusjednakERROR; u suprotnom jenull.
webhook.test
Šalje ga dugme Send sample event (Pošalji probni događaj) kada pokrenete jednostavnu proveru povezivanja. Potpisan je potpuno isto kao stvarni događaj.
{
"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- fiksni tekst, uvek isti. Polja u koverti nose probne vrednosti, pa nikada nemojte tretirati isporukuwebhook.testkao stvarne podatke.- Ovo je jedini tip događaja na koji se ne možete pretplatiti na krajnjoj tački: šalje se na zahtev iz administratorskog panela i uvek stiže na krajnju tačku na koju ste kliknuli, bez obzira na to koje događaje ona sluša.
Bezbednost: verifikacija isporuka
Svaka isporuka nosi četiri zaglavlja:
| Zaglavlje | Vrednost |
|---|---|
X-ChatLab-Signature |
sha256=<hex hmac> - HMAC-SHA256 potpis tela zahteva |
X-ChatLab-Timestamp |
Unix vreme u sekundama kada je isporuka potpisana |
X-ChatLab-Event |
Tip događaja, npr. lead.created |
X-ChatLab-Delivery |
Jedinstveni ID isporuke, jednak vrednosti eventId iz tela zahteva |
Potpis se računa kao HMAC-SHA256 nad stringom {timestamp}.{rawBody} pomoću tajnog ključa vaše krajnje tačke, gde je {timestamp} vrednost zaglavlja X-ChatLab-Timestamp, a {rawBody} sirovo, neobrađeno telo zahteva. Uvek verifikujte na osnovu sirovih bajtova - ponovna serijalizacija raščlanjenog JSON-a promeniće redosled bajtova i poništiti potpis.
Da biste se zaštitili od napada ponavljanjem (replay attacks), odbijte isporuke čiji je X-ChatLab-Timestamp stariji od 5 minuta.
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;
// Odbijte zastarele isporuke (starije od 5 minuta)
const ageSeconds = Math.abs(Date.now() / 1000 - Number(timestamp));
if (ageSeconds > 300) return false;
// rawBody moraju biti sirovi bajtovi tela zahteva, a ne ponovo serijalizovan JSON.
// Sa Express-om: 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;
}
// Odbijte zastarele isporuke (starije od 5 minuta)
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);
}
Ako verifikacija ne uspe, odgovorite statusom 401 i odbacite podatke. Nikada nemojte obrađivati neverifikovane isporuke - svako ko otkrije vaš URL može mu poslati proizvoljan JSON putem POST zahteva.
Ponašanje isporuke
Upoznajte se sa ovim pravilima isporuke pre nego što počnete sa radom na webhook-ovima:
- Odgovorite brzo. Vaša krajnja tačka (endpoint) mora da odgovori u roku od 3 sekunde ili se isporuka smatra neuspešnom. Verifikujte potpis, trajno smestite događaj u red čekanja i potvrdite prijem statusom
2xxunutar tog vremenskog okvira. Sporije CRM pozive i poslovnu obradu obavljajte asinhrono. - Pošalji i zaboravi (fire-and-forget), najviše jednom (at-most-once). Odgovarajuće omogućene krajnje tačke dobijaju najviše jedan pokušaj isporuke - nema ponovnih pokušaja. Pauzirane krajnje tačke i aktivirani mehanizmi prekidača (open circuits) mogu sprečiti čak i taj jedan pokušaj. Ako je vaša krajnja tačka nedostupna, istekne joj vreme za odgovor ili vrati status koji nije 2xx, taj događaj je izgubljen i neće biti ponovo isporučen. Webhook-ovi su obaveštenja, a ne skladište replikovanih podataka: koristite krajnje tačke za razgovore u okviru Bot Talk API-ja ili izvoz lead-ova kako biste usaglasili sačuvane podatke gde je to podržano. Management API pokriva podešavanja bota i podatke o korišćenju, a ne kompletnu arhivu događaja. Neki događaji se ne mogu rekonstruisati putem ovih interfejsa.
- Prekidač kola (circuit breaker). Nakon 5 uzastopnih neuspešnih isporuka za par krajnja tačka/bot, isporuke za taj par se pauziraju na 5 minuta. Događaji koji se dese tokom pauze se odbacuju, a evidencija isporuke prikazuje unose
CIRCUIT_OPENkako bi se identifikovali sprečeni pokušaji. Isporuke preskočene zbog otvorenog prekidača ne računaju se u automatsko onemogućavanje. - Automatsko onemogućavanje. Provera se vrši u trenutku kada isporuka ne uspe, nikada na osnovu tajmera. Ako isporuka ne uspe, a 7 dana nije bilo nijedne uspešne isporuke - računajući od poslednjeg uspeha ili od datuma kreiranja krajnje tačke ako nikada nije uspela - krajnja tačka se isključuje i dobijate obaveštenje putem e-pošte. Jedan jedini status
2xxu bilo kom trenutku resetuje taj tajmer. Krajnja tačka koja ne prima saobraćaj se nikada ne onemogućava, jer ništa ne doživljava neuspeh. Ponovo je omogućite u Account settings (Podešavanja naloga) čim popravite svoj prijemnik; brojač neuspeha i oznaka automatskog onemogućavanja se brišu kada je ponovo uključite, a propušteni događaji dok je bila isključena se ne nadoknađuju. - 410 Gone. Ako vaša krajnja tačka odgovori sa HTTP
410 Gone, ChatLab je odmah onemogućava. Iskoristite ovo da programski ugasite krajnju tačku sa strane prijemnika. - Idempotentnost. Dvostruke isporuke se ne očekuju u normalnom radu, ali ako vaša obrada mora biti striktno idempotentna, izvršite deduplikaciju prema
eventId(takođe dostupnom u zaglavljuX-ChatLab-Delivery).
Redosled isporuke nije garantovan. Sačuvajte ID događaja i učinite poslovnu obradu idempotentnom. Zadržite sopstvenu retenciju i kontrole pristupa za sadržaje webhook-ova, koji mogu sadržati lične podatke i linkove za preuzimanje datoteka.
Primeri potpisa koriste Node.js crypto i PHP funkciju hash_equals. Preuzmite sirovo telo zahteva pre nego što ga parsirate.
Ograničenja
- Do 10 webhook krajnjih tačaka po nalogu.
- Zadržavanje evidencije isporuke: 14 dana. Stariji unosi se automatski brišu.
Povezani članci
- Prikupljanje lead-ova - obrazac iza događaja
lead.created - Obrazac za kontakt sa ljudskom podrškom - obrazac iza događaja
contact_form.submitted - Live Chat - tok iza događaja
live_chat.* - Ocena razgovora - palac nagore/nadole iza događaja
conversation.rated - AI Actions - integracije iza događaja
ai_action.executed - Chat API - povratni pozivi vidžeta u pregledaču (pandan webhook-ovima na strani klijenta)
- Management API - REST API za upravljanje botom i podatke o korišćenju