Webhooks
Webhooks push goal completions and traffic alerts to your endpoint, Slack, Zapier, or your own service, seconds after they happen.
- Key takeaways
- Events: goal.completed, traffic.spike, report.ready, signed with HMAC-SHA256.
- Delivery is at-least-once with 1/5/30-minute retries, make handlers idempotent.
- Payloads contain zero visitor-identifying data.
Available events
goal.completed: fires per conversion with goal name, page, and any event metadata.traffic.spike: fires when 15-minute traffic exceeds your configured multiple of baseline.report.ready: fires when a scheduled report is generated, handy for archiving PDFs.
Payload and signature
POST https://yourapp.example/hooks/bobray
X-BobRay-Signature: sha256=8f3a…
{
"event": "goal.completed",
"site": "br_7fk2mq",
"goal": "signup",
"page": "/pricing",
"meta": { "plan": "growth" },
"occurred_at": "2026-06-29T14:03:22Z"
}Verify the HMAC-SHA256 signature with your endpoint's secret before trusting a payload.
Delivery semantics
- At-least-once delivery with retries at 1, 5, and 30 minutes on non-2xx responses, make handlers idempotent using
occurred_at+ goal + page. - Payloads contain zero visitor-identifying data, consistent with everything else we do.
- Test deliveries can be fired from
Settings → Webhooks → Send test.
Common pitfalls
The mistakes we see most often on this topic, so you can skip them entirely.
- Trusting payloads without verifying X-BobRay-Signature.
- Doing heavy work inline and timing out into retry storms, ack fast, process async.
- Keying idempotency on delivery time instead of occurred_at + goal + page.
Quick reference
| Signature | X-BobRay-Signature: sha256=… |
| Retries | 1 m, 5 m, 30 m |
| Test fire | Settings → Webhooks → Send test |
| Ack window | Respond 2xx < 10 s |
Did this solve it? If not, write to support with your site ID, a real person replies within one business day.