Webhookien yleiskatsaus
Webhookien avulla ChatLab voi ilmoittaa järjestelmillesi heti, kun chatboteissasi tapahtuu jotain. Sen sijaan, että kyselisit tietoja Management API:sta toistuvasti tai veisit dataa manuaalisesti, rekisteröit HTTPS-päätepisteen, johon ChatLab lähettää allekirjoitetun HTTP POST -pyynnön reaaliajassa - kun vierailija jättää liidin, lähettää yhteydenottolomakkeen, arvioi keskustelun, pyytää asiakaspalvelijaa tai kun tekoälytoiminto suoritetaan.
Tyypillisiä käyttötarkoituksia:
- uusien liidien siirtäminen suoraan CRM-järjestelmääsi heti, kun ne on tallennettu
- ilmoituksen lähettäminen tiimillesi Slackissa, kun vierailija pyytää Live Chatia
- keskustelujen arviointien ja yhteenvetojen syöttäminen omaan analytiikkaasi
- AI Action -suoritusten seuranta ja virheistä hälyttäminen
Saatavuus: webhookit ovat käytettävissä STANDARD-paketista alkaen (ominaisuus: Webhooks).
Missä määritys tehdään: avaa hallintapaneelissa Account settings -> Webhooks (Tilin asetukset -> Webhookit) (aivan Management API -osion vieressä). Webhookit ovat tilitasoisia - yksi päätepiste voi vastaanottaa tapahtumia kaikista boteistasi tai suodatetusta osajoukosta.
Päätepisteen määrittäminen
- Avaa Account settings -> Webhooks ja napsauta Create endpoint (Luo päätepiste).
- Täytä päätepisteen lomake:
- Name (Nimi) - omaan käyttöön tarkoitettu tunniste, esim. "CRM-synkronointi" tai "Slack-hälytykset".
- URL - HTTPS-osoite, johon ChatLab lähettää tapahtumat POST-pyyntöinä.
- Events (Tapahtumat) - valitse, mitä tapahtumatyyppejä tämä päätepiste vastaanottaa (katso alla oleva luettelo). Valitse vain tarvitsemasi tapahtumat; paljon liikennettä tuottavat tapahtumat, kuten
ai_action.executed, voivat aiheuttaa runsaasti liikennettä. - Bot filter (Bottisuodatin) (valinnainen) - rajaa päätepiste tiettyihin botteihin. Jätä tyhjäksi, jos haluat vastaanottaa tapahtumia kaikista tilisi boteista.
- Custom form filter (Mukautetun lomakkeen suodatin) (valinnainen) - ohjaa tietyn mukautetun lomakkeen lähetykset tähän päätepisteeseen. Se rajaa vain tapahtumaa
custom_form.submitted; kaikki muut tilaamasi tapahtumat (liidit, yhteydenottopyynnöt, keskustelut, live chat, tekoälytoiminnot) toimitetaan tästä asetuksesta riippumatta.
- Lähetä lomake. Päätepisteen salaisuus (secret) näytetään tasan kerran onnistumisikkunassa - kopioi se talteen heti ja säilytä sitä turvallisesti. Tarvitset sitä allekirjoitusten vahvistamiseen (katso Turvallisuus alla). Selväkielistä merkkijonoa ei voi hakea myöhemmin.
Jokaisella päätepisteellä on myös:
- Ota käyttöön / poista käytöstä -kytkin (Enable/disable toggle) - keskeytä toimitukset poistamatta päätepistettä. Käytöstä poistetut päätepisteet hylkäävät tapahtumat hiljaisesti (niitä ei laiteta jonoon myöhempää varten).
- Send sample event (Lähetä esimerkkitapahtuma) - toimittaa allekirjoitetun testipyynnön URL-osoitteeseesi, jotta voit varmistaa vastaanottimesi toiminnan alusta loppuun. Voit valita tapahtumatyypin ja muokata esimerkkipyyntöjen arvoja ennen lähettämistä, jotta käsittelijäsi näkee realistista dataa. Testi saapuu tavallisena toimituksena, jonka
eventTypevastaa valintaasi (tai muodossawebhook.test, jos kyseessä on pelkkä yhteyden tarkistus). - Roll secret (Uusi salaisuus) - luo uuden salaisuuden ja mitätöi vanhan. Käytä tätä, jos salaisuus on saattanut vuotaa. Uusi salaisuus näytetään jälleen vain kerran. Päivitä vastaanottimesi ennen salaisuuden uusimista, tai toimitusten allekirjoitusten vahvistus epäonnistuu järjestelmässäsi.
- Delivery log (Toimitusloki) - päätepisteen viimeaikaisten toimitusten luettelo, joka sisältää aikaleiman, tapahtumatyypin, palvelimesi palauttaman HTTP-tilakoodin ja vasteajan. Epäonnistuneet toimitukset ja automaattisen virrankatkaisun (circuit breaker) tauot näkyvät täällä. Lokia säilytetään 14 päivää.
Tapahtumapaketti (Event envelope)
Jokainen toimitus on HTTP POST -pyyntö, jossa on Content-Type: application/json. Rungolla on aina sama perusrakenne; data-objekti määräytyy tapahtumatyypin mukaan:
{
"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- uniikki tunniste tapahtumaa kohden. Käytä sitä duplikaattien estämiseen, jos käsittelysi on oltava idempotenttia.eventType- yksi alla kuvatuista tyypeistä; lähetetään myösX-ChatLab-Event-otsakkeessa.timestamp- ISO 8601 UTC -aika, jolloin tapahtuma tapahtui.botId/botName- botti, jolle tapahtuma kuuluu.conversationId/sessionId- keskustelukonteksti, silloin kun se on sovellettavissa.
Tapahtumaluettelo
lead.created
Laukeaa, kun vierailija lähettää yhteystietonsa - liidien keruulomakkeen, live chatin esilomakkeen tai liidien keruuseen käytettävän mukautetun lomakkeen kautta.
{
"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- tapa, jolla yhteystiedot kerättiin:LEAD_COLLECTION_FORM(liidien keruulomake),LIVE_CHAT_FORM(live chatin esilomake),CONVERSATION(tekoäly poimi tiedot keskustelun aikana),ADMIN_DATA_UPDATEtaiUPDATE_CLIENT_CONTEXT(muokattu ChatLabin puolella). Asiakaspalvelun yhteydenottolomakkeen lähetykset eivät koskaan laukaise tätä tapahtumaa - ne laukaisevat sen sijaan tapahtumancontact_form.submitted.email,name,phone- liiditietueeseen yhdistetyt yhteystiedot.- Kun liidien keräämiseen käytetään mukautettua lomaketta, jokainen lomakkeessa määritetty kenttä sisältyy taulukkoon
fieldslomakkeen mukaisessa järjestyksessä, jaformCodeName/formNametunnistavat lomakkeen. Perinteisen liidilomakkeen kohdalla molemmat ovatnulljafieldson tyhjä taulukko. - Jokainen
fields-taulukon alkio on muotoa{name, value, type}.nameon kentän tekninen nimi, joka pysyy samana otsikkomuutoksista riippumatta - käytä sitä kenttien yhdistämiseen (mapping) CRM-järjestelmässäsi. - Monivalintakentissä (
multichoice)valueon valittujen vaihtoehtojen taulukko (array). Valintaruutukentät ovat yksittäisiä kenttiä arvoilla"true"/"false". - Tiedostokentissä (
file)valueon ladatun tiedoston latauslinkki; webhook ei koskaan sisällä itse tiedoston sisältöä. pageUrl- sivu, jolla vierailija oli lomakkeen lähettäessään.
contact_form.submitted
Laukeaa, kun vierailija lähettää asiakaspalvelun yhteydenottolomakkeen tai yhteydenottoon käytettävän mukautetun lomakkeen.
{
"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- osoite, jonka vierailija jätti ja johon tukitiimisi tulisi vastata.source-CUSTOM_FORM, kun yhteydenottolomakkeen taustalla on mukautettu lomake, taiCONTACT_FORM, kun kyseessä on sisäänrakennettu lomake.formCodeName/formName- pyynnön taustalla olevan mukautetun lomakkeen tunnisteet; molemmat ovatnullsisäänrakennetulla lomakkeella.- Kun mukautettua lomaketta käytetään, jokainen kyseiseen lomakkeeseen määritetty kenttä sisältyy
fields-taulukkoon (sama muoto{name, value, type}kuin tapahtumassalead.created). Sisäänrakennetulla yhteydenottolomakkeella vainemailjamessagetäytetään,fieldson tyhjä taulukko ja lomaketunnisteet ovatnull. message- yhteydenottoviestiksi määritetty kenttä tai kaikkien täytettyjen kenttien yhdistetty teksti, jos lomakkeessa ei ole erillistä viestikenttää.
custom_form.submitted
Laukeaa kaikista mukautetun lomakkeen lähetyksistä lomakkeen käyttötarkoituksesta riippumatta. Huomaa, että lomakkeet, joiden käyttötarkoitus on liidien keruu tai ihmisen tavoittaminen, laukaisevat myös niille omistetun tapahtuman lead.created / contact_form.submitted - tilaa jompikumpi sen mukaan, haluatko yleisen vai erikoistuneen näkymän, ja poista duplikaatit yhdistelmällä conversationId + timestamp, jos tilaat molemmat.
{
"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- lomakkeen pysyvä tekninen nimi, joka ei muutu lomaketta uudelleennimettäessä; käytä sitä lähetysten ohjaamiseen omassa järjestelmässäsi.formNameon vierailijoille näytettävä nimi.fieldskäyttää samoja{name, value, type}-tietueita kuinlead.created: monivalintojen arvot ovat taulukoita ja tiedostojen arvot latauslinkkejä.purpose-STANDALONE,LEAD_COLLECTIONtaiHUMAN_CONTACTriippuen siitä, miten lomake on liitetty chatbotiin.
conversation.started
Laukeaa, kun vierailija lähettää uuden keskustelun ensimmäisen viestin.
{
"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- vierailijan aloitusviestin tarkka teksti.null, jos keskustelu avattiin ilman viestisisältöä.chatSource- kanava, josta keskustelu saapui:WIDGET,WHATSAPP,MESSENGER,VOICE,VOICE_PHONE,API,BOOKING,AIRBNBtaiIDOBOOKING.byAdmin-true, kun keskustelu tulee ChatLabin hallintapaneelin chatbot-esikatselusta eikä oikealta vierailijalta. Käytä tätä pitääksesi omat testikeskustelusi poissa CRM:stäsi.countryCode- vierailijan IP-osoitteesta määritetty ISO-maakoodi,nulljos sitä ei pystytty määrittämään.ipAddress- vierailijan IP-osoite ChatLabin havaitsemana,nulljos se ei ole saatavilla. Käsittele sitä henkilötietona GDPR:n mukaisesti ja tallenna se vain, jos sinulla on siihen laillinen peruste.
conversation.rated
Laukeaa, kun vierailija arvioi botin vastauksen peukalolla ylös tai alas (katso Keskustelun arviointi).
{
"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-POSITIVEtaiNEGATIVE. Arvioinnin poistaminen ei laukaise tapahtumaa, joten et koskaan saa neutraalia arvoa.
conversation.summarized
Laukeaa, kun ChatLab luo yhteenvedon päättyneestä keskustelusta.
{
"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"
}
}
summary- luotu yhteenvetoteksti. Yhteenvedot luodaan muutaman minuutin kuluttua siitä, kun keskustelu on hiljentynyt, joten tämä tapahtuma saapuu myöhemmin kuin muut keskustelutapahtumat.language- sen kielen ISO-koodi, jolla yhteenveto kirjoitettiin (keskustelun kielen mukaisesti).
client.summarized
Laukeaa, kun ChatLab päivittää asiakkaan tekoälyprofiilin. Profiili muodostetaan uudelleen aiemmasta profiilista ja juuri päättyneen keskustelun yhteenvedosta, joten tämä tapahtuma seuraa saman keskustelun conversation.summarized-tapahtumaa. Asiakkaat tunnistetaan sähköpostiosoitteen perusteella, minkä vuoksi osoite toistetaan data-objektin päätasolla.
{
"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- tunniste, jolla asiakas voidaan yhdistää omaan CRM-järjestelmääsi. Se onnullanonyymeille vierailijoille, jotka eivät koskaan jättäneet osoitetta, ja tapahtuma laukeaa heillekin - ohita nämä toimitukset, jos integraatiosi perustuu sähköpostiin.client- yhteystietue, joka ChatLabilla on tästä henkilöstä:email,name,phone,countryCodejaipAddress. Jokainen avain on aina läsnä; tuntemattomat arvot ovatnull.clientSummary- koko profiiliteksti pelkkänä tekstinä, ei erotustietona (diff). Se korvaa aiemman yhteenvedon kokonaan, joten tallenna se korvaamalla vanha teksti sen sijaan, että lisäisit sen perään.- Profiili luodaan uudelleen vain boteille, joissa chat memory (keskustelumuisti) on käytössä, ja vain keskusteluille, jotka olivat toimettomina tarpeeksi kauan yhteenvedon tekemiseksi - odota tämän tapahtuman saapuvan minuuttien kuluttua keskustelun päättymisestä, ei välittömästi.
live_chat.requested
Laukeaa, kun tekoäly siirtää keskustelun Live Chatiin, joko siksi, että vierailija pyysi ihmistä, tai siksi, että botti päätti asiakaspalvelijan olevan tarpeen.
{
"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- toistaiseksi ainaAI, koska siirron tekee aina botin live chat -toiminto, silloinkin kun vierailija pyytää sitä suoraan sanoin. Käsittele sitä avoimena enumina: varaudu tuntemattomiin arvoihin sen sijaan, että olettaisit arvon olevan aina pelkkäAI.- Tapahtuma ilmoittaa vain, että siirtoa pyydettiin, ei sitä, että asiakaspalvelija olisi ottanut sen vastaan. Odota sitä varten tapahtumaa
live_chat.started.
live_chat.started
Laukeaa, kun asiakaspalvelija liittyy mukaan ja live chat -istunto todella alkaa.
{
"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": {}
}
dataon tarkoituksella tyhjä. Kaikki tarvitsemasi tiedot ovat perusrakenteessa (envelope):botIdtunnistaa chatbotin jaconversationId/sessionIdyhdistävät tapahtuman keskusteluun, josta sait jo aiemmin tapahtumanlive_chat.requested.
live_chat.ended
Laukeaa, kun live chat -istunto päättyy.
{
"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- kuinka kauan asiakaspalvelija oli keskustelussa laskettuna istunnon alkamishetkestä. Kenttä jätetään pois niissä harvoissa tapauksissa, joissa istunto päättyy ilman, että sitä olisi koskaan aloitettu.
ai_action.executed
Laukeaa joka kerta, kun botti suorittaa tekoälytoiminnon (AI action) - hallitun integraatiokutsun tai mukautetun API-funktion. Tämä on erittäin suuren volyymin tapahtuma: aktiivinen verkkokauppabotti voi suorittaa satoja toimintoja päivässä, ja yksi ainoa vierailijan viesti voi laukaista useita toimintoja. Tilaa se erilliseen päätepisteeseen tai varmista, että vastaanottimesi kestää liikennemäärän.
{
"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- suoritetun toiminnon nimi tekoälyn näkemänä, esimerkiksisearch_productshallitulle integraatiolle tai nimi, jonka annoit mukautetulle API-toiminnolle.status-SUCCESStaiERROR.durationMs- kuinka kauan toiminnon suoritus kesti millisekunteina. Hyödyllinen hitaan integraation havaitsemiseen ennen kuin vierailijat valittavat siitä.errorMessage- epäonnistumisen syy, täytetään vain silloin, kunstatusonERROR; muulloinnull.
webhook.test
Lähetetään Send sample event (Lähetä esimerkkitapahtuma) -painikkeesta, kun suoritat tavallisen yhteyden testauksen. Allekirjoitettu täsmälleen kuten oikea tapahtuma.
{
"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- kiinteä teksti, aina sama. Perusrakenteen kentät sisältävät esimerkkilukuja, joten älä koskaan käsittelewebhook.test-toimitusta oikeana datana.- Tämä on ainoa tapahtumatyyppi, jota et voi tilata päätepisteeseen: se lähetetään tarpeen mukaan hallintapaneelista ja saapuu aina siihen päätepisteeseen, jota napsautit, riippumatta siitä, mitä tapahtumia se kuuntelee.
Tietoturva: toimitusten todentaminen
Jokainen toimitus sisältää neljä otsaketta (headers):
| Otsake | Arvo |
|---|---|
X-ChatLab-Signature |
sha256=<hex hmac> - hyötykuorman HMAC-SHA256-allekirjoitus |
X-ChatLab-Timestamp |
Unix-aikaleima sekunteina, jolloin toimitus allekirjoitettiin |
X-ChatLab-Event |
Tapahtumatyyppi, esim. lead.created |
X-ChatLab-Delivery |
Yksilöllinen toimitustunnus, joka vastaa tekstiosan eventId-kenttää |
Allekirjoitus lasketaan HMAC-SHA256-tiivisteenä merkkijonosta {timestamp}.{rawBody} päätepisteen salaisuudella (endpoint secret), missä {timestamp} on X-ChatLab-Timestamp-otsakkeen arvo ja {rawBody} on pyynnön raaka, jäsentämätön runko. Vahvista allekirjoitus aina raakojen tavujen perusteella - jäsennetyn JSON-datan uudelleenserialisointi muuttaa tavujärjestystä ja rikkoo allekirjoituksen.
Suojaudu toistohyökkäyksiltä (replay attacks) hylkäämällä toimitukset, joiden X-ChatLab-Timestamp on vanhempi kuin 5 minuuttia.
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 (!signature || !timestamp) 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 + '.' + 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 === '') {
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);
}
Jos vahvistus epäonnistuu, vastaa tilakoodilla 401 ja hylkää hyötykuorma. Älä koskaan käsittele vahvistamattomia toimituksia - kuka tahansa osoitteesi löytävä voi lähettää siihen mielivaltaista JSON-dataa POST-pyynnöllä.
Toimitusten toimintaperiaate
Huomioi nämä toimintatakuut ennen webhookien käyttöönottoa:
- Vastaa nopeasti. Päätepisteesi on vastattava 3 sekunnin kuluessa, tai toimitus katsotaan epäonnistuneeksi. Palauta
2xx-vastaus heti ja käsittele hyötykuorma asynkronisesti (aseta se jonoon ja kuittaa vasta sitten) - älä tee CRM-kutsuja tai tietokantakirjauksia ennen vastaamista. - Kertaluonteinen lähetys (fire-and-forget, at-most-once). Jokaiselle tapahtumalle tehdään tasan yksi toimitusyritys - uudelleenyrityksiä ei ole. Jos päätepisteesi on alhaalla, pyyntö aikakatkaistaan tai se palauttaa muun kuin 2xx-tilakoodin, kyseinen tapahtuma menetetään eikä sitä toimiteta uudelleen. Webhookit ovat ilmoituksia, eivät replikoitu tietovarasto: kun tarvitset taatun kattavuuden, vertaa tietoja Management API -rajapinnan tai liidivientien kanssa.
- Vikavirtakytkin (circuit breaker). Jos botille tapahtuu 5 peräkkäistä epäonnistunutta toimitusta, kyseisen botin toimitukset keskeytetään 5 minuutiksi. Tauon aikana tapahtuvat tapahtumat hylätään, ja toimituslokiin tulee
CIRCUIT_OPEN-merkintöjä, jotta näet tarkalleen, milloin ja miksi liikenne estettiin. Avoimen kytkimen ohittamia toimituksia ei lasketa mukaan automaattiseen käytöstäpoistoon. - Automaattinen käytöstäpoisto. Tarkistus suoritetaan vain toimituksen epäonnistuessa, ei koskaan ajastetusti. Jos toimitus epäonnistuu eikä 7 päivään ole ollut yhtään onnistunutta toimitusta - laskettuna viimeisimmästä onnistumisesta tai päätepisteen luontipäivästä, jos se ei ole koskaan onnistunut - päätepiste kytketään pois päältä ja saat sähköposti-ilmoituksen. Yksittäinen
2xx-vastaus milloin tahansa nollaa tämän laskurin. Päätepistettä, joka ei vastaanota liikennettä, ei koskaan poisteta käytöstä, koska mikään ei epäonnistu. Ota se uudelleen käyttöön Account settings (tilin asetukset) -osiosta, kun vastaanottimesi on korjattu; epäonnistumislaskuri ja automaattisen käytöstäpoiston aikaleima nollataan, kun kytket sen takaisin päälle, eikä poissaolon aikana menetettyjä tapahtumia toimiteta jälkikäteen. - 410 Gone. Jos päätepisteesi vastaa HTTP-tilakoodilla
410 Gone, ChatLab poistaa sen käytöstä välittömästi. Käytä tätä päätepisteen ohjelmalliseen poistamiseen vastaanottavalta puolelta. - Idempotenssi. Kaksinkertaisia toimituksia ei pitäisi tapahtua normaalissa toiminnassa, mutta jos käsittelysi on oltava täysin idempotenttia, poista kaksoiskappaleet
eventId-kentän perusteella (saatavilla myösX-ChatLab-Delivery-otsakkeessa).
Rajoitukset
- Enintään 10 webhook-päätepistettä tiliä kohden.
- Toimituslokien säilytysaika: 14 päivää. Vanhemmat merkinnät poistetaan automaattisesti.
Aiheeseen liittyvät artikkelit
- Liidien kerääminen - lomake
lead.created-tapahtuman taustalla - Ihmisasiakaspalvelun yhteydenottolomake - lomake
contact_form.submitted-tapahtuman taustalla - Live Chat - työnkulku
live_chat.*-tapahtumien taustalla - Keskustelun arviointi - peukutus ylös/alas
conversation.rated-tapahtuman taustalla - AI Actions - integraatiot
ai_action.executed-tapahtuman taustalla - Chat API - selaimen widget-takaisinkutsut (asiakaspuolen vastine webhoodeille)
- Management API - REST-rajapinta bottien hallintaan ja käyttötietoihin