Webhooks
Webhooks let you receive real-time notifications when events happen in your chatbot. Connect to your CRM, trigger automations, or build custom integrations.
Setting Up Webhooks
- Go to Settings → Webhooks in your dashboard
- Click Add Webhook
- Enter your webhook URL (must be HTTPS)
- Select which events you want to receive
- Click Save
Webhook Events
You can subscribe to any or all of these events:
| Event | Description |
|---|---|
| conversation_started | A visitor opened the chat widget |
| message_received | A visitor sent a message to the bot |
| bot_response | The bot sent a response to the visitor |
Payload Format
All webhook payloads are sent as JSON with the following structure:
{
"event": "message_received",
"timestamp": "2025-01-22T14:30:00.000Z",
"bot_id": "cmkms0wt5000i93y1udty4dy0",
"conversation_id": "conv_abc123xyz789",
"data": {
"message": "What are your business hours?",
"visitor_id": "v_12345",
"metadata": {
"page_url": "https://yoursite.com/contact",
"user_agent": "Mozilla/5.0..."
}
}
}{
"event": "bot_response",
"timestamp": "2025-01-22T14:30:01.234Z",
"bot_id": "cmkms0wt5000i93y1udty4dy0",
"conversation_id": "conv_abc123xyz789",
"data": {
"message": "We're open Monday through Friday, 9 AM to 6 PM Eastern Time.",
"visitor_id": "v_12345",
"sources_used": [
{
"title": "Contact Us",
"url": "https://yoursite.com/contact"
}
]
}
}Signature Verification
Every webhook request includes a signature header so you can verify it came from SiteAnswerAI. Always verify signatures in production to prevent spoofed requests.
Signature Header
The signature is sent in the X-SiteAnswerAI-Signature header as an HMAC SHA-256 hash of the request body.
POST /your-webhook-endpoint HTTP/1.1
Host: yourserver.com
Content-Type: application/json
X-SiteAnswerAI-Signature: sha256=a1b2c3d4e5f6...Verification Examples
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// In your webhook handler:
app.post('/webhook', (req, res) => {
const signature = req.headers['x-siteanswerai-signature'];
const payload = JSON.stringify(req.body);
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process the webhook...
console.log('Event:', req.body.event);
res.status(200).send('OK');
});import hmac
import hashlib
def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = 'sha256=' + hmac.new(
secret.encode('utf-8'),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
# In your webhook handler (Flask example):
@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-SiteAnswerAI-Signature', '')
payload = request.get_data()
if not verify_webhook_signature(payload, signature, WEBHOOK_SECRET):
return 'Invalid signature', 401
data = request.get_json()
print(f"Event: {data['event']}")
return 'OK', 200<?php
function verifyWebhookSignature($payload, $signature, $secret) {
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
return hash_equals($expected, $signature);
}
// In your webhook handler:
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_SITEANSWERAI_SIGNATURE'] ?? '';
if (!verifyWebhookSignature($payload, $signature, WEBHOOK_SECRET)) {
http_response_code(401);
exit('Invalid signature');
}
$data = json_decode($payload, true);
error_log('Event: ' . $data['event']);
http_response_code(200);
echo 'OK';Automatic Retries
If your webhook endpoint returns an error (4xx or 5xx status code) or times out, we'll automatically retry the delivery:
- Retry 1: After 1 minute
- Retry 2: After 5 minutes
- Retry 3: After 30 minutes
After 3 failed attempts, the webhook is marked as failed. You can see failed deliveries in the webhook logs.
Delivery Logs
Every webhook delivery is logged so you can debug issues. Find the logs at:
- Go to Settings → Webhooks
- Click on a webhook to see its details
- Click View Logs
Each log entry shows the timestamp, event type, HTTP status code, and response time. You can also see the full request payload and response body for debugging.
Best Practices
- Always verify signatures - Don't skip this in production!
- Respond quickly - Return a 200 status within 5 seconds. Do heavy processing asynchronously.
- Handle duplicates - Webhooks may be delivered more than once. Use the conversation_id to deduplicate.
- Use HTTPS - We only send webhooks to secure endpoints.