synaptiq Live demo
  • How It Works
  • Pricing
  • Blog
  • FAQ
Log InStart Free Pilot
synaptiq

AI-powered sales agent that qualifies leads and books meetings autonomously.

Product
  • How It Works
  • Pricing
  • FAQ
Resources
  • Blog
  • Docs
  • API Reference
  • Embed Guide
Legal
  • Privacy Policy
  • Terms of Service
  • Cookie Policy
2026 Synaptiq. All rights reserved.
Documentation
  • Quick Start Guide
  • Embed the Widget on Your Site
  • Configure Your AI Agent
  • Upload Your Knowledge Base
  • Test Your First Conversation
  • Understanding Your Dashboard Metrics
  • Managing Leads and Conversations
  • Using the Conversion Funnel
  • Exporting Data
  • Choosing a Theme
  • Customizing the Chat Icon
  • Position and Sizing Options
  • Custom CSS Overrides
  • Choosing an Industry Template
  • Customizing Qualification Criteria
  • Writing Effective Greeting Messages
  • Objection Handling Best Practices
  • Uploading Documents
  • Supported File Formats
  • How the AI Uses Your Documents
  • Testing Queries Against Your Knowledge Base
  • Calendar Setup (Cal.com / Calendly)
  • CRM Sync (HubSpot)
  • Webhook Configuration
  • Zapier / Make Integration
  • Authentication
  • Chat API
  • Leads API
  • Conversations API
  • Analytics API
  • Webhooks
  • Rate Limits and Error Codes
  • Code Examples
  • Plans and Pricing
  • Usage Metering
  • Managing Your Subscription
  • Invoices and Receipts
Docs/API Reference/Webhooks

Webhooks

Receive real-time event notifications from Synaptiq via HTTP webhooks.

Webhooks

Webhooks allow your application to receive real-time notifications when events occur in Synaptiq. Instead of polling the API, Synaptiq sends an HTTP POST request to your configured endpoint whenever a subscribed event fires.

Setting Up Webhooks

  1. Navigate to Settings > Webhooks in your Synaptiq Dashboard.
  2. Click Add Endpoint.
  3. Enter your HTTPS endpoint URL.
  4. Select the events you want to subscribe to.
  5. Click Create. Synaptiq will send a test ping to verify your endpoint.

You can also manage webhooks via the API:

curl -X POST https://synaptiqintel.com/api/v1/webhooks \
  -H "Authorization: Bearer sk_live_abc123def456ghi789jkl012mno345" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/synaptiq",
    "events": ["lead.created", "lead.qualified", "conversation.completed"],
    "secret": "whsec_your_signing_secret_here"
  }'
{
  "id": "wh_01HQ9AAA1BBB2CCC3DDD4EEE5F",
  "url": "https://your-app.com/webhooks/synaptiq",
  "events": ["lead.created", "lead.qualified", "conversation.completed"],
  "status": "active",
  "createdAt": "2026-04-05T16:00:00.000Z"
}

Event Types

| Event | Description | |-----------------------------|---------------------------------------------------------------| | lead.created | A new lead was captured from a conversation or the API. | | lead.updated | A lead's fields were modified (status, score, tags, etc.). | | lead.qualified | A lead's status changed to qualified. | | lead.converted | A lead's status changed to converted. | | lead.deleted | A lead was deleted. | | conversation.started | A new AI conversation was initiated. | | conversation.completed | A conversation was closed or expired. | | conversation.handoff | A conversation was handed off to a human agent. | | message.received | A new visitor message was received in a conversation. | | message.sent | The AI agent sent a response message. | | intent.high_value | A high-value buying intent was detected in a conversation. |

Payload Structure

Every webhook delivery follows a consistent envelope format:

{
  "id": "evt_01HQAAA1BBB2CCC3DDD4EEE5FF",
  "type": "lead.created",
  "apiVersion": "2026-01-15",
  "createdAt": "2026-04-05T16:05:00.000Z",
  "data": {
    // Event-specific payload (see examples below)
  }
}

Envelope Fields

| Field | Type | Description | |--------------|--------|------------------------------------------------------| | id | string | Unique event ID. Use for idempotency checks. | | type | string | The event type that triggered the webhook. | | apiVersion | string | The API version used to format the payload. | | createdAt | string | ISO 8601 timestamp of when the event occurred. | | data | object | The event payload. Structure varies by event type. |

Delivery Headers

Each webhook request includes the following headers:

| Header | Description | |-------------------------|----------------------------------------------------------------| | Content-Type | Always application/json. | | User-Agent | Synaptiq-Webhooks/1.0. | | X-Synaptiq-Event | The event type (e.g., lead.created). | | X-Synaptiq-Delivery | A unique delivery ID for this attempt. | | X-Synaptiq-Timestamp | Unix timestamp (seconds) of when the request was sent. | | X-Synaptiq-Signature | HMAC-SHA256 signature for verifying payload authenticity. |

Verifying Signatures

Every webhook delivery is signed with your webhook secret using HMAC-SHA256. Always verify the signature before processing a webhook to ensure the request is genuinely from Synaptiq.

The signature is computed over the concatenation of the timestamp and the raw request body:

signature = HMAC-SHA256(secret, timestamp + "." + body)

Node.js Verification Example

const crypto = require("crypto");

