Skip to content

Webhook System - Documentation

Overview

The webhook system allows you to configure HTTP endpoints that will be called automatically when specific events occur in your ConnectGain system. This enables you to integrate with external systems, trigger automations, or build custom workflows.

Available Events (17 Total)

Contact Events (3)

  • contact.created - Fired when a new contact is created
  • contact.updated - Fired when a contact is updated
  • contact.assigned - Fired when a contact is assigned to someone

Deal/Lead Events (4)

  • deal.created - Fired when a new deal/lead is created
  • deal.updated - Fired when a deal is updated
  • deal.stage.changed - Fired when a deal moves to a different pipeline stage
  • deal.assigned - Fired when a deal is assigned to someone

Conversation Events (3)

  • conversation.created - Fired when a new conversation is created
  • conversation.assigned - Fired when a conversation is assigned
  • conversation.status.changed - Fired when conversation status changes (OPEN/CLOSED)

Message Events (5)

  • message.received - Fired when a new message is received
  • message.sent - Fired when a message is sent
  • message.delivered - Fired when a sent message is delivered to the recipient
  • message.read - Fired when a sent message is read by the recipient
  • message.failed - Fired when a message fails to send

Broadcast Events (1)

  • broadcast.response - Fired when a contact replies to a broadcast/campaign message

Meeting Events (1)

  • zoom.recording.completed - Fired when a Zoom cloud recording finishes processing

HTTP Method: POST

All webhooks are sent as HTTP POST requests with JSON payload.

⚠️ Your endpoint must accept POST requests (not GET).

The webhook dispatcher sends: - Method: POST - Content-Type: application/json - Body: JSON payload with event data

Event Payload Format

All webhook calls follow this format:

{
 "event": "contact.created",
 "timestamp": "2024-01-15T10:30:00Z",
 "data": {
 "id": "uuid-here",
 "first_name": "John",
 "last_name": "Doe",
 "organization_id": "org-uuid",
 //... other fields specific to the event
 }
}

Webhook Signature

If you provide a secret when configuring your webhook, requests will include an HMAC SHA-256 signature:

Headers: - X-Webhook-Event: The event type - X-Webhook-Timestamp: ISO timestamp - X-Webhook-Signature: HMAC signature (if secret is set)

Verification: 1. Get the X-Webhook-Signature header 2. Compute HMAC SHA-256 of the request body using your secret 3. Compare the signatures (use constant-time comparison)

Configuration

Webhooks are configured via the Settings page or through the API.

Using the API

import { createWebhookConfig } from '@/lib/webhook';

await createWebhookConfig({
 name: 'My Integration',
 url: 'https://example.com/webhooks',
 events: ['contact.created', 'deal.stage.changed'],
 secret: 'your-hmac-secret', // Optional
 is_active: true
});

Configuration Fields

  • name: Human-readable name for the webhook
  • url: Endpoint URL to receive webhook calls
  • events: Array of event types to subscribe to
  • secret: HMAC secret for signature verification (optional)
  • is_active: Whether the webhook is active

Example Implementations

Node.js Example

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

const app = express;
app.use(express.json); // Parse JSON body

app.post('/webhooks', (req, res) => {
 console.log('Received webhook:', req.method, req.headers);
 const signature = req.headers['x-webhook-signature'];
 const secret = 'your-secret-here';

 // Verify signature
 const hmac = crypto.createHmac('sha256', secret);
 hmac.update(JSON.stringify(req.body));
 const computedSignature = hmac.digest('hex');

 if (signature !== computedSignature) {
 return res.status(401).send('Invalid signature');
 }

 const { event, data } = req.body;

 // Handle the event
 switch (event) {
 case 'contact.created':
 console.log('New contact:', data);
 break;
 case 'deal.stage.changed':
 console.log('Deal stage changed:', data);
 break;
 }

 res.status(200).send('OK');
});

Python Example

import hmac
import hashlib
from flask import Flask, request

app = Flask(__name__)

@app.route('/webhooks', methods=['POST'])
def webhook:
 signature = request.headers.get('X-Webhook-Signature')
 secret = b'your-secret-here'

 # Verify signature
 computed = hmac.new(secret, request.data, hashlib.sha256).hexdigest

 if not hmac.compare_digest(computed, signature):
 return 'Invalid signature', 401

 event = request.json['event']
 data = request.json['data']

 # Handle event
 if event == 'contact.created':
 print(f'New contact: {data}')
 elif event == 'deal.stage.changed':
 print(f'Deal stage changed: {data}')

 return 'OK', 200

Webhook Logs

All webhook delivery attempts are logged in the webhook_logs table, including: - Event type and payload - Response status code - Response body - Error messages (if any)

View logs in Settings > Webhooks > Logs

Testing Webhooks

You can test your webhook configuration by sending a test event:

import { testWebhook } from '@/lib/webhook';

await testWebhook('webhook-id');

This sends a test event to your configured endpoint.

Best Practices

  1. Always verify signatures - Use the HMAC signature to verify webhook authenticity
  2. Use HTTPS - Never send webhooks over unencrypted connections
  3. Respond quickly - Your endpoint should respond within 5 seconds
  4. Idempotent handlers - Webhooks may be retried, handle duplicate events gracefully
  5. Log deliveries - Keep your own logs of webhook deliveries
  6. Handle failures - Webhooks are fire-and-forget, but logs show delivery status

Rate Limits

Currently, webhooks are sent synchronously. If you have high event volumes, consider: - Batch processing events - Using queueing system - Filtering events you actually need

Troubleshooting

Webhooks not being called: 1. Check that webhook is is_active: true 2. Verify the endpoint URL is correct and accessible 3. Check webhook logs for errors

Invalid signature: 1. Ensure you're using the same secret 2. Verify you're computing HMAC-SHA256 correctly 3. Check that request body matches what you're hashing

Events not firing: 1. Verify the event types are subscribed in your webhook config 2. Check that the action triggers the event (e.g., creates/updates records)

Next Steps

After deploying this system, you can: 1. Configure webhooks in Settings page 2. Monitor webhook delivery in logs 3. Test with sample events 4. Integrate with external systems

API Reference

See the Webhooks Feature guide and Enhanced Payload reference for the complete event catalogue and payload schemas.