Everything that happens,
pushed to your systems
16 events. Signed with HMAC-SHA256. Retried on failure. Your CRM, data warehouse and ops tooling stay in sync without polling.
Setup
Dashboard → Integrations → Add Webhook. Give us your HTTPS endpoint, pick the events you want (or all), and we generate a signing secret. A test ping button verifies your endpoint before anything real flows.
The event catalog
| Event | Fires when |
|---|---|
message.received | Any inbound message — includes cached media URLs |
message.sent | Any outbound message leaves the platform |
message.status | Delivery ticks: sent → delivered → read → failed |
contact.created | A brand-new number messages you |
contact.updated | Profile, tags or opt-in status changes |
campaign.completed | A campaign finishes — with sent/failed totals |
automation.completed | A contact finishes a chatbot flow — with collected data |
ctwa.lead.created | Someone arrives from a Click-to-WhatsApp ad — with ad attribution |
cart.recovered | An abandoned-cart message converts |
approval.approved / approval.rejected | Approval outcomes — rejection includes the reason |
interaction.responded / .reply / .completed | Option taps, each captured reply, and the final bundle |
lead.created | An agent creates an internal-type lead from a chat |
test.ping | You pressed the test button |
Delivery format
POST your-endpoint ← ChatReach
Headers:
Content-Type: application/json
X-ChatReach-Event: message.received
X-ChatReach-Signature: 3f1a9c… (HMAC-SHA256 of the raw body)
Body:
{
"event": "message.received",
"timestamp": "2026-07-11T12:00:00Z",
"data": {
"messageId": 88231,
"contactId": "…",
"phone": "27821234567",
"name": "John Smith",
"type": "image",
"body": null,
"mediaUrl": "https://yourdomain.co.za/media/wamid_abc.jpg",
"receivedAt": "2026-07-11T11:59:58Z"
}
}Verify the signature (4 lines)
C#
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(signingSecret));
var computed = Convert.ToHexString(
hmac.ComputeHash(Encoding.UTF8.GetBytes(rawRequestBody))).ToLowerInvariant();
var valid = computed == Request.Headers["X-ChatReach-Signature"];Node.js
const crypto = require('crypto');
const computed = crypto.createHmac('sha256', signingSecret)
.update(rawBody).digest('hex');
const valid = computed === req.headers['x-chatreach-signature'];PHP
$computed = hash_hmac('sha256', $rawBody, $signingSecret);
$valid = hash_equals($computed, $_SERVER['HTTP_X_CHATREACH_SIGNATURE']);Always compute over the raw request body — parse the JSON after verifying, never before re-serializing.
Retries & reliability
| Behavior | Detail |
|---|---|
| Success | Any 2xx response within 15 seconds |
| Retries | Failures retry at +5s, +30s and +2min before marking the delivery failed |
| Delivery log | Every attempt (status code, response snippet, timing) is visible on the Integrations page |
| Ordering | Best-effort per event; use timestamps for strict ordering on your side |
| Idempotency | Retries resend the same payload — dedupe on data.messageId / entity IDs |
Tip: respond 200 immediately and process asynchronously. Slow endpoints trigger unnecessary retries.
Point us at your endpoint
Test ping to production events in under five minutes. Free trial includes unlimited webhooks.
Start Free Trial