Webhooks (developer API)
How it works
Section titled “How it works”BUZ sends a thin notification. It deliberately carries no business data — just what happened and where to fetch it:
{ "event": "lead.created", "organizationId": 1234, "occurredAt": "2026-08-06T02:15:44.182+00:00", "resource": { "type": "lead", "id": "9f2b...", "url": "https://api.buzmanager.com/sales/Leads/9f2b..." }}Your endpoint receives this, then calls resource.url with your own BUZ token to get the
full record. That’s why the payload is thin: nothing sensitive is sent to an endpoint that hasn’t
authenticated, so a leaked or mistyped URL can’t leak customer data.
Events you can subscribe to
Section titled “Events you can subscribe to”| Event | Fires when |
|---|---|
lead.created |
A new lead is created |
lead.updated |
An existing lead is changed |
order.invoiced |
An order is invoiced |
payment.received |
A payment is recorded |
Subscribing to anything else is rejected with the list of valid events.
Subscribe
Section titled “Subscribe”Subscriptions are scoped to your user and the organisation you’re authenticated against. All
three calls need a BUZ access token and the Sales / Leads / Access permission.
-
Create the subscription.
POST /sales/Webhooks/SubscriptionsContent-Type: application/json{ "event": "lead.created", "targetUrl": "https://example.com/hooks/buz" }The response contains the subscription id and its signing secret:
{ "id": "3f0c...", "secret": "…" } -
Store the secret now. It is returned once, at creation, and never shown again — not by the list endpoint, not by support. Lose it and you must create a new subscription.
-
Verify deliveries using the secret (see below).
List your subscriptions
Section titled “List your subscriptions”GET /sales/Webhooks/SubscriptionsReturns id, event, target URL, active flag and created date for the calling user and organisation. Secrets are never included.
Stop a subscription
Section titled “Stop a subscription”DELETE /sales/Webhooks/Subscriptions/{id}Deactivates it so deliveries stop.
Verify the signature
Section titled “Verify the signature”Every delivery carries an X-BUZ-Signature header:
X-BUZ-Signature: sha256=<lowercase hex>It is the HMAC-SHA256 of the raw request body, keyed by your subscription secret, prefixed
with sha256=.
- Read the raw request body — before any JSON parsing or re-serialising. Re-encoding changes the bytes and the signature won’t match.
- Compute
HMAC-SHA256(rawBody, secret)and hex-encode it in lowercase. - Compare with the header value using a constant-time comparison.
- Reject the request if it doesn’t match.
import crypto from 'node:crypto';
function isValid(rawBody, header, secret) { const expected = 'sha256=' + crypto.createHmac('sha256', secret) .update(rawBody) .digest('hex'); const a = Buffer.from(expected); const b = Buffer.from(header ?? ''); return a.length === b.length && crypto.timingSafeEqual(a, b);}Requirements for your endpoint
Section titled “Requirements for your endpoint”- Must be
httporhttps— other schemes are rejected when you subscribe. - Must be publicly reachable. URLs resolving to private, loopback or reserved IP ranges are rejected at subscribe time and skipped at delivery time.
- Must answer within 10 seconds. Deliveries time out after that so a slow endpoint can’t hold up someone’s save in BUZ.
- Should respond quickly and do the work afterwards — acknowledge with
2xx, then process in the background.
Delivery behaviour
Section titled “Delivery behaviour”410 Gonedeactivates the subscription. Return410when an endpoint is permanently retired and BUZ stops sending. Never return410for a temporary outage.- A delivery failure never breaks BUZ. Dispatch failures are swallowed, so a broken endpoint can’t stop a lead from saving.
- Order isn’t guaranteed. Use
occurredAtif sequence matters. - Handle repeats. Make your handler idempotent, keyed on
resource.id+event+occurredAt.
Building a reliable consumer
Section titled “Building a reliable consumer”- Verify the signature. Reject if invalid.
- Return
2xximmediately — before doing any real work. - Queue the notification internally.
- Fetch the full record from
resource.urlwith your own token. - De-duplicate on
resource.id+event+occurredAt. - Reconcile periodically to catch anything a failed delivery lost.
See also
Section titled “See also”- Website leads (developer API) — push leads into BUZ.
- Integrations overview — Zapier and the polling triggers.