Centrum pomoci
Chat API

Webhooks

Posledná aktualizácia:

Prehľad webhookov

Webhooky umožňujú službe ChatLab upozorniť vaše systémy v okamihu, keď sa v chatbotoch niečo stane. Namiesto dopytovania rozhrania Management API alebo manuálneho exportu údajov zaregistrujete koncový bod HTTPS a ChatLab naň v reálnom čase odošle podpísanú požiadavku HTTP POST - keď návštevník zanechá lead, odošle kontaktný formulár, ohodnotí konverzáciu, požiada o človeka alebo keď prebehne akcia AI.

Typické použitia:

  • odosielanie nových leadov priamo do vášho CRM v sekunde, keď sú zachytené
  • upozornenie vášho tímu v Slacku, keď návštevník požiada o live chat (živý čet)
  • odovzdávanie hodnotení a súhrnov konverzácií do vašich vlastných analytických nástrojov
  • sledovanie vykonávania akcií AI a upozorňovanie na chyby

Dostupnosť: váš účet musí obsahovať funkciu Webhooks.

Kde konfigurovať: v administračnej aplikácii otvorte Account settings -> Webhooks (Nastavenia účtu -> Webhooky; hneď vedľa sekcie Management API). Webhooky fungujú na úrovni účtu - jeden koncový bod môže prijímať udalosti zo všetkých vašich botov alebo z jedného vybraného bota.

Nastavenie koncového bodu

  1. Otvorte Account settings -> Webhooks a kliknite na Add endpoint (Pridať koncový bod).
  2. Vyplňte formulár koncového bodu:
    • Name (Názov) - označenie pre vašu vlastnú potrebu, napr. „Synchronizácia CRM“ alebo „Upozornenia Slack“.
    • URL - adresa HTTPS, na ktorú bude ChatLab odosielať udalosti cez POST.
    • Events (Udalosti) - vyberte, ktoré typy udalostí tento koncový bod prijíma (pozrite si katalóg nižšie). Vyberte len to, čo potrebujete; udalosti s vysokým objemom ako ai_action.executed môžu generovať veľkú prevádzku.
    • Bot filter (voliteľné) - vyberte jedného bota alebo možnosť All bots (Všetky boty) pre všetky boty vo vašom účte.
    • Custom form filter (voliteľné) - smeruje odoslania jedného vlastného formulára na tento koncový bod. Zúži iba udalosť custom_form.submitted; všetky ostatné udalosti, na ktoré ste prihlásení (leady, žiadosti o kontakt, konverzácie, live chat, akcie AI), sa doručujú bez ohľadu na toto nastavenie.
  3. Odošlite. Secret (tajný kľúč) koncového bodu sa zobrazí presne raz v potvrdzovacom dialógu - skopírujte si ho hneď a bezpečne ho uložte. Budete ho potrebovať na overenie podpisov (pozrite si časť Zabezpečenie nižšie). V čitateľnej podobe ho už neskôr nie je možné získať.

Každý koncový bod má tiež:

  • Prepínač povolenia/zakázania - pozastavenie doručovania bez odstránenia koncového bodu. Zakázané koncové body udalosti potichu zahadzujú (nezaraďujú sa do frontu na neskôr).
  • Send sample event (Odoslať vzorovú udalosť) - doručí podpísanú testovaciu požiadavku na vašu adresu URL, aby ste si mohli overiť svoj prijímač od začiatku do konca. Pred odoslaním môžete vybrať typ udalosti a upraviť vzorové hodnoty, aby váš handler videl realistické údaje. Test dorazí ako bežné doručenie s hodnotou eventType zodpovedajúcou vášmu výberu (alebo ako webhook.test pre obyčajnú kontrolu pripojenia).
  • Roll secret (Obnoviť tajný kľúč) - vygeneruje nový tajný kľúč a zneplatní ten starý. Použite to v prípade, že mohlo dôjsť k úniku kľúča. Nový tajný kľúč sa znova zobrazí iba raz. Pre riadenú rotáciu koncový bod pozastavte, obnovte a skopírujte nový kľúč, aktualizujte prijímač, potom koncový bod znova povoľte a odošlite vzorovú udalosť. Udalosti počas pozastavenia sa nezaraďujú do frontu. Pred rotáciou si toto prerušenie naplánujte.
  • Delivery log (Záznam doručovania) - zoznam nedávnych doručení pre daný koncový bod s časovou pečiatkou, typom udalosti, stavom HTTP vráteným vaším serverom a časom odozvy. Neúspešné doručenia a pozastavenia ističom (circuit breaker) sú viditeľné tu. Záznam sa uchováva 14 dní.

