Skip to Content
DevelopersWebhooks

Webhooks

Webhooks push Loopwave events to a URL you control, in real time. Because Loopwave can deliver any event to any HTTPS endpoint, you can connect Loopwave to virtually any tool — a CRM, a spreadsheet automation, a workflow builder, or your own backend — without per-vendor connectors. If a system can receive an HTTP POST, it can react to Loopwave.

Events

Subscribe a webhook to one or more of these events:

EventFires when
message.createdA message is sent or received.
chats.updatedA chat changes (status, assignment, new activity).
session.statusA connected number changes connection state.
session.removedA number is unlinked.
broadcast.progressA broadcast advances (sent/failed counts update).

Payload format

Every delivery is a JSON POST with a consistent envelope:

Delivery body
{ "event": "message.created", "data": { }, "timestamp": "2026-06-29T10:15:00.000Z" }

data carries the event-specific payload; timestamp is the ISO-8601 send time.

Verifying signatures

Each delivery includes an HMAC signature so you can confirm it genuinely came from your Loopwave instance and wasn’t tampered with.

  • Header: X-Loopwave-Signature
  • Format: sha256=<hex>
  • Computation: HMAC-SHA256 of the exact JSON body using your webhook’s secret.

Always verify the signature before trusting a payload, and compare using a constant-time comparison. Compute the HMAC over the raw request body bytes.

Node.js
import crypto from 'node:crypto'; function verify(rawBody, signatureHeader, secret) { const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex'); const a = Buffer.from(signatureHeader || ''); const b = Buffer.from(expected); return a.length === b.length && crypto.timingSafeEqual(a, b); } // Express: capture the raw body so the bytes match exactly. // app.use(express.json({ verify: (req, _res, buf) => { req.rawBody = buf; } })); app.post('/loopwave-webhook', (req, res) => { if (!verify(req.rawBody, req.header('X-Loopwave-Signature'), process.env.LOOPWAVE_SECRET)) { return res.status(401).end(); } const { event, data } = req.body; // ...handle event... res.status(200).end(); });
Python (Flask)
import hmac, hashlib def verify(raw_body: bytes, signature_header: str, secret: str) -> bool: expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, signature_header or "") @app.post("/loopwave-webhook") def hook(): if not verify(request.get_data(), request.headers.get("X-Loopwave-Signature"), SECRET): return ("", 401) payload = request.get_json() # ...handle payload["event"]... return ("", 200)

Setting up a webhook

  1. Create the webhook (admin)

    In the dashboard, add a webhook with a name, your endpoint URL, and the events to subscribe to. Set a secret (8+ characters) so deliveries are signed.

  2. Send a test delivery

    Use the test action to POST a sample test event to your URL and confirm your endpoint receives and verifies it.

  3. Go live

    Once verified, your endpoint will receive real events as they happen.

The test delivery looks like:

Test event
{ "event": "test", "data": { "message": "Test delivery from Loopwave", "webhook": "My CRM sync" }, "timestamp": "2026-06-29T10:15:00.000Z" }

Delivery, retries & timeouts

BehaviorValue
Request timeout5 seconds
RetriesUp to 2 additional attempts after the first
BackoffLinear (attempt number x 300ms)
Recorded per webhookLast delivery time, last status, last error

Respond with a 2xx status quickly to acknowledge receipt. If your endpoint times out or errors, Loopwave retries with a short backoff, then records the failure (HTTP status, or timeout/error) on the webhook so you can diagnose it.

Make your handler idempotent. A retry can deliver the same event more than once, so key on the event content (or your own dedupe id) rather than assuming exactly-once delivery.

Managing webhooks

Webhook management is admin-only: create, update, send a test, and delete. Each webhook can be enabled or disabled without deleting it.

Drive Loopwave from your code

Pair outbound webhooks with the REST API to build full integrations.