Overview
RevRag.ai sends webhook notifications to your configured endpoint when specific events occur (such as when a call ends). To ensure the security and authenticity of these webhooks, we implement cryptographic signature verification that allows you to confirm that requests are genuinely from RevRag.ai.Authentication Method
We use HMAC-based authentication to secure webhook notifications. This method uses a shared secret to cryptographically sign webhook payloads, providing strong security guarantees for verifying the authenticity and integrity of each request.Configuration
To set up webhooks, you’ll need to configure:- Webhook URL: The HTTPS endpoint where you’ll receive webhook notifications (HTTP is not supported for security reasons)
- Secret Key: A secure shared secret used for HMAC signature verification
- Event Types: Select which events you want to receive (currently supported:
call.ended)
Webhook Headers
Every webhook request includes the following headers:| Header | Purpose | Example |
|---|---|---|
Content-Type | Ensures receiver parses payload correctly | application/json |
X-Webhook-Event | Identifies the event type | call.ended |
X-Webhook-ID | Unique identifier for deduplication and logging | evt_01HC3Q0MZQABR3... |
X-Webhook-Timestamp | Unix timestamp when the webhook was sent | 1698064496 |
X-Webhook-Signature | HMAC signature for verifying authenticity | t=1698064496,v1=abc123... |
Webhook Payload
The webhook payload contains the same data structure as described in the Webhook Notifications section of the API documentation. For complete payload details and field descriptions, please refer to that section.Signature Verification
How It Works
We use HMAC-SHA256 to sign every webhook request. The signature is computed over a string consisting of:timestampis the Unix timestamp (in seconds) from theX-Webhook-Timestampheaderraw_request_bodyis the exact byte sequence of the JSON payload (before parsing)
Signature Format
TheX-Webhook-Signature header contains two components:
t: The timestamp when the signature was generatedv1: The HMAC-SHA256 signature in hexadecimal format
Verification Steps
To verify a webhook request is authentic, follow these steps:- Extract the timestamp and signature from the
X-Webhook-Signatureheader - Verify the timestamp is within an acceptable time window (recommended: ±5 minutes) to prevent replay attacks
- Reconstruct the signed string by concatenating the timestamp, a period, and the raw request body
- Compute the HMAC-SHA256 using your shared secret
- Compare signatures using a constant-time comparison function to prevent timing attacks
- Check the X-Webhook-ID (optional but recommended) to prevent duplicate processing
Implementation Examples
Python
Node.js (Express)
Security Best Practices
1. Use HTTPS Only
Always use HTTPS endpoints for webhooks. We reject HTTP URLs to prevent man-in-the-middle attacks.2. Validate the Timestamp
Always verify the timestamp is within an acceptable window (recommended: ±5 minutes). This prevents replay attacks where an attacker attempts to resend a captured webhook.3. Use Constant-Time Comparison
Always use constant-time comparison functions (likehmac.compare_digest in Python or crypto.timingSafeEqual in Node.js) when comparing signatures. This prevents timing attacks.
4. Store the Secret Securely
- Generate a cryptographically secure random secret (32 bytes / 256 bits)
- Store it encrypted using a key management service (KMS, HashiCorp Vault, etc.)
- Never commit secrets to version control
- Rotate secrets periodically
5. Implement Idempotency
Use theX-Webhook-ID header to track which webhooks you’ve already processed. Store this ID in your database and reject duplicate deliveries.
6. Verify the Raw Body
The signature is computed over the raw request bytes, not the parsed JSON. Make sure your verification code uses the exact body bytes received, before any parsing or transformation.7. Return Appropriate Status Codes
- Return
200or204for successful processing - Return
401for signature verification failures - Return
400for malformed requests - Return
500for internal server errors
Troubleshooting
Signature Verification Fails
Common causes:- Using parsed JSON instead of raw request body for verification
- Incorrect timestamp extraction or format
- Secret key mismatch
- Using string concatenation instead of proper byte operations
- Not using UTF-8 encoding consistently
- Ensure you’re computing the HMAC over the exact raw bytes received
- Verify your secret key matches what was configured
- Check that you’re extracting the timestamp correctly from the header
- Use logging to compare your computed signature with the received signature
Timestamp Out of Range
Common causes:- Server clock drift
- Processing delays
- Timezone issues
- Synchronize your server clock using NTP
- Use Unix timestamps (seconds since epoch) in UTC
- Adjust your tolerance window if needed (but don’t exceed 10 minutes)
Duplicate Webhooks
Common causes:- Network issues causing retries
- Not implementing idempotency checks
- Track
X-Webhook-IDvalues in your database - Implement idempotent webhook handlers that can safely process the same event multiple times
Testing Webhooks
When testing webhook integration, you can use tools like:- ngrok or localtunnel to expose your local server to receive webhooks
- Request logging to inspect the exact headers and body received
- Manual signature generation to test your verification logic