Dashboard
Back to Documentation

Webhooks

Receive real-time notifications when events occur in your chatbot using secure webhooks.

Overview

Webhooks allow your application to receive real-time notifications when specific events occur in your chatbot. When an event is triggered, Pollybot will send an HTTP POST request to your webhook URL with details about the event.

Key Features:

  • HMAC SHA256 signatures for payload verification
  • Automatic retries with exponential backoff
  • Delivery tracking and monitoring
  • Event filtering - only receive events you care about
  • 30-second timeout for reliable delivery

Security

All webhook payloads are signed with HMAC SHA256 using a secret key unique to each webhook. You should always verify the signature to ensure the request came from Pollybot.

Signature Verification

The signature is sent in the X-Webhook-Signature header in the format sha256=<signature>

Node.js Example:
const crypto = require('crypto');

function verifyWebhookSignature(body, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  
  const receivedSignature = signature.replace('sha256=', '');
  
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature, 'hex'),
    Buffer.from(receivedSignature, 'hex')
  );
}

// Usage in Express.js
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const secret = 'your-webhook-secret';
  
  if (!verifyWebhookSignature(req.body, signature, secret)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process the webhook payload
  const payload = JSON.parse(req.body);
  res.status(200).send('OK');
});
Python Example:
import hmac
import hashlib
from flask import Flask, request

app = Flask(__name__)

def verify_webhook_signature(body, signature, secret):
    expected_signature = hmac.new(
        secret.encode('utf-8'),
        body,
        hashlib.sha256
    ).hexdigest()
    
    received_signature = signature.replace('sha256=', '')
    
    return hmac.compare_digest(expected_signature, received_signature)

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Webhook-Signature')
    secret = 'your-webhook-secret'
    
    if not verify_webhook_signature(request.data, signature, secret):
        return 'Invalid signature', 401
    
    # Process the webhook payload
    payload = request.json
    print(f"Received event: {payload['event']}")
    
    return 'OK', 200

Available Events

LEAD_CREATED

Triggered when a new lead is created for your chatbot.

Payload Structure:
{
  "event": "LEAD_CREATED",
  "timestamp": 1699123456,
  "data": {
    "id": "clp123abc456",
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "+1234567890",
    "company": "Acme Corp",
    "message": "Interested in your services",
    "preferredMethod": "email",
    "urgency": "medium",
    "source": "chat_widget",
    "status": "NEW",
    "priority": "MEDIUM",
    "tags": ["website", "inquiry"],
    "customFields": {
      "budget": "10000",
      "timeline": "Q1 2024"
    },
    "chatbotId": "clp123chatbot456",
    "createdAt": "2023-11-04T15:30:56.789Z",
    "updatedAt": "2023-11-04T15:30:56.789Z"
  },
  "chatbotId": "clp123chatbot456"
}
More Events Coming Soon

Additional events like LEAD_UPDATED, CONVERSATION_STARTED, and CONVERSATION_RESOLVED will be available in future releases.

API Endpoints

Authentication Required

All webhook API endpoints require session authentication. You must be logged in to your Pollybot account and own the chatbot to access these endpoints. API keys are not currently supported - use session cookies from your logged-in browser session.

GET/api/v1/chatbots/{chatbotId}/webhooks

List all webhooks for a chatbot.

Response:
{
  "webhooks": [
    {
      "id": "webhook_123",
      "name": "Lead Notifications",
      "url": "https://yourapp.com/webhooks/leads",
      "eventTypes": ["LEAD_CREATED"],
      "isActive": true,
      "maxRetries": 3,
      "retryDelay": 1000,
      "successCount": 25,
      "failureCount": 2,
      "lastTriggeredAt": "2023-11-04T15:30:56.789Z",
      "lastSuccessAt": "2023-11-04T15:30:56.789Z",
      "createdAt": "2023-11-01T10:00:00.000Z",
      "updatedAt": "2023-11-04T15:30:56.789Z"
    }
  ],
  "total": 1
}
POST/api/v1/chatbots/{chatbotId}/webhooks

Create a new webhook.

