Appearance
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
- You register a publicly accessible HTTPS URL in your Watzy dashboard (Profile → Webhook Endpoints).
- Watzy stores a unique signing secret for that endpoint.
- When an event occurs, Watzy sends an HTTP
POSTrequest to your URL with a JSON payload. - 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.
| Field | Description |
|---|---|
| URL | Your server's HTTPS endpoint, e.g. https://myapp.com/watzy-events |
| Label | A 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": { ... }
}| Field | Type | Description |
|---|---|---|
event | string | Event type — see Events Reference |
timestamp | string | ISO 8601 UTC timestamp of when Watzy processed the event |
data | object | Event-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);
}