Skip to main content

Webhooks

Webhooks let your application receive real-time notifications when lead events happen, instead of polling the API.

How it works

  1. Subscribe to one or more event types by creating a webhook subscription (POST /v1/webhook-subscriptions).
  2. ABC Sales AI sends an HTTP POST to your callback URL whenever a subscribed event fires.
  3. Your endpoint verifies the signature and responds with a 2xx status to acknowledge receipt.

Event types

You can subscribe to these event types:

Event typeFires when
leads_createdA new lead is created
leads_updatedA lead is updated
leads_deletedA lead is deleted
leads_escalation_requestedA lead requests escalation to a human
conversation_createdA new conversation is created

Fetch the current list programmatically via GET /v1/webhook-subscriptions/events.

Managing subscriptions

ActionEndpoint
List event typesGET /v1/webhook-subscriptions/events
Create a subscriptionPOST /v1/webhook-subscriptions
Update a subscriptionPUT /v1/webhook-subscriptions/{subscriptionId}
Delete a subscriptionDELETE /v1/webhook-subscriptions/{subscriptionId}
Regenerate signing secretPOST /v1/webhook-subscriptions/{subscriptionId}/regenerate-secret

See the API Reference for exact request and response schemas.

Delivery headers

Every webhook request includes these headers:

HeaderDescription
X-AbcSalesAI-SignatureHMAC-SHA256 signature of the raw request body (hex). See below.
X-AbcSalesAI-EventThe event type that triggered this delivery.
X-AbcSalesAI-DeliveryUnique delivery ID (useful for logging and idempotency).
X-AbcSalesAI-TimestampUnix timestamp of the delivery.
Content-Typeapplication/json
User-AgentEngagematic-Webhook-Dispatcher/1.0

Payload

The request body is JSON with this shape (a lead event example):

{
"event_type": "leads_created",
"event_data": {},
"lead": {
"id": "external-lead-id",
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+60123456789",
"source": "whatsapp",
"timezone": "Asia/Kuala_Lumpur",
"locale": "en",
"currency": "MYR",
"tags": ["new"],
"custom_fields": {},
"created_at": "2026-01-01T08:00:00Z"
}
}

event_data carries event-specific detail. For conversation_created, a conversation object is included; for leads_escalation_requested, escalation_reason and escalation_topic may be present.

Verifying signatures

Each subscription has a signing secret: a 64-character hex string, returned when you create the subscription and rotatable via the regenerate-secret endpoint.

The X-AbcSalesAI-Signature header is the HMAC-SHA256 of the raw request body, keyed with your signing secret, hex-encoded. Compute the same value and compare in constant time. Use the raw bytes of the body, before any JSON parsing or re-serialization.

const crypto = require('crypto');

function isValidSignature(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody) // the raw request body, not the parsed object
.digest('hex');
// constant-time comparison
return (
signatureHeader.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected))
);
}

Reject any request whose signature does not match.

Retries

If your endpoint does not respond with a 2xx status (or times out), ABC Sales AI retries delivery:

  • Timeout: each attempt waits up to 10 seconds for your response.
  • Success: any 2xx status. Anything else (including timeouts and network errors) is a failure.
  • Retries: up to 5 retries after the initial attempt, with exponential backoff of 1, 2, 4, 8, then 16 minutes.
  • After the final retry fails, the delivery is marked failed and not retried again.

Make your handler idempotent (use X-AbcSalesAI-Delivery to de-duplicate), since a delivery can arrive more than once.