Webhook Authentication
All webhooks sent by our system include a signature header named X-SIGNATURE to verify authenticity. The signature is computed using HMAC SHA-256 with the provided API_SECRET. Specifically, the signature is generated from the raw webhook body (as a string, without extra spaces) using the secret key. The signature can be generated with the following code:
public static class SignatureGenerator
{
public static string GenerateSignatureForCallback(string rawBody, string secretKey)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey));
var signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(rawBody));
return Convert.ToBase64String(signatureBytes);
}
}
function generateSignatureForCallback(rawBody, secretKey) {
const hmac = require('crypto').createHmac('sha256', secretKey);
hmac.update(rawBody, 'utf8');
return hmac.digest('base64');
}
function generateSignatureForCallback($rawBody, $secretKey) {
return base64_encode(hash_hmac('sha256', $rawBody, $secretKey, true));
}
def generate_signature_for_callback(raw_body, secret_key):
import hmac, hashlib, base64
signature = hmac.new(secret_key.encode(), raw_body.encode(), hashlib.sha256).digest()
return base64.b64encode(signature).decode()
public class SignatureGenerator {
public static String generateSignatureForCallback(String rawBody, String secretKey) throws Exception {
javax.crypto.Mac sha256_HMAC = javax.crypto.Mac.getInstance("HmacSHA256");
javax.crypto.spec.SecretKeySpec secretKeySpec = new javax.crypto.spec.SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secretKeySpec);
byte[] hashBytes = sha256_HMAC.doFinal(rawBody.getBytes("UTF-8"));
return java.util.Base64.getEncoder().encodeToString(hashBytes);
}
}
When you receive a webhook, compute the HMAC SHA-256 of the body using the API_SECRET and compare it to the X-SIGNATURE header to ensure the webhook is genuine and untampered.
08 January 2026