Obálka udalosti

Každé doručenie je požiadavka HTTP POST s hlavičkou Content-Type: application/json. Telo má vždy rovnakú obálku; objekt data je špecifický pre daný typ udalosti:

{
  "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 - jedinečné pre každú udalosť. Použite ho na deduplikáciu, ak vaše spracovanie musí byť idempotentné.
  • eventType - jeden z typov popísaných nižšie; odosiela sa aj v hlavičke X-ChatLab-Event.
  • timestamp - čas podľa ISO 8601 UTC, kedy bola obálka doručenia pripravená.
  • botId / botName - bot, ktorému udalosť patrí.
  • conversationId / sessionId - kontext konverzácie, ak je k dispozícii.

Katalóg udalostí

lead.created

Spustí sa, keď návštevník odošle svoje kontaktné údaje - prostredníctvom formulára na zber leadov (lead collection form), úvodného formulára pred live chatom alebo vlastného formulára použitého na zber leadov.

{
  "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 - spôsob zachytenia kontaktných údajov: LEAD_COLLECTION_FORM (formulár na zber leadov), LIVE_CHAT_FORM (úvodný formulár pred live chatom), CONVERSATION (AI získala údaje počas chatu), ADMIN_DATA_UPDATE alebo UPDATE_CLIENT_CONTEXT (upravené na strane ChatLabu). Odoslania formulára na ľudskú podporu túto udalosť nikdy nespúšťajú - namiesto toho spúšťajú contact_form.submitted.
  • email, name, phone - kontaktné údaje namapované do záznamu leadu.
  • Keď sa na zber leadov použije vlastný formulár, každé pole definované v tomto formulári je zahrnuté v fields, v poradí z formulára, a formCodeName / formName identifikujú daný formulár. Pri klasickom formulári na zber leadov sú obe hodnoty null a fields je prázdne pole.
  • Každá položka v fields má štruktúru {name, value, type}. name je technický názov poľa, ktorý sa nemení ani pri úprave popiskov - použite ho na mapovanie do vášho CRM.
  • Pri poliach typu multichoice je value pole (array) vybraných možností. Začiarkavacie polia (checkbox) sú samostatné položky s hodnotami "true" / "false".
  • Pri poliach typu file je value odkaz na stiahnutie nahraného súboru; webhook nikdy neprenáša samotný obsah súborov.
  • pageUrl - stránka, na ktorej sa návštevník nachádzal pri odoslaní formulára.

contact_form.submitted

Spustí sa, keď návštevník odošle kontaktný formulár na ľudskú podporu alebo vlastný formulár použitý na kontakt s človekom.

{
  "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, ktorú návštevník zanechal a na ktorú má váš tím podpory odpovedať.
  • source - CUSTOM_FORM, keď kontaktný formulár vychádza z vlastného formulára, CONTACT_FORM pri vstavanom formulári.
  • formCodeName / formName - identifikujú vlastný formulár stojaci za požiadavkou; pri vstavanom formulári sú obe hodnoty null.
  • Keď sa použije vlastný formulár, každé pole definované v tomto formulári je zahrnuté v fields (rovnaký formát {name, value, type} ako pri lead.created). Pri vstavanom kontaktnom formulári sú vyplnené iba polia email a message, fields je prázdne pole a identifikátory formulára sú null.
  • message - namapované pole správy alebo všetky vyplnené hodnoty spojené dohromady, ak formulár nedefinuje samostatné pole pre správu.

custom_form.submitted

Spustí sa pri každom odoslaní vlastného formulára bez ohľadu na jeho účel. Upozorňujeme, že formuláre slúžiace na zber leadov alebo kontakt s človekom spúšťajú aj svoju vyhradenú udalosť lead.created / contact_form.submitted - prihláste sa na odber jednej alebo druhej podľa toho, či chcete všeobecné alebo špecializované zobrazenie, aby ste nevytvárali duplicitné obchodné akcie. Tieto dve rodiny udalostí majú odlišné ID udalostí; conversationId spolu s timestamp nepredstavujú spoľahlivý identifikátor odoslania.

{
  "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 - stabilný technický názov formulára, ktorý sa nemení ani po premenovaní formulára; použite ho na smerovanie odoslaných údajov vo vlastnom systéme. formName je zobrazovaný názov pre návštevníkov.
  • fields používa rovnaké položky {name, value, type} ako lead.created: hodnoty multichoice sú polia, hodnoty súborov sú odkazy na stiahnutie.
  • purpose - STANDALONE, LEAD_COLLECTION alebo HUMAN_CONTACT podľa toho, ako je formulár prepojený s chatbotom.

conversation.started

Spustí sa, keď návštevník odošle prvú správu novej konverzácie.

{
  "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 - presný text úvodnej správy návštevníka. Hodnota je null, ak bola konverzácia otvorená bez textového obsahu.
  • chatSource - kanál, z ktorého konverzácia prišla: WIDGET, WHATSAPP, MESSENGER, VOICE, VOICE_PHONE, API, BOOKING, AIRBNB alebo IDOBOOKING.
  • byAdmin - hodnota true, ak konverzácia pochádza z náhľadu chatbota v administrátorskom paneli ChatLabu namiesto od skutočného návštevníka. Použite ju na odfiltrovanie vlastných testovacích chatov z vášho CRM.
  • countryCode - kód krajiny ISO určený z IP adresy návštevníka, null, ak sa ho nepodarilo určiť.
  • ipAddress - IP adresa návštevníka, ako ju vidí ChatLab, null, ak nie je dostupná. Podľa nariadenia GDPR s ňou zaobchádzajte ako s osobným údajom a ukladajte ju iba vtedy, ak na to máte právny základ.

conversation.rated

Spustí sa, keď návštevník odošle pozitívne alebo negatívne hodnotenie konverzácie (pozrite si Hodnotenie konverzácie).

{
  "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 - POSITIVE alebo NEGATIVE. Zrušenie hodnotenia túto udalosť nespúšťa, takže neutrálnu hodnotu nikdy nedostanete.

conversation.summarized

Spustí sa, keď ChatLab vygeneruje zhrnutie ukončenej konverzácie.

{
  "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 - text vygenerovaného zhrnutia. Generovanie zhrnutia prebieha asynchrónne a závisí od konfigurácie zhrnutí bota a plánu spracovania; nepočítajte s fixným časom doručenia.
  • language - interná jazyková lokalizácia (locale) bota odovzdaná do procesu sumarizácie, napríklad en_US; nepredpokladajte, že sa automaticky zhoduje s jazykom konverzácie návštevníka.

client.summarized

Spustí sa, keď ChatLab aktualizuje profil klienta vytvorený pomocou AI. Profil sa prebudováva z predchádzajúceho profilu a zhrnutia práve ukončenej konverzácie, pričom sa môže vygenerovať až po udalosti conversation.summarized. Poradie doručenia nie je garantované. Údaje zahŕňajú e-mail, pokiaľ je známy, no ChatLab môže evidovať aj klientov bez e-mailu.

{
  "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 - identifikátor na priradenie klienta k vášmu CRM. Pre anonymných návštevníkov, ktorí nezanechali adresu, má hodnotu null, pričom udalosť sa pre nich aj tak spustí - ak je vaša integrácia postavená na e-maili, tieto doručenia preskočte.
  • client - kontaktný záznam, ktorý ChatLab o tejto osobe uchováva: email, name, phone, countryCode a ipAddress. Každý kľúč je vždy prítomný; neznáme hodnoty sú null.
  • clientSummary - celý text profilu ako čistý text, nie zoznam zmien (diff). Nahrádza akékoľvek predchádzajúce zhrnutie, preto ho ukladajte prepísaním pôvodnej hodnoty, nie pripájaním na koniec.
  • Profil sa prebudováva iba pri botoch so zapnutou pamäťou chatu a len pri konverzáciách, ktoré boli neaktívne dostatočne dlho na to, aby boli zhrnuté - túto udalosť očakávajte niekoľko minút po skončení konverzácie, nie okamžite.

live_chat.requested

Spustí sa, keď AI odovzdá konverzáciu do Live Chat (četu naživo) - buď preto, že návštevník požiadal o človeka, alebo preto, že bot vyhodnotil prítomnosť človeka ako potrebnú.

{
  "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 - v súčasnosti vždy AI, pretože odovzdanie je vždy vyvolané akciou bota pre live chat, a to aj vtedy, keď oň návštevník požiada vlastnými slovami. Považujte to za otvorený výpočet (enum): ošetrite aj neznáme hodnoty a nespoliehajte sa striktne len na AI.
  • Táto udalosť pokrýva situáciu, kedy akcia AI požiada o odovzdanie, nie každý spôsob, akým môže návštevník otvoriť live chat. Nedokazuje, že sa operátor skutočne pripojil.

live_chat.started

Spustí sa po odoslaní formulára na odovzdanie návštevníka, keď sa vytvorí relácia live chatu. K tomu dochádza skôr, než sa operátor nevyhnutne pripojí alebo odpovie; nepovažujte to za dôkaz zapojenia človeka.

{
  "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": {}
}
  • Objekt data je zámerne prázdny. Všetko potrebné je v obálke: botId identifikuje chatbota a conversationId / sessionId prepájajú udalosť s konverzáciou. Udalosť môžete prijať aj bez predchádzajúcej udalosti live_chat.requested, napríklad keď návštevník použil ovládací prvok live chatu vo widgete.

live_chat.ended

Spustí sa po ukončení relácie live chatu.

{
  "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 - uplynuté trvanie relácie live chatu v sekundách, počítané od vytvorenia relácie vrátane času čakania na operátora. Pole sa vynecháva v zriedkavých prípadoch, keď sa relácia ukončí bez toho, aby sa vôbec začala.

ai_action.executed

Spustí sa zakaždým, keď bot vykoná akciu AI Actions (akciu AI) - spravované volanie integrácie alebo vlastnú funkciu API. Ide o vysoko frekventovanú udalosť: aktívny e-commerce bot môže vykonať stovky akcií denne a jedna odpoveď návštevníkovi môže vyvolať hneď niekoľko z nich. Prihláste sa na jej odber na vyhradenom koncovom bode alebo sa uistite, že váš prijímač dokáže takýto objem spracovať.

{
  "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 - názov vykonanej akcie tak, ako ju vidí AI, napríklad search_products pri spravovanej integrácii alebo názov, ktorý ste dali vlastnej akcii API.
  • status - SUCCESS alebo ERROR.
  • durationMs - čas trvania akcie v milisekundách. Užitočné na odhalenie pomalej integrácie skôr, ako sa na ňu začnú sťažovať návštevníci.
  • errorMessage - dôvod zlyhania, vyplnený iba vtedy, keď má status hodnotu ERROR; inak null.

webhook.test

Odosiela sa tlačidlom Send sample event (Odoslať ukážkovú udalosť) pri vykonaní bežného testu konektivity. Je podpísaná presne rovnako ako skutočná udalosť.

{
  "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 - fixný text, vždy rovnaký. Polia obálky obsahujú vzorové hodnoty, preto doručenie webhook.test nikdy nepovažujte za skutočné údaje.
  • Toto je jediný typ udalosti, na ktorý sa na koncovom bode nedá prihlásiť: odosiela sa na vyžiadanie z administrátorského panelu a vždy dorazí na koncový bod, na ktorý ste klikli, bez ohľadu na to, na aké udalosti počúva.

Bezpečnosť: overovanie doručených správ

Každá doručená správa obsahuje štyri hlavičky:

Hlavička Hodnota
X-ChatLab-Signature sha256=<hex hmac> - HMAC-SHA256 podpis tela správy
X-ChatLab-Timestamp Unixový čas v sekundách, kedy bola správa podpísaná
X-ChatLab-Event Typ udalosti, napr. lead.created
X-ChatLab-Delivery Jedinečné ID doručenia, zhodné s hodnotou eventId v tele správy

Podpis sa vypočíta ako HMAC-SHA256 z reťazca {timestamp}.{rawBody} pomocou tajného kľúča vášho koncového bodu, kde {timestamp} je hodnota hlavičky X-ChatLab-Timestamp a {rawBody} je pôvodné, nespracované telo požiadavky. Vždy overujte voči nespracovaným bajtom - opätovná serializácia spracovaného JSON zmení sekvenciu bajtov a zneplatní podpis.

Na ochranu pred útokmi opakovaným odoslaním (replay attacks) odmietajte správy, ktorých X-ChatLab-Timestamp je starší ako 5 minút.

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);
}

Ak overenie zlyhá, odpovedzte kódom 401 a telo správy zahoďte. Nikdy nespracovávajte neoverené doručenia - ktokoľvek, kto zistí vašu URL adresu, na ňu môže odoslať ľubovoľný JSON.

Správanie pri doručovaní

Pred implementáciou webhookov sa oboznámte s týmito pravidlami doručovania:

  • Odpovedajte rýchlo. Váš koncový bod musí odpovedať do 3 sekúnd, inak sa doručenie považuje za neúspešné. V tomto časovom okne overte podpis, bezpečne zaraďte udalosť do frontu a potvrďte príjem stavovým kódom 2xx. Pomalšie volania do CRM a spracovanie obchodnej logiky vykonávajte asynchrónne.
  • Fire-and-forget, najviac raz (at-most-once). Zodpovedajúce povolené koncové body majú najviac jeden pokus o doručenie - neprebieha žiadne opakovanie. Pozastavené koncové body a rozpojené ističe (open circuits) môžu potlačiť aj tento pokus. Ak je váš koncový bod nedostupný, vyprší mu časový limit alebo vráti iný kód než 2xx, daná udalosť je stratená a nebude znovu doručená. Webhooky slúžia ako notifikácie, nie ako replikované úložisko údajov: na zosúladenie uchovávaných údajov použite Bot Talk API koncové body pre konverzácie alebo exporty leadov, ak sú podporované. Management API pokrýva nastavenia bota a údaje o využití, nie kompletný archív udalostí. Niektoré udalosti nie je možné cez tieto rozhrania spätne zrekonštruovať.
  • Istič (Circuit breaker). Po 5 po sebe idúcich neúspešných doručeniach pre danú dvojicu koncový bod / bot sa doručovanie pre túto dvojicu pozastaví na 5 minút. Udalosti, ktoré nastanú počas tejto pauzy, sa zahodia a v protokole doručovania sa zobrazia záznamy CIRCUIT_OPEN, ktoré označujú potlačené pokusy. Doručenia preskočené v dôsledku rozpojeného ističa sa nezapočítavajú do limitu pre automatické vypnutie.
  • Automatické vypnutie (Auto-disable). Kontrola sa vykonáva v okamihu zlyhania doručenia, nikdy nie na základe časovača. Ak doručenie zlyhá a počas posledných 7 dní nedošlo k žiadnemu úspešnému doručeniu - počítané od posledného úspechu alebo od dátumu vytvorenia koncového bodu, ak ešte nikdy neuspel - koncový bod sa automaticky vypne a vy dostanete e-mailové upozornenie. Jediný kód 2xx v ktoromkoľvek okamihu toto počítadlo resetuje. Koncový bod, ktorý nedostáva žiadnu prevádzku, sa nikdy nevypne, pretože pri ňom nič nezlyháva. Po oprave vášho prijímača ho znova zapnite v Account settings (Nastavenia účtu); počítadlo zlyhaní a časová pečiatka automatického vypnutia sa pri opätovnom zapnutí vymažú, pričom zmeškané udalosti sa spätne nedoručujú.
  • 410 Gone. Ak váš koncový bod odpovie stavovým kódom HTTP 410 Gone, ChatLab ho okamžite vypne. Toto môžete využiť na programové vyradenie koncového bodu z prevádzky priamo z prijímacej strany.
  • Idempotencia. Pri bežnej prevádzke sa neočakáva duplicitné doručenie, ale ak vaše spracovanie vyžaduje striktnú idempotenciu, odstraňujte duplicity podľa eventId (ktoré je k dispozícii aj v hlavičke X-ChatLab-Delivery).

Poradie doručovania nie je zaručené. Ukladajte si ID udalosti a zaistite, aby bolo spracovanie obchodnej logiky idempotentné. Nastavte si vlastné pravidlá uchovávania a kontroly prístupu k dátam z webhookov, pretože môžu obsahovať osobné údaje a odkazy na stiahnutie súborov.

Príklady overenia podpisu využívajú modul Node.js crypto a funkciu hash_equals v PHP. Surové telo požiadavky (raw request body) zachyťte ešte pred jeho spracovaním (parsingom).

Limity

  • Maximálne 10 webhook koncových bodov na jeden účet.
  • Doba uchovávania protokolu doručovania: 14 dní. Staršie záznamy sa odstraňujú automaticky.

Súvisiace články

  • Lead collection - formulár na pozadí udalosti lead.created
  • Human Support Contact form - formulár na pozadí udalosti contact_form.submitted
  • Live Chat - proces na pozadí udalostí live_chat.*
  • Conversation rating - hodnotenie palcom hore/dole na pozadí udalosti conversation.rated
  • AI Actions - integrácie na pozadí udalosti ai_action.executed
  • Chat API - spätné volania widgetu v prehliadači (náprotivok webhookov na strane klienta)
  • Management API - REST API pre správu botov a údaje o využití