Webhook Signature Verification

To ensure that webhook requests originate from our platform and have not been modified during transmission, every webhook request is signed using an HMAC-SHA256 signature.

Headers

Each webhook request includes the following HTTP headers:

HeaderDescription
X-TimestampUnix timestamp (seconds) indicating when the signature was generated.
X-SignatureHMAC-SHA256 signature generated using your webhook secret.

Signature Generation

The signature is generated using the following formula:

signature = HMAC_SHA256(timestamp + "." + request_body, webhook_secret)

Where:

  • timestamp is the value of the X-Timestamp header.
  • request_body is the exact raw HTTP request body.
  • webhook_secret is the shared secret configured for your webhook endpoint.

Code Samples

<?php

$signature = $_SERVER['HTTP_X_SIGNATURE'] ?? null;
$timestamp = $_SERVER['HTTP_X_TIMESTAMP'] ?? null;
$encoded = json_encode($_POST, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
$hash = hash_hmac('sha256', $timestamp . '.' . $encoded, $secretKey);
if (hash_equals($hash, $signature)) {
  // YOUR CODE HERE
} else {
  echo "Invalid signature";
}

Preventing Replay Attacks

We strongly recommend validating the timestamp before verifying the signature. Reject requests whose timestamp is outside an acceptable window (for example, 5 minutes).

<?php

if (time() - (int) $timestamp > 300) {
    echo "Request expired";
}

Important Notes

  • Always use the raw request body exactly as received.
  • Perform the comparison using a constant-time comparison function (for example, PHP's hash_equals()).


Did this page help you?