Skip to content

Webhooks Overview

Webhooks let you receive real-time notifications from Watzy whenever something happens — a customer replies to a message, or a message's delivery status changes.

How it works

  1. You register a publicly accessible HTTPS URL in your Watzy dashboard (Profile → Webhook Endpoints).
  2. Watzy stores a unique signing secret for that endpoint.
  3. When an event occurs, Watzy sends an HTTP POST request to your URL with a JSON payload.
  4. You verify the request using the signing secret and process the event.

Registering a webhook endpoint

Go to Dashboard → Profile → Webhook Endpoints and click Add Endpoint.

FieldDescription
URLYour server's HTTPS endpoint, e.g. https://myapp.com/watzy-events
LabelA friendly name (for your reference only)

After saving, Watzy will show you the signing secret once. Copy it — you'll need it to verify signatures.

You can also test the endpoint from the dashboard (sends a ping event to confirm reachability).

Payload format

Every event POST has this JSON shape:

json
{
  "event": "message.received",
  "timestamp": "2024-06-06T14:30:00+00:00",
  "data": { ... }
}
FieldTypeDescription
eventstringEvent type — see Events Reference
timestampstringISO 8601 UTC timestamp of when Watzy processed the event
dataobjectEvent-specific payload — different per event type

Response requirements

Your endpoint must respond with HTTP 2xx within 10 seconds.

  • If your endpoint returns a non-2xx status or times out, Watzy will retry up to 3 times with exponential back-off (1 min → 5 min → 25 min).
  • Make your handler idempotent — the same event may be delivered more than once during retries.

Security — verifying signatures

Every request includes an X-Watzy-Signature header:

X-Watzy-Signature: sha256=<hmac-hex>

You must verify this before processing the payload.

See the full guide → Signature Verification.

Quick verification snippet

js
const crypto = require('crypto')

function verifyWatzy(rawBody, signatureHeader, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex')
  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader),
    Buffer.from(expected),
  )
}
python
import hmac, hashlib

def verify_watzy(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)
php
function verifyWatzy(string $rawBody, string $signatureHeader, string $secret): bool {
    $expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
    return hash_equals($expected, $signatureHeader);
}

Built with ❤️ on top of the WhatsApp Business API.