Wacrm’s Webhooks API lets you register HTTPS endpoints that receive real-time event notifications when things happen in your account — new messages, delivery status changes, and new conversations — without polling the read endpoints. Each delivery is signed with HMAC-SHA256 so you can verify that it genuinely came from your Wacrm instance.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ArnasDon/wacrm/llms.txt
Use this file to discover all available pages before exploring further.
Migration required. Webhooks require the
supabase/migrations/028_webhook_endpoints.sql migration to be applied to your Supabase project before the endpoints and delivery machinery are available.Events
| Event | Fires when |
|---|---|
message.received | An inbound message arrives from a contact |
message.status_updated | A sent message changes delivery status (e.g. delivered, read) |
conversation.created | A new conversation is opened for a contact |
Managing endpoints
All webhook management endpoints require thewebhooks:manage scope.
POST /api/v1/webhooks — Register an endpoint
Register a new webhook endpoint to start receiving events.
Request body:
The HTTPS URL Wacrm will POST events to. Must begin with
https://. Localhost, RFC1918 ranges, link-local addresses (including the cloud metadata address 169.254.169.254), and other non-public targets are rejected — see SSRF restrictions below.A non-empty array of event names to subscribe to. Valid values:
message.received, message.status_updated, conversation.created.GET /api/v1/webhooks — List endpoints
Returns all registered webhook endpoints for your account. The secret is never returned in list or read responses — only at creation.
GET /api/v1/webhooks/{id} — Read one endpoint
Returns a single endpoint by UUID. Returns 404 if it does not exist or belongs to a different account. The secret is not returned.
PATCH /api/v1/webhooks/{id} — Update an endpoint
Updates one or more fields. Only fields present in the request body are changed.
New HTTPS destination URL. Must satisfy the same
https:// and public-address requirements as registration.Replaces the current event subscription list. Must be a non-empty array of known event names.
Enable (
true) or disable (false) the endpoint. Re-enabling an endpoint resets failure_count to zero, giving it a clean slate to start receiving deliveries again.404 if the endpoint belongs to a different account.
DELETE /api/v1/webhooks/{id} — Remove an endpoint
Permanently removes the endpoint. Future events will not be delivered to the associated URL. Returns 404 if the endpoint belongs to a different account.
Delivery payload
Every event delivery is an HTTP POST to your registered URL with a JSON body using this envelope:A unique UUID for this delivery attempt. Use this to deduplicate events — the same logical event may occasionally be delivered more than once.
The event name:
message.received, message.status_updated, or conversation.created.ISO 8601 timestamp of when the event occurred in Wacrm.
The UUID of your account. Useful when a single endpoint receives webhooks from multiple Wacrm instances.
Event-specific payload. Shape varies by
event — see below.data shape by event
Delivery headers
Each request also includes these HTTP headers:| Header | Value |
|---|---|
X-Wacrm-Event | The event name (e.g. message.received) |
X-Wacrm-Webhook-Id | The UUID of your registered endpoint |
X-Wacrm-Signature | HMAC-SHA256 signature — see below |
Verifying signatures
Every delivery includes anX-Wacrm-Signature header with this format:
v1 is computed as:
secret is the plaintext secret shown at endpoint creation and rawBody is the raw (unparsed) request body bytes.
Verification steps:
- Parse
t(timestamp) andv1(signature hex) from the header. - Recompute the expected HMAC over the raw body using your stored secret.
- Compare in constant time to prevent timing attacks.
- Reject the delivery if
tis more than a few minutes old (replay protection).
Delivery semantics
Understanding how Wacrm delivers events helps you build a robust consumer:- Best-effort, single attempt. Each event triggers one HTTP POST. There is no automatic retry on failure.
- Short timeout, no redirects. Wacrm uses a short request timeout and does not follow redirects. Your endpoint must respond promptly (return a
2xxbefore the timeout) and must not issue a redirect. - Failure counting and auto-disable. Each consecutive failed delivery increments
failure_counton the endpoint. After enough consecutive failures, the endpoint is automatically set tois_active: false. Re-enable it withPATCH /api/v1/webhooks/{id}(which resetsfailure_countto zero). message.status_updatedquirks. This event covers messages Wacrm has a record for (inbox messages and API sends), not broadcast-only sends. Because Meta can re-send and re-order status callbacks, the same status transition may arrive more than once or out of sequence — always dedupe onidand do not assume ordering.- Dedupe on
id. Every delivery envelope has a uniqueid. Process it idempotently and ignore duplicates.
Durable retries are a future enhancement. Today, delivery is best-effort with no retry queue. If your use case requires guaranteed at-least-once delivery, reconcile missed events using the read endpoints (
GET /api/v1/conversations, GET /api/v1/conversations/{id}/messages) when a gap is detected.SSRF restrictions
To prevent server-side request forgery, Wacrm validates the destination URL before attempting delivery. The following targets are blocked:- URLs that do not begin with
https:// localhostand loopback addresses (127.0.0.0/8,::1)- RFC1918 private ranges (
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16) - Link-local addresses (
169.254.0.0/16), including the cloud instance metadata endpoint at169.254.169.254 - Other non-public or internal network targets