Documentation Index
Fetch the complete documentation index at: https://docs.insitechat.ai/llms.txt
Use this file to discover all available pages before exploring further.
InsiteChat webhooks fire HMAC-signed HTTP POST requests to URLs you configure whenever specific events happen on a chatbot. Use webhooks to push leads into your CRM, mirror conversations into a data warehouse, or trigger Zapier / Make.com / n8n workflows.
Set up webhooks in Dashboard → your chatbot → Webhooks → Add Webhook. Pick the events you care about, set a destination URL, and InsiteChat does the rest.
Events
| Event | When it fires |
|---|
lead.captured | A visitor submitted the lead form |
conversation.started | The first message of a brand-new conversation |
message.received | Every visitor message (after conversation.started on the first turn) |
conversation.escalated | The visitor (or smart-intent / CTA) requested human help — fires once per conversation |
Common Envelope
Every event uses the same outer envelope. The event-specific payload lives under data:
{
"event": "lead.captured",
"chatbot_id": "0a1b2c3d-4e5f-6789-abcd-ef0123456789",
"timestamp": "2026-04-23T12:00:00.123456+00:00",
"data": { /* event-specific shape — see below */ }
}
| Field | Type | Description |
|---|
event | string | Event name (one of the four above). |
chatbot_id | UUID | The chatbot the event belongs to. |
timestamp | string | ISO 8601 timestamp of when the event was queued. |
data | object | Event-specific payload. See the per-event shapes below. |
Per-Event Payloads
lead.captured
{
"event": "lead.captured",
"chatbot_id": "0a1b2c3d-...",
"timestamp": "2026-04-23T12:00:00.123456+00:00",
"data": {
"lead_id": "ab12cd34-5e6f-7890-abcd-ef1234567890",
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+1234567890",
"custom_data": { "company": "Acme Corp", "role": "VP Engineering" }
}
}
| Field | Type | Notes |
|---|
lead_id | UUID | The Lead record ID. |
name / email / phone | string | May be empty strings if the form didn’t collect them or the visitor skipped the field. |
custom_data | object | Any custom fields configured on the lead form, keyed by field name. Empty object if no custom fields. |
conversation.started
{
"event": "conversation.started",
"chatbot_id": "0a1b2c3d-...",
"timestamp": "2026-04-23T12:00:01.123456+00:00",
"data": {
"conversation_id": "f1e2d3c4-...",
"session_id": "embed-abc123",
"source": "embed"
}
}
| Field | Type | Notes |
|---|
conversation_id | UUID | The Conversation record ID. |
session_id | string | Channel-prefixed: embed-… (web widget), wa_… (WhatsApp), tg_… (Telegram), or api-… (REST API). |
source | string | Origin channel: embed, whatsapp, telegram, or api. |
message.received
{
"event": "message.received",
"chatbot_id": "0a1b2c3d-...",
"timestamp": "2026-04-23T12:00:01.456789+00:00",
"data": {
"conversation_id": "f1e2d3c4-...",
"session_id": "embed-abc123",
"content": "Hi! Do you ship to Canada?",
"source": "embed"
}
}
| Field | Type | Notes |
|---|
conversation_id | UUID | The Conversation record ID. |
session_id | string | Same channel-prefixed format as conversation.started. |
content | string | The visitor’s raw message text. |
source | string | Origin channel. |
conversation.escalated
Fires once per conversation the first time the visitor (or a smart-intent / CTA / agent rule) flips the conversation into “needs a human” mode. Subsequent triggers on an already-escalated conversation are no-ops.
{
"event": "conversation.escalated",
"chatbot_id": "0a1b2c3d-...",
"timestamp": "2026-04-23T12:00:30.123456+00:00",
"data": {
"conversation_id": "f1e2d3c4-...",
"session_id": "embed-abc123",
"channel": "web",
"escalated_at": "2026-04-23T12:00:30.000000+00:00"
}
}
| Field | Type | Notes |
|---|
conversation_id | UUID | The Conversation record ID. |
session_id | string | Channel-prefixed: embed-…, wa_…, tg_…. |
channel | string | Inferred from session_id prefix: web, whatsapp, telegram, or unknown. |
escalated_at | string | ISO 8601 timestamp of the escalation. |
Web escalations may include an additional message_count field; WhatsApp / Telegram escalations don’t. Treat any field beyond the four above as optional and channel-specific.
Every webhook request carries:
| Header | Value |
|---|
Content-Type | application/json |
X-InsiteChat-Signature | HMAC-SHA256 of the raw request body, hex-encoded — use this to verify authenticity |
X-InsiteChat-Event | The event name (also present in the body’s event field) — convenient for fast routing |
User-Agent | InsiteChat-Webhook/1.0 |
Signature Verification
Every payload is signed with HMAC-SHA256 using the per-webhook secret you’ll see when you create or view the webhook in the dashboard. Always verify the signature before trusting the body.
Python
import hmac
import hashlib
def verify_signature(payload_bytes: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), payload_bytes, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
Node.js
const crypto = require('crypto');
function verifySignature(payloadBuffer, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payloadBuffer)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature),
);
}
Verify against the raw request bytes, not the parsed JSON. Re-serializing changes whitespace and breaks the signature. Most frameworks expose a req.rawBody or request.body() (bytes) helper.
Retry Policy
A delivery is failed if the response is non-2xx or the request times out (10 seconds). Failed deliveries are retried up to 3 times with fixed backoff:
| Attempt | Delay after previous failure |
|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 15 minutes |
After the 3rd failed retry the delivery is marked permanently failed.
Delivery Log
Every webhook attempt is logged. Open Dashboard → your chatbot → Webhooks, click Delivery log on any webhook to see status code, response body, and retry attempts.