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.

On this page:

Available Events (29 Total)

These are the events selectable when creating a webhook in Settings → Webhooks.

Contact Events (5)

  • 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
  • contact.tag.updated - Fired when a contact's tags change
  • contact.lifecycle.updated - Fired when a contact moves to a different lifecycle stage

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 (3)

  • message.received - Fired when a new message is received
  • message.sent - Fired when a message is sent
  • message.failed - Fired when a message fails to send

message.delivered and message.read are not subscribable. The dispatcher recognises the names, but they are not offered in the Settings → Webhooks picker, so no webhook can be configured for them. Track delivery/read state by polling the message row's status instead.

Broadcast Events (1)

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

Task Events (4)

  • task.created - Fired when a task is created
  • task.updated - Fired when a task is updated
  • task.completed - Fired when a task is completed
  • task.overdue - Fired when a task passes its due date

Comment Events (2)

  • comment.created - Fired when an internal comment is added
  • fb.comment.received - Fired when a comment is left on a connected Facebook post

Call & Meeting Events (5)

  • call.ended - Fired when a call finishes
  • call.processed - Fired when AI analysis of a call completes
  • meeting.processed - Fired when AI analysis of a meeting completes
  • minutes.generated - Fired when Minutes of Meeting are generated
  • zoom.recording.completed - Fired when a Zoom cloud recording finishes processing

Approval Events (2)

  • approval.requested - Fired when an approval request is raised
  • approval.decided - Fired when an approval is approved or rejected

Inbound flow triggers (separate catalogue)

These are not outbound webhook subscriptions — they start a bot flow and are chosen in the flow builder's trigger node:

  • webhook.received - An inbound HTTP POST to your flow's webhook URL A given contact starts a flow this way at most once per day (your organisation's timezone); further POSTs for the same contact that day return 200 with "skipped": true and "reason": "once_per_contact_per_day". Switch it off per flow on the Trigger node if needed; Channel Simulator runs are never limited.
  • manual.shortcut - An agent launched the flow from the inbox
  • comment.received - A comment on a Facebook / Instagram post
  • voice_call.requested - A voice call was requested (Simulator)

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 - Failed deliveries are logged and routed to a dead-letter queue, then retried automatically; use the delivery logs to monitor status

Rate Limits

Webhooks are dispatched in near real time as events occur. If you have high event volumes, consider:

  • Batch processing events
  • Using a 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.

See also


ConnectGain — omnichannel inbox, CRM & automation for WhatsApp, Messenger, Instagram, Telegram and more. Open the app · Docs home