function verifyWebhookSignature(req, secret) {
  const timestamp = req.headers["x-synaptiq-timestamp"];
  const signature = req.headers["x-synaptiq-signature"];
  const body = req.rawBody; // raw request body as string

  // Reject requests older than 5 minutes to prevent replay attacks
  const currentTime = Math.floor(Date.now() / 1000);
  if (Math.abs(currentTime - parseInt(timestamp)) > 300) {
    throw new Error("Webhook timestamp too old. Possible replay attack.");
  }

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${body}`)
    .digest("hex");

  const trusted = Buffer.from(expected, "hex");
  const received = Buffer.from(signature, "hex");

  if (!crypto.timingSafeEqual(trusted, received)) {
    throw new Error("Invalid webhook signature.");
  }

  return true;
}

Python Verification Example

import hmac
import hashlib
import time

def verify_webhook(payload_body, timestamp, signature, secret):
    # Reject old timestamps (5-minute tolerance)
    current_time = int(time.time())
    if abs(current_time - int(timestamp)) > 300:
        raise ValueError("Webhook timestamp too old")

    expected = hmac.new(
        secret.encode("utf-8"),
        f"{timestamp}.{payload_body}".encode("utf-8"),
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(expected, signature):
        raise ValueError("Invalid webhook signature")

    return True

Event Payload Examples

lead.created

{
  "id": "evt_01HQAAA1BBB2CCC3DDD4EEE5FF",
  "type": "lead.created",
  "apiVersion": "2026-01-15",
  "createdAt": "2026-04-05T16:05:00.000Z",
  "data": {
    "lead": {
      "id": "lead_01HQ3VXK9BWMN4F6T2P8R5GYSC",
      "email": "sarah.chen@acmecorp.com",
      "name": "Sarah Chen",
      "company": "Acme Corp",
      "status": "new",
      "score": 42,
      "source": "chat",
      "createdAt": "2026-04-05T16:05:00.000Z"
    },
    "conversationId": "conv_01HQ7ABC2DEF3GHI4JKL5MNO6P"
  }
}

lead.qualified

{
  "id": "evt_01HQBBB2CCC3DDD4EEE5FFF6GG",
  "type": "lead.qualified",
  "apiVersion": "2026-01-15",
  "createdAt": "2026-04-05T16:10:00.000Z",
  "data": {
    "lead": {
      "id": "lead_01HQ3VXK9BWMN4F6T2P8R5GYSC",
      "email": "sarah.chen@acmecorp.com",
      "name": "Sarah Chen",
      "company": "Acme Corp",
      "status": "qualified",
      "score": 87,
      "previousStatus": "new"
    },
    "qualificationReason": "High intent signals: pricing inquiry, demo request, team size confirmed (50+ seats)."
  }
}

conversation.handoff

{
  "id": "evt_01HQCCC3DDD4EEE5FFF6GGG7HH",
  "type": "conversation.handoff",
  "apiVersion": "2026-01-15",
  "createdAt": "2026-04-05T16:15:00.000Z",
  "data": {
    "conversation": {
      "id": "conv_01HQ7ABC2DEF3GHI4JKL5MNO6P",
      "leadId": "lead_01HQ3VXK9BWMN4F6T2P8R5GYSC",
      "messageCount": 14,
      "status": "handed_off"
    },
    "handoff": {
      "reason": "enterprise_inquiry",
      "priority": "high",
      "suggestedTeam": "enterprise-sales",
      "context": "Visitor is CTO of 50-person SaaS company comparing with Drift. Budget confirmed at $5-10k/mo."
    }
  }
}

intent.high_value

{
  "id": "evt_01HQDDD4EEE5FFF6GGG7HHH8II",
  "type": "intent.high_value",
  "apiVersion": "2026-01-15",
  "createdAt": "2026-04-05T16:20:00.000Z",
  "data": {
    "leadId": "lead_01HQ6JKL8MWPN3D5R7S9T1UVWX",
    "conversationId": "conv_01HQ7QRS8TUV9WXY0ZAB1CDE2F",
    "intent": "purchase_ready",
    "confidence": 0.92,
    "signals": [
      "Asked about contract terms",
      "Confirmed budget authority",
      "Requested implementation timeline"
    ],
    "estimatedDealSize": 18000
  }
}

Retry Behavior

If your endpoint returns a non-2xx status code or fails to respond within 30 seconds, Synaptiq retries the delivery with exponential backoff:

| Attempt | Delay After Failure | |---------|---------------------| | 1 | Immediate | | 2 | 1 minute | | 3 | 5 minutes | | 4 | 30 minutes | | 5 | 2 hours | | 6 | 12 hours | | 7 (final) | 24 hours |

After 7 failed attempts, the delivery is marked as failed. You can view failed deliveries and manually retry them from the Webhooks page in your dashboard.

Best Practices

  • Respond quickly. Return a 200 OK as soon as you receive the webhook. Process the event asynchronously.
  • Use idempotency. Store the event id and skip duplicates. Retries may deliver the same event more than once.
  • Verify signatures. Always validate X-Synaptiq-Signature to prevent spoofed requests.
  • Monitor delivery health. Check the webhook dashboard for failed deliveries and error rates.
  • Use HTTPS. Synaptiq only delivers webhooks to HTTPS endpoints.

Was this page helpful?

PreviousAnalytics APINextRate Limits and Error Codes