Webhooks
When a callbackUrl is provided on execution, White Rabbit delivers the completed execution record to your endpoint as an HTTP POST with a JSON body. This page covers how to secure, verify, and recover webhook deliveries.
How it worksβ
POST /v1/sdk/components
callbackUrl: "https://your-app.com/webhooks/wr"
callbackSecret: "my-hmac-secret"
attempts: 2
β
βΌ (component runs in background)
β
βΌ on completion
White Rabbit ββPOSTβββΆ https://your-app.com/webhooks/wr
X-WR-Signature: hmac-sha256-v1=<hex>
Body: { execution record }
The payload is the same execution record shape returned by Execute Component.
Signature verificationβ
When callbackSecret is set, White Rabbit signs the raw request body using HMAC-SHA256 and sends the result in the X-WR-Signature header as hmac-sha256-v1=<hex>.
Always verify this signature before processing the payload.
Verifying in Node.jsβ
import { createHmac, timingSafeEqual } from 'crypto';
function verifyWebhookSignature(
rawBody: Buffer | string,
signatureHeader: string,
secret: string,
): boolean {
const expected = createHmac('sha256', secret)
.update(typeof rawBody === 'string' ? rawBody : rawBody)
.digest('hex');
const received = signatureHeader.replace('hmac-sha256-v1=', '');
return timingSafeEqual(
Buffer.from(expected, 'hex'),
Buffer.from(received, 'hex'),
);
}
// Express handler example
app.post('/webhooks/wr', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-wr-signature'] as string;
if (!verifyWebhookSignature(req.body, sig, process.env.WR_CALLBACK_SECRET!)) {
return res.status(401).send('Invalid signature');
}
const execution = JSON.parse(req.body.toString());
console.log('Execution completed:', execution.id, execution.status);
res.sendStatus(200);
});
Always use timingSafeEqual to compare signatures. Standard string comparison (===) is vulnerable to timing attacks.
Verifying in Pythonβ
import hmac
import hashlib
def verify_signature(raw_body: bytes, signature_header: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
raw_body,
hashlib.sha256,
).hexdigest()
received = signature_header.replace('hmac-sha256-v1=', '')
return hmac.compare_digest(expected, received)
Retry behaviourβ
| Field | Default | Description |
|---|---|---|
attempts | 1 | Total delivery attempts (max 3) |
callbackHeaders | {} | Custom headers added to every delivery request |
If a delivery fails (non-2xx response or timeout), White Rabbit retries up to the configured attempts count with exponential backoff.
Replay callbackβ
POST /v1/sdk/components/executions/:executionId/replay-callback
Manually re-deliver the completion webhook for a finished execution. Useful when your endpoint was temporarily unavailable or returned an error. Idempotent β safe to call multiple times.
curl -X POST \
https://api.whiterabbit.app/v1/sdk/components/executions/3f7a.../replay-callback \
-H "X-Api-Key: ws_..." \
-H "X-Sdk-Timestamp: <timestamp>" \
-H "X-Sdk-Signature: <signature>"
Response β same execution record shape as Execute Component.