Súgóközpont
Chat API

Webhooks

Utoljára frissítve:

Webhookok áttekintése

A webhookok lehetővé teszik, hogy a ChatLab értesítse az Ön rendszereit abban a pillanatban, amint valami történik a chatbotjaiban. Ahelyett, hogy folyamatosan lekérdezné a Management API-t vagy manuálisan exportálná az adatokat, Ön regisztrál egy HTTPS-végpontot, a ChatLab pedig valós időben küld egy aláírt HTTP POST kérést erre a címre - amikor egy látogató leadet hagy hátra, beküld egy űrlapot, értékeli a beszélgetést, emberi ügyintézőt kér, vagy amikor lefut egy AI action.

Tipikus felhasználási esetek:

  • új leadek beküldése közvetlenül a CRM-be a rögzítésük pillanatában
  • a csapat értesítése a Slacken, amikor egy látogató élő chatet kér
  • a beszélgetések értékeléseinek és összegzéseinek betöltése a saját analitikai rendszerébe
  • az AI action futások figyelése és riasztás hibák esetén

Elérhetőség: a fiókjának tartalmaznia kell a Webhooks funkciót.

Hol konfigurálható: az adminisztrációs felületen nyissa meg az Account settings -> Webhooks (Fiókbeállítások -> Webhookok) menüpontot (közvetlenül a Management API szekció mellett). A webhookok fiókszintűek - egy végpont fogadhat eseményeket az összes botból vagy egy kiválasztott botból is.

Végpont beállítása

  1. Nyissa meg az Account settings -> Webhooks menüpontot, majd kattintson az Add endpoint (Végpont hozzáadása) gombra.
  2. Töltse ki a végpont űrlapját:
    • Name (Név) - egy címke a saját azonosításhoz, pl. „CRM sync” vagy „Slack alerts”.
    • URL - a HTTPS-cím, amelyre a ChatLab a POST eseményeket küldi.
    • Events (Események) - válassza ki, mely eseménytípusokat fogadja ez a végpont (lásd az alábbi katalógust). Csak azt válassza ki, amire szüksége van; a nagy forgalmú események, mint például az ai_action.executed, jelentős hálózati forgalmat generálhatnak.
    • Bot filter (Botszűrő) (opcionális) - válasszon ki egy botot, vagy az All bots (Összes bot) lehetőséget a fiókjában lévő összes bot eléréséhez.
    • Custom form filter (Egyéni űrlap szűrő) (opcionális) - egy adott egyéni űrlap beküldéseit irányítja erre a végpontra. Ez kizárólag a custom_form.submitted eseményt szűkíti le; minden más esemény, amelyre feliratkozott (leadek, kapcsolatfelvételi kérések, beszélgetések, élő chat, AI actionök), ettől a beállítástól függetlenül kézbesítésre kerül.
  3. Küldje be. A végpont secret (titkos kulcsa) pontosan egyszer jelenik meg a sikeres létrehozást jelző ablakban - másolja ki azonnal, és tárolja biztonságosan. Erre az aláírások ellenőrzéséhez lesz szüksége (lásd a Biztonság részt lentebb). A nyers szöveget később már nem lehet lekérni.

Mindegyik végpont rendelkezik a következőkkel is:

  • Engedélyezés/letiltás kapcsoló - a kézbesítések szüneteltetése a végpont törlése nélkül. A letiltott végpontok némán elvetik az eseményeket (nem kerülnek várólistára későbbi feldolgozáshoz).
  • Send sample event (Mintaesemény küldése) - egy aláírt tesztkérést küld az Ön URL-címére, így a fogadó oldalt a teljes folyamatban ellenőrizheti. Kiválaszthatja az esemény típusát, és a küldés előtt módosíthatja a mintaértékeket, hogy a feldolgozó kód életszerű adatokat lásson. A teszt normál kézbesítésként érkezik, a kiválasztásának megfelelő eventType értékkel (vagy webhook.test értékként egy egyszerű kapcsolati ellenőrzésnél).
  • Roll secret (Titkos kulcs megújítása) - új titkos kulcsot hoz létre, és érvényteleníti a régit. Akkor használja ezt, ha a titkos kulcs esetleg kiszivárgott. Az új kulcs szintén csak egyszer jelenik meg. A zökkenőmentes kulcscsere érdekében szüneteltesse a végpontot, újítsa meg és másolja ki az új kulcsot, frissítse a fogadó rendszert, majd engedélyezze újra a végpontot, és küldjön egy mintát. A szüneteltetés alatt beérkező események nem kerülnek várólistára. A kulcscsere előtt tervezze meg ezt a leállást.
  • Delivery log (Kézbesítési napló) - végpontonkénti lista a legutóbbi kézbesítésekről, időbélyeggel, eseménytípussal, az Ön szervere által visszaadott HTTP-állapottal és a válaszidővel. A sikertelen kézbesítések és a circuit breaker által okozott szüneteltetések itt láthatók. A napló 14 napig őrződik meg.