Request Body:
{
  "name": "Lead Notifications",
  "url": "https://yourapp.com/webhooks/leads",
  "eventTypes": ["LEAD_CREATED"],
  "maxRetries": 3,
  "retryDelay": 1000
}
Response:
{
  "message": "Webhook created successfully",
  "webhook": {
    "id": "webhook_123",
    "name": "Lead Notifications",
    "url": "https://yourapp.com/webhooks/leads",
    "secret": "whsec_1234567890abcdef...",
    "eventTypes": ["LEAD_CREATED"],
    "isActive": true,
    "maxRetries": 3,
    "retryDelay": 1000,
    "successCount": 0,
    "failureCount": 0,
    "createdAt": "2023-11-04T15:30:56.789Z",
    "updatedAt": "2023-11-04T15:30:56.789Z"
  },
  "security": {
    "note": "Store the secret securely. It will not be shown again.",
    "headerName": "X-Webhook-Signature",
    "format": "sha256=<hmac_signature>"
  }
}
PUT/api/v1/chatbots/{chatbotId}/webhooks/{id}

Update an existing webhook.

Request Body (partial updates supported):
{
  "name": "Updated Lead Notifications",
  "isActive": false
}
DELETE/api/v1/chatbots/{chatbotId}/webhooks/{id}

Delete a webhook.

Response:
{
  "message": "Webhook deleted successfully"
}

Complete Code Examples

Creating a Webhook

curl -X POST https://your-domain.com/api/v1/chatbots/your-chatbot-id/webhooks \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-session-token" \
  -d '{
    "name": "Lead Notifications",
    "url": "https://yourapp.com/webhooks/leads",
    "eventTypes": ["LEAD_CREATED"],
    "maxRetries": 3,
    "retryDelay": 1000
  }'

Handling Webhooks in Express.js

const express = require('express');
const crypto = require('crypto');

const app = express();

// Use raw body parser for webhook signature verification
app.use('/webhooks', express.raw({type: 'application/json'}));

function verifyWebhookSignature(body, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  
  const receivedSignature = signature.replace('sha256=', '');
  
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature, 'hex'),
    Buffer.from(receivedSignature, 'hex')
  );
}

app.post('/webhooks/pollybot', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const webhookSecret = process.env.POLLYBOT_WEBHOOK_SECRET;
  
  // Verify the signature
  if (!verifyWebhookSignature(req.body, signature, webhookSecret)) {
    console.error('Invalid webhook signature');
    return res.status(401).send('Invalid signature');
  }
  
  // Parse the payload
  const payload = JSON.parse(req.body);
  // Handle different event types
  switch (payload.event) {
    case 'LEAD_CREATED':
      handleLeadCreated(payload.data);
      break;
    default:
  }
  
  // Always respond with 200 to acknowledge receipt
  res.status(200).send('OK');
});

function handleLeadCreated(lead) {
  // Add your business logic here:
  // - Send notification email
  // - Create record in CRM
  // - Trigger follow-up workflow
  // - etc.
}

app.listen(3000, () => {
});

Testing Webhooks

Before deploying webhooks to production, you can test them using our built-in test endpoint that logs all incoming webhook data.

🧪 Test Endpoint

Use this endpoint to see exactly what data your webhooks will receive:

# Test webhook URL (use in your webhook settings)
http://localhost:3000/api/test-webhook

# Or for production
https://your-domain.com/api/test-webhook

How to Test:

  1. Create a webhook using the test URL above
  2. Trigger a lead creation in your chatbot
  3. Check your server console/logs for detailed webhook data
  4. Verify the payload structure and signature
  5. Update your webhook URL to your production endpoint

Console Output Example:

🎣 WEBHOOK TEST RECEIVED!
==========================================
⏰ Time: 2025-10-10T15:30:45.123Z
📦 Payload: {
  "event": "LEAD_CREATED",
  "data": {
    "id": "lead_123",
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "+1234567890",
    "chatbotId": "bot_456"
  }
}
🎯 LEAD INFORMATION:
   Name: John Doe
   Email: john@example.com
   Phone: +1234567890
🔐 SIGNATURE INFO:
   Signature: sha256=abc123...
   Timestamp: 1728573045
==========================================

Best Practices

🔒 Always Verify Signatures

Never trust webhook payloads without verifying the HMAC signature. This prevents malicious requests from affecting your system.

⚡ Respond Quickly

Return a 200 status code as quickly as possible. Perform heavy processing asynchronously after acknowledging the webhook.

🔄 Handle Retries Gracefully

Implement idempotency in your webhook handlers. The same event might be delivered multiple times due to retries.

📊 Monitor Webhook Health

Check the webhook delivery statistics in your chatbot settings to ensure webhooks are being delivered successfully.

🚨 Handle Failures

If your webhook endpoint is down, events will be retried automatically. Consider implementing a fallback mechanism or alerting system.

    PollyBot.ai - Smart Conversations, Seamless Automation