Try any paid plan free for 14 days — no credit card, no commitment, no contract.14-day free trial on all paid plans — no card needed. Start free trial
Webhooks send a structured HTTP notification to your endpoint after ReviewPanel refreshes a connected business account.
| Event | Description |
|---|---|
| business_account.metrics.updated | Business-account review metrics were refreshed. |
| webhook.test.sent | A test event triggered from the dashboard. |
The live business_account.metrics.updated event includes:
Every webhook request includes an HMAC-SHA256 signature in the X-Webhook-Signature header. The signature is computed over {timestamp}.{body} — the X-Timestamp header value, a literal dot, then the raw request body. Signing the timestamp makes it tamper-evident so you can reject replayed requests.
To protect against replay attacks: reject requests whose X-Timestamp is more than 5 minutes old, and reject any X-Request-ID (unique delivery ID) you have already processed.
const crypto = require('crypto'); const seenDeliveryIds = new Set(); // back with Redis/TTL store in production const TOLERANCE_MS = 5 * 60 * 1000; function verifyWebhook(rawBody, headers, secret) { const timestamp = headers['x-timestamp']; const deliveryId = headers['x-request-id']; const signature = (headers['x-webhook-signature'] || '').replace('sha256=', ''); // 1. Reject stale requests (replay protection) const age = Date.now() - new Date(timestamp).getTime(); if (!timestamp || Number.isNaN(age) || Math.abs(age) > TOLERANCE_MS) { return false; } // 2. Reject duplicate delivery IDs (replay protection) if (!deliveryId || seenDeliveryIds.has(deliveryId)) { return false; } // 3. Verify the signature over `${timestamp}.${body}` const expected = crypto .createHmac('sha256', secret) .update(`${timestamp}.${rawBody}`) .digest('hex'); const sigBuf = Buffer.from(signature, 'hex'); const expBuf = Buffer.from(expected, 'hex'); if (sigBuf.length !== expBuf.length || !crypto.timingSafeEqual(sigBuf, expBuf)) { return false; } seenDeliveryIds.add(deliveryId); return true; } You can rotate your signing secret at any time from the webhook settings. During rotation, deliveries include an X-Webhook-Signature-Previous header signed with the old secret so you can accept either while you roll over.
If your endpoint returns a non-2xx status code or times out, ReviewPanel retries with exponential backoff:
Send a test event from your webhook settings to verify your endpoint is configured correctly. The test event uses the webhook.test.sent type and includes sample data.