Eseményburok (Event envelope)

Minden kézbesítés egy HTTP POST kérés Content-Type: application/json fejléccel. A törzs mindig ugyanazzal a burokszerkezettel rendelkezik; a data objektum tartalma az esemény típusától függ:

{
  "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 - eseményenként egyedi. Használja deduplikációra, ha a feldolgozásnak idempotensnek kell lennie.
  • eventType - az alább dokumentált típusok egyike; az X-ChatLab-Event fejlécben is elküldésre kerül.
  • timestamp - az ISO 8601 UTC időpont, amikor a kézbesítési burok elkészült.
  • botId / botName - a bot, amelyhez az esemény tartozik.
  • conversationId / sessionId - a beszélgetés kontextusa, amennyiben releváns.

Eseménykatalógus

lead.created

Akkor aktiválódik, amikor egy látogató elküldi az elérhetőségeit - a leadgyűjtő űrlapon, a live chat előzetes űrlapján vagy egy leadgyűjtésre használt egyéni űrlapon keresztül.

{
  "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 - az elérhetőségi adatok rögzítésének módja: LEAD_COLLECTION_FORM (leadgyűjtő űrlap), LIVE_CHAT_FORM (live chat előzetes űrlap), CONVERSATION (az AI a csevegés során gyűjtötte be az adatokat), ADMIN_DATA_UPDATE vagy UPDATE_CLIENT_CONTEXT (a ChatLab oldalán szerkesztve). Az emberi ügyfélszolgálati űrlap elküldése soha nem váltja ki ezt az eseményt - helyette a contact_form.submitted eseményt aktiválja.
  • email, name, phone - a leadrekordhoz hozzárendelt elérhetőségi adatok.
  • Ha egyéni űrlapot használ leadgyűjtésre, az adott űrlapon definiált összes mező szerepel a fields tömbben, az űrlapon lévő sorrendben, a formCodeName és a formName pedig azonosítja az űrlapot. A klasszikus lead űrlap esetében mindkettő null, a fields pedig egy üres tömb.
  • A fields minden egyes bejegyzése {name, value, type} formátumú. A name a mező technikai neve, amely a címkék szerkesztése után is változatlan marad - használja ezt a CRM-rendszerébe történő leképezéshez.
  • A multichoice mezők esetében a value a kiválasztott opciók tömbje. A jelölőnégyzet-mezők különálló bejegyzések "true" / "false" értékekkel.
  • A file mezők esetében a value egy letöltési hivatkozás a feltöltött fájlhoz; a webhook soha nem tartalmazza magát a fájltartalmat.
  • pageUrl - az az oldal, amelyen a látogató az űrlap elküldésekor tartózkodott.

contact_form.submitted

Akkor aktiválódik, amikor egy látogató elküldi az emberi ügyfélszolgálati kapcsolatfelvételi űrlapot vagy egy emberi kapcsolatfelvételre használt egyéni űrlapot.

{
  "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 - a látogató által megadott cím, amelyre az ügyfélszolgálati csapatnak válaszolnia kell.
  • source - CUSTOM_FORM, ha a kapcsolatfelvételi űrlap mögött egyéni űrlap áll, és CONTACT_FORM a beépített űrlap esetén.
  • formCodeName / formName - a kérés mögött álló egyéni űrlapot azonosítják; mindkettő null a beépített űrlap esetén.
  • Egyéni űrlap használata esetén az adott űrlapon definiált minden mező szerepel a fields tömbben (ugyanabban a {name, value, type} formátumban, mint a lead.created esetében). A beépített kapcsolatfelvételi űrlapnál csak az email és a message mező töltődik ki, a fields egy üres tömb, az űrlapazonosítók pedig null értékűek.
  • message - a hozzárendelt üzenetmező, vagy az összes kitöltött érték összefűzve, ha az űrlapon nincs külön üzenetmező definiálva.

custom_form.submitted

Minden egyes egyéni űrlapbeküldéskor aktiválódik, függetlenül az űrlap céljától. Vegye figyelembe, hogy azok az űrlapok, amelyek célja a leadgyűjtés vagy az emberi kapcsolatfelvétel, a saját dedikált lead.created / contact_form.submitted eseményüket is aktiválják - iratkozzon fel az egyikre vagy a másikra attól függően, hogy az általános vagy a specializált nézetre van szüksége, elkerülve a duplikált üzleti műveleteket. A két eseménycsalád eltérő eseményazonosítókkal rendelkezik; a conversationId és a timestamp együttesen sem tekinthető megbízható beküldés-azonosítónak.

{
  "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 - az űrlap stabil gépi neve, amely az űrlap átnevezésekor sem változik; használja ezt a beküldések saját rendszerébe történő irányításához. A formName a látogatóknak megjelenített címke.
  • A fields ugyanazokat a {name, value, type} bejegyzéseket használja, mint a lead.created: a többválasztós értékek tömbök, a fájlértékek pedig letöltési hivatkozások.
  • purpose - STANDALONE, LEAD_COLLECTION vagy HUMAN_CONTACT, attól függően, hogy az űrlap hogyan kapcsolódik a cold chatbothoz.

conversation.started

Akkor aktiválódik, amikor egy látogató elküldi egy új beszélgetés első üzenetét.

{
  "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 - a látogató nyitó üzenetének pontos szövege. null, ha a beszélgetést üzenettartalom nélkül nyitották meg.
  • chatSource - a csatorna, amelyen a beszélgetés érkezett: WIDGET, WHATSAPP, MESSENGER, VOICE, VOICE_PHONE, API, BOOKING, AIRBNB vagy IDOBOOKING.
  • byAdmin - értéke true, ha a beszélgetés nem valódi látogatótól, hanem a ChatLab adminisztrációs felületén lévő chatbot-előnézetből származik. Használja ezt arra, hogy a saját tesztbeszélgetéseit távol tartsa a CRM-rendszerétől.
  • countryCode - a látogató IP-címéből meghatározott ISO országkód, vagy null, ha nem sikerült megállapítani.
  • ipAddress - a látogató IP-címe a ChatLab által észleltek szerint, vagy null, ha nem érhető el. Kezelje személyes adatként a GDPR szerint, és csak akkor tárolja, ha rendelkezik megfelelő jogalappal.

conversation.rated

Akkor aktiválódik, amikor egy látogató pozitív vagy negatív beszélgetésértékelést küld be (lásd a Beszélgetés értékelése szakaszt).

{
  "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 vagy NEGATIVE. Az értékelés törlése nem váltja ki az eseményt, így soha nem fog semleges értéket kapni.

conversation.summarized

Akkor aktiválódik, amikor a ChatLab összegzést készít egy befejezett beszélgetésről.

{
  "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 - a generált összegzés szövege. Az összegzés létrehozása aszinkron módon történik, és a bot összegzési beállításaitól, valamint feldolgozási ütemezésétől függ; ne számítson fix kézbesítési késleltetésre.
  • language - a bot összegzéshez átadott belső területi beállítása (locale), például en_US; ne feltételezze, hogy ez megegyezik a látogató beszélgetési nyelvével.

client.summarized

Akkor aktiválódik, amikor a ChatLab frissíti egy ügyfél AI-profilját. A profil az előző profilból, valamint a most véget ért beszélgetés összegzéséből épül újra, és lehetséges, hogy a conversation.summarized után generálódik. A kézbesítési sorrend nem garantált. A hasznos teher (payload) tartalmazza az e-mail-címet, ha az ismert, de a ChatLab e-mail-cím nélküli ügyfeleket is tud kezelni.

{
  "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 - az azonosító, amellyel az ügyfelet a saját CRM-rendszerében meglévő adatokhoz illesztheti. Az olyan névtelen látogatók esetében, akik soha nem adtak meg címet, ez az érték null, az esemény azonban náluk is aktiválódik - hagyja figyelmen kívül ezeket a kézbesítéseket, ha az integrációja e-mail-címre épül.
  • client - a ChatLab által az adott személyről tárolt kapcsolattartási rekord: email, name, phone, countryCode és ipAddress. Mindegyik kulcs mindig jelen van; az ismeretlen értékek mezői null értékűek.
  • clientSummary - a teljes profilszöveg egyszerű szövegként, nem diffként. Ez felülírja a korábbi összegzést, ezért hozzáfűzés helyett felülíró mentéssel tárolja.
  • A profil csak azoknál a botoknál épül újra, amelyeknél engedélyezve van a csevegési memória, és csak olyan beszélgetések esetén, amelyek elég hosszú ideig voltak inaktívak az összegzéshez - erre az eseményre percekkel a beszélgetés befejezése után számítson, nem pedig azonnal.

live_chat.requested

Akkor aktiválódik, amikor az AI átadja a beszélgetést a Live Chat funkciónak, vagy azért, mert a látogató emberi munkatársat kért, vagy mert a bot úgy döntött, hogy emberi segítségre van szükség.

{
  "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 - jelenleg mindig AI, mert az átadást mindig a bot live chat művelete kezdeményezi, még akkor is, ha a látogató kifejezetten szavakkal kéri azt. Kezelje nyílt enumként: felkészülve kezelje az ismeretlen értékeket ahelyett, hogy kizárólag az AI értékre hagyatkozna.
  • Ez az esemény az átadást kérő AI-műveletet fedi le, nem pedig a látogató általi live chat megnyitás összes lehetséges módját. Nem igazolja, hogy egy operátor ténylegesen csatlakozott is.

live_chat.started

Akkor aktiválódik, amikor a live chat munkamenet létrejön a látogató átadási űrlapjának elküldése után. Ez még azelőtt megtörténik, hogy egy operátor feltétlenül csatlakozna vagy válaszolna; ne tekintse az emberi bekapcsolódás bizonyítékának.

{
  "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": {}
}
  • A data szándékosan üres. Minden szükséges információ megtalálható a borítékban: a botId azonosítja a chatbotot, a conversationId / sessionId pedig a beszélgetéshez köti az eseményt. Előfordulhat, hogy korábbi live_chat.requested esemény nélkül érkezik, például ha a látogató a widget élő csevegési vezérlőjét használta.

live_chat.ended

Akkor aktiválódik, amikor a live chat munkamenet véget ér.

{
  "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 - a live chat munkamenet eltelt időtartama a munkamenet létrehozásától számítva, beleértve az operátorra való várakozási időt is. A mező kimarad abban a ritka esetben, ha a munkamenet anélkül fejeződik be, hogy valaha elindult volna.

ai_action.executed

Minden alkalommal aktiválódik, amikor a bot egy AI-műveletet hajt végre - legyen szó felügyelt integrációs hívásról vagy egyéni API-funkcióról. Ez egy nagy forgalmú esemény: egy aktív e-kereskedelmi bot naponta több száz műveletet is végrehajthat, és egyetlen látogatói interakció is több műveletet válthat ki. Iratkozzon fel rá egy dedikált végponton, vagy győződjön meg arról, hogy a fogadó oldala képes kezelni ezt a mennyiséget.

{
  "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 - a végrehajtott művelet neve az AI szemszögéből, például search_products egy kezelt integrációnál, vagy az a név, amelyet Ön adott egy egyéni API-műveletnek.
  • status - SUCCESS vagy ERROR.
  • durationMs - a művelet időtartama ezredmásodpercben. Hasznos a lassú integrációk észlelésére, még mielőtt a látogatók panaszkodnának miatta.
  • errorMessage - a hiba oka, amely csak akkor töltődik ki, ha a status értéke ERROR; egyébként null.

webhook.test

A Send sample event (Mintaesemény küldése) gomb küldi ki, amikor egyszerű kapcsolódási ellenőrzést hajt végre. Pontosan úgy van aláírva, mint egy valódi esemény.

{
  "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 - rögzített szöveg, mindig ugyanaz. A boríték mezői mintaértékeket hordoznak, ezért soha ne kezelje a webhook.test kézbesítést valódi adatként.
  • Ez az egyetlen eseménytípus, amelyre nem iratkozhat fel egy adott végponton: ezt igény szerint lehet elküldeni az adminisztrációs felületről, és mindig eléri azt a végpontot, amelyre rákattintott, függetlenül attól, hogy az milyen eseményeket figyel.

Biztonság: a kézbesítések ellenőrzése

Minden kézbesítés négy fejlécet tartalmaz:

Fejléc Érték
X-ChatLab-Signature sha256=<hex hmac> - a hasznos teher HMAC-SHA256 aláírása
X-ChatLab-Timestamp Unix időbélyeg másodpercben a kézbesítés aláírásának időpontjáról
X-ChatLab-Event Az esemény típusa, pl. lead.created
X-ChatLab-Delivery Egyedi kézbesítési azonosító, amely megegyezik a törzs eventId mezőjével

Az aláírás a {timestamp}.{rawBody} karakterláncon végzett HMAC-SHA256 számításként jön létre a végpont titkos kulcsának (secret) használatával, ahol a {timestamp} a X-ChatLab-Timestamp értéke, a {rawBody} pedig a kérés nyers, nem feldolgozott törzse. Mindig a nyers bájtok alapján végezze el az ellenőrzést - a feldolgozott JSON újra szerializálása megváltoztatja a bájtsorrendet, és érvényteleníti az aláírást.

A visszajátszásos támadások (replay attack) elleni védelem érdekében utasítsa el azokat a kézbesítéseket, amelyek X-ChatLab-Timestamp értéke régebbi 5 percnél.

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

Ha az ellenőrzés sikertelen, válaszoljon 401 kóddal, és dobja el a tartalmat. Soha ne dolgozzon fel ellenőrizetlen kézbesítéseket - bárki, aki felfedezi az Ön URL-jét, tetszőleges JSON-t küldhet rá POST kéréssel.

Kézbesítési viselkedés

Mielőtt webhookokra építene, ismerje meg ezeket a kézbesítési szabályokat:

  • Válaszoljon gyorsan. A végpontjának 3 másodpercen belül válaszolnia kell, ellenkező esetben a kézbesítés sikertelennek minősül. Ellenőrizze az aláírást, helyezze az eseményt tartósan várólistára, és igazolja vissza egy 2xx kóddal ezen az időkereten belül. A lassabb CRM-hívásokat és az üzleti feldolgozást aszinkron módon végezze el.
  • Fire-and-forget, legfeljebb egyszer. A megfelelő engedélyezett végpontok legfeljebb egy kézbesítési kísérletet kapnak - nincsenek újrapróbálkozások. A szüneteltetett végpontok és a nyitott áramkörök még ezt a kísérletet is letilthatják. Ha a végpontja nem működik, túllépi az időkorlátot, vagy nem 2xx státuszkódot ad vissza, az az esemény elvész, és nem lesz újra kézbesítve. A webhookok értesítések, nem pedig replikált adattárolók: használja a Bot Talk API beszélgetési végpontjait vagy a lead-exportokat a megőrzött adatok egyeztetésére, ahol ez támogatott. A Management API a bot beállításait és használati adatait fedi le, nem egy teljes eseményarchívumot. Egyes események ezeken a felületeken keresztül nem állíthatók helyre.
  • Áramköri megszakító (circuit breaker). Ha egymás után 5 sikertelen kézbesítés történik egy végpont/bot párosnál, a kézbesítések az adott párosnál 5 percre szünetelnek. A szünet alatt bekövetkező események elvesznek, és a kézbesítési naplóban CIRCUIT_OPEN bejegyzések jelennek meg a letiltott kísérletek azonosítására. A nyitott áramkör által kihagyott kézbesítések nem számítanak bele az automatikus letiltásba.
  • Automatikus letiltás. Az ellenőrzés a kézbesítés meghiúsulásának pillanatában fut le, soha nem időzítő alapján. Ha egy kézbesítés meghiúsul, és 7 napja nem volt sikeres kézbesítés - az utolsó sikertől vagy a végpont létrehozásának dátumától számítva, ha még soha nem volt sikeres -, a végpont kikapcsolásra kerül, és Ön e-mail értesítést kap. Bármely pillanatban érkező egyetlen 2xx válasz visszaállítja ezt az órát. Egy olyan végpont, amely nem kap forgalmat, soha nem kerül letiltásra, mert semmi sem hiúsul meg. Engedélyezze újra az Account settings (Fiókbeállítások) felületen, amint a fogadó oldalt kijavította; a hiba számlálója és az automatikus letiltás jelölése törlődik a visszakapcsoláskor, és a kikapcsolt állapotban elmulasztott események nem kerülnek utólagos pótlásra.
  • 410 Gone. Ha a végpontja HTTP 410 Gone kóddal válaszol, a ChatLab azonnal letiltja azt. Használja ezt egy végpont programozott leszerelésére a fogadó oldalról.
  • Idempotencia. Normál működés során nem várhatók ismétlődő kézbesítések, de ha a feldolgozásnak szigorúan idempotensnek kell lennie, szűrje ki a duplikátumokat az eventId alapján (ez az X-ChatLab-Delivery fejlécben is elérhető).

A kézbesítési sorrend nem garantált. Tárolja az eseményazonosítót, és tegye az üzleti feldolgozást idempotenssé. Gondoskodjon saját adatmegőrzési és hozzáférés-vezérlési szabályairól a webhookok adattartalmaira (payload) vonatkozóan, amelyek személyes adatokat és fájlletöltési hivatkozásokat is tartalmazhatnak.

Az aláírási példák a Node.js crypto és a PHP hash_equals függvényét használják. Rögzítse a nyers kéréstörzset (raw request body), mielőtt elemezné azt.

Korlátok

  • Fiókonként legfeljebb 10 webhook-végpont.
  • A kézbesítési napló megőrzési ideje: 14 nap. A régebbi bejegyzések automatikusan törlődnek.

Kapcsolódó cikkek