Skip to content

Webhooks

Validate Webhooks

Last updated 4 June 2026

Webhooks notify your systems in real time when account and transaction events occur. Every delivery is signed — always validate the signature before trusting the payload.

Signature scheme

Each request carries a Webhook-Signature header. Xace signs the concatenation of the delivery timestamp and the raw event body using RSA with SHA-512, then Base64-encodes the result:

Webhook-Signature headertext
Webhook-Signature: Base64(RSA512(_WEBHOOK_PRIVATE_KEY_, SHA512(timestamp + eventBody)))

Verifying a delivery

Recompute the signature over the exact raw request body (do not re-serialize the JSON) prefixed with the timestamp, then verify it against your workspace public key:

verify-webhook.jsjavascript
const crypto = require('crypto');

// rawBody must be the exact bytes received, not a re-stringified object.
function isValidWebhook({ rawBody, timestamp, signature, publicKeyPem }) {
  const verifier = crypto.createVerify('RSA-SHA512');
  verifier.update(timestamp + rawBody);
  verifier.end();
  return verifier.verify(publicKeyPem, signature, 'base64');
}

Production public key

Validate Production deliveries with the public key for your Production workspace. Replace the placeholder below with the key shown in your workspace settings.

production-public-key.pemtext
-----BEGIN PUBLIC KEY-----
<your Production workspace public key>
-----END PUBLIC KEY-----

Reject stale and tampered deliveries

Compare signatures in constant time, reject any delivery whose timestamp is older than a few minutes to prevent replay attacks, and always verify over the raw body bytes — re-serializing the JSON will change the signature and verification will fail.

Was this page helpful?
Suggest edits