Verification
Check that a webhook delivery came from RankDebug and has not been replayed.
Every delivery is signed with the webhook's secret, so your endpoint can reject anything that did not come from RankDebug. Verify before you act on a delivery.
The signatures
Each delivery carries two signatures, both HMAC-SHA256 keyed with the webhook secret and written as sha256= followed by the hex digest:
X-RankDebug-Signature-256signs the timestamp and the body together, as{timestamp}.{body}, where the timestamp is theX-RankDebug-Timestampheader. Use this one. Because the timestamp is signed, a captured delivery cannot be sent again later.X-RankDebug-Signaturesigns the raw body alone. It is kept for receivers that already check it.
Always sign the raw request body exactly as received, before any JSON parsing.
Steps
- Read
X-RankDebug-Timestampand refuse the delivery if it is more than 300 seconds old. - Compute HMAC-SHA256 of
{timestamp}.{raw body}with your secret, hex-encoded. - Compare it with the value after
sha256=inX-RankDebug-Signature-256, using a constant-time comparison.
Example
import crypto from 'node:crypto';
const TOLERANCE_SECONDS = 300;
export function verifyRankDebugWebhook(
rawBody: string,
headers: Record<string, string | undefined>,
secret: string,
): boolean {
const timestamp = Number(headers['x-rankdebug-timestamp']);
const signature = headers['x-rankdebug-signature-256'] ?? '';
if (!Number.isFinite(timestamp)) return false;
if (Math.abs(Date.now() / 1000 - timestamp) > TOLERANCE_SECONDS) return false;
const expected =
'sha256=' +
crypto.createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex');
const a = Buffer.from(signature);
const b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Rotating the secret
Send a new secret when updating the webhook, or use Rotate Secret when editing the webhook in the dashboard. The new secret is shown once. It applies from the next attempt, including retries of deliveries that were already queued, so update your receiver at the same time.
Related documentation
- Webhooks
Receive RankDebug events at your own HTTPS endpoint, signed so you can trust them.
- Events
The events a webhook can subscribe to, when they fire, and what their data contains.
- Retries and Deliveries
How failed deliveries are retried, when a webhook is paused, and how to inspect and replay deliveries.
- Webhooks
Create and manage webhook endpoints, send test events, and read and replay deliveries.