API Docs
Webhooks
API ReferenceWebhooksVerification

Signature Verification

Verify webhook authenticity using HMAC signatures.

How It Works

Every webhook request includes an X-Uprails-Signature header containing an HMAC-SHA256 signature of the request body. Verify this signature to ensure the webhook was sent by Uprails.

Verification Steps

  1. Extract the X-Uprails-Signature header from the request
  2. Compute an HMAC-SHA256 of the raw request body using your webhook secret
  3. Compare the computed signature with the one in the header
  4. Reject the request if signatures don't match

Code Examples

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler:
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-uprails-signature'];

  if (!verifyWebhookSignature(req.body, signature, WEBHOOK_SECRET)) {
    return res.status(400).send('Invalid signature');
  }

  // Process the event...
  res.status(200).send('OK');
});
import hmac
import hashlib

def verify_webhook_signature(payload, signature, secret):
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected)

# In your webhook handler:
@app.route('/webhooks', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Uprails-Signature')

    if not verify_webhook_signature(request.data, signature, WEBHOOK_SECRET):
        return 'Invalid signature', 400

    # Process the event...
    return 'OK', 200
<?php
function verifyWebhookSignature($payload, $signature, $secret) {
    $expected = hash_hmac('sha256', $payload, $secret);
    return hash_equals($expected, $signature);
}

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_UPRAILS_SIGNATURE'];

if (!verifyWebhookSignature($payload, $signature, WEBHOOK_SECRET)) {
    http_response_code(400);
    echo 'Invalid signature';
    exit;
}

// Process the event...
http_response_code(200);
echo 'OK';

Always verify webhook signatures in production. Never skip verification, as it protects against forged webhook requests.