Outbound webhooks
Register an HTTPS URL and DMtoLead posts events to it as they happen — new conversations, messages, automation triggers. Plug it into your CRM, Slack, or any internal tool.
Register a webhook
- 1
Open the dashboard
Settings → Webhooks → Create webhook.
- 2
Give it a name and URL
Name is internal-only (e.g. "Production CRM"). URL must be a public HTTPS endpoint you control. Self-signed certificates are rejected — use a real cert (Let's Encrypt is fine).
- 3
(Optional) Account filter
For agencies running multiple managed accounts in one workspace: select which managed accounts this webhook should fire for. Leave empty to fire on all activity.
- 4
Save — DMtoLead verifies the URL
On save, DMtoLead posts a verification payload to your URL (see below). Your endpoint must respond
2xxwithin 10 seconds and echo back theverifyTokenin JSON. If it fails verification the webhook is saved but disabled — fix the endpoint and toggle re-verify. - 5
Copy the API key
We auto-generate an API key shown once after save. Use it to authenticate the request signature header on your side (HMAC-SHA256 of the body using the key as the secret). The full key is stored hashed in our database — we can't show it again.
Verification payload
On webhook creation (and on every "re-verify"), we POST this to your URL:
{
"event": "webhook.verify",
"verifyToken": "abc123...",
"timestamp": "2026-05-13T19:24:00.000Z"
}Respond with:
{ "verifyToken": "abc123..." }Status code 200, content-type application/json. Anything else and the webhook stays unverified.
Event types
webhook.verify— sent once during setup (above).conversation.created— new conversation on any channel.message.received— inbound message from customer.message.sent— outbound message (AI or manual).automation.triggered— fires when an automation rule matches (keyword auto-reply, comment auto-engage).conversation.closed— agent or AI marked the conversation resolved.
Example payloads
{
"event": "conversation.created",
"timestamp": "2026-05-13T19:24:00.000Z",
"data": {
"conversationId": "65f3a2...",
"workspaceId": "wks_...",
"automationId": "auto_...",
"channel": "instagram",
"customer": {
"platformId": "17841...",
"name": "Alice",
"username": "alice.example"
},
"firstMessage": "Hi, do you have the green one in M?"
}
}{
"event": "message.sent",
"timestamp": "2026-05-13T19:24:02.310Z",
"data": {
"conversationId": "65f3a2...",
"messageId": "msg_...",
"direction": "outbound",
"type": "ai",
"text": "Yes! The green is in stock in M. Want me to set up a draft order?",
"creditsUsed": 1
}
}Verifying the request came from DMtoLead
Every webhook POST includes an X-DMtoLead-Signatureheader with an HMAC-SHA256 hex digest of the raw request body, using your API key as the secret. Verify on your side:
import crypto from "crypto";
function verify(rawBody, signatureHeader, apiKey) {
const expected = crypto
.createHmac("sha256", apiKey)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}Delivery and retries
DMtoLead retries failed deliveries with exponential backoff: 1s, 5s, 30s, 5min, 30min, then gives up. Failures are visible in Settings → Webhooks → Delivery log. Your endpoint can return any 2xx to acknowledge; anything else triggers retry.
Aim to respond within 10 seconds — slow endpoints don't break delivery but can stack up retries during high-volume periods. If you need to do heavy work, queue it on your side and return 200 fast.
Plan limits
- Free: 1 webhook
- Starter: 3 webhooks
- Pro: 10 webhooks
- Business / Agency: unlimited
Each registered URL counts as one webhook. Multiple events route to the same URL with different event values in the payload — you don't need a separate URL per event.
