Webhooks
Webhooks let your application receive real-time notifications when lead events happen, instead of polling the API.
How it works
- Subscribe to one or more event types by creating a webhook subscription (
POST /v1/webhook-subscriptions). - ABC Sales AI sends an HTTP
POSTto your callback URL whenever a subscribed event fires. - Your endpoint verifies the signature and responds with a
2xxstatus to acknowledge receipt.
Event types
You can subscribe to these event types:
| Event type | Fires when |
|---|---|
leads_created | A new lead is created |
leads_updated | A lead is updated |
leads_deleted | A lead is deleted |
leads_escalation_requested | A lead requests escalation to a human |
conversation_created | A new conversation is created |
Fetch the current list programmatically via GET /v1/webhook-subscriptions/events.
Managing subscriptions
| Action | Endpoint |
|---|---|
| List event types | GET /v1/webhook-subscriptions/events |
| Create a subscription | POST /v1/webhook-subscriptions |
| Update a subscription | PUT /v1/webhook-subscriptions/{subscriptionId} |
| Delete a subscription | DELETE /v1/webhook-subscriptions/{subscriptionId} |
| Regenerate signing secret | POST /v1/webhook-subscriptions/{subscriptionId}/regenerate-secret |
See the API Reference for exact request and response schemas.
Delivery headers
Every webhook request includes these headers:
| Header | Description |
|---|---|
X-AbcSalesAI-Signature | HMAC-SHA256 signature of the raw request body (hex). See below. |
X-AbcSalesAI-Event | The event type that triggered this delivery. |
X-AbcSalesAI-Delivery | Unique delivery ID (useful for logging and idempotency). |
X-AbcSalesAI-Timestamp | Unix timestamp of the delivery. |
Content-Type | application/json |
User-Agent | Engagematic-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
2xxstatus. 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.