Webhooks
Instead of polling, give us an HTTPS address and we call it when something you care about happens.
| Event | Sent when | Level |
|---|---|---|
signal.published | A signal was published for a brand you follow or match with a filter. | Level 2+ |
signal.veto | A hard-veto signal was published. | Level 2+ |
score.changed | A brand score was re-evaluated and moved by more than the threshold you set. | Level 2+ |
mall.tenants_changed | The tenants of a mall you follow changed (an opening or a closing). | Level 3+ |
Payload
{
"id": "evt_6Qm3zRb",
"type": "signal.published",
"created_at": "2026-11-01T09:30:05Z",
"data": { "id": "sig_2Lm4vXb", "brand_id": "brd_9Tq2xKf", "category": "Expansion & Growth", "title": "Opens 12 new stores in the UK" }
}Verifying a delivery
Each delivery is signed. The RB-Signature header holds an HMAC-SHA256 of the raw request body, keyed with the secret of your endpoint. Compute it and compare in constant time before trusting the event.
import crypto from "node:crypto";
const expected = crypto.createHmac("sha256", process.env.RB_WEBHOOK_SECRET)
.update(rawBody).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));Delivery
Answer with any 2xx within 10 seconds. Otherwise we retry with growing delays for 24 hours. Deliveries can repeat, so make your handler idempotent using the event id.