Skip to main content
In order to be able to verify that a webhook request is actually sent by Payt, and has not been modified since, a signature is included in each request. This signature is calculated based on the JSON payload and a secret key, and sent in the X-PAYT-SIGNATURE header. The secret key can be obtained on the settings page of the webhooks, it is shown only once after generating it. If you lose the secret or if it has been compromised a new one can be created on the settings page. Note that there may be a short delay before the new secret takes effect for all webhook requests. Due to the asynchronous nature of the webhooks you might receive requests using either the old or new secret for a while. Webhook requests are retried automatically and these retries will pick up the new secret. When all retries are exhausted they can be retried manually. The failed requests can be found on the settings page of the corresponding webhook. To verify the signature, take the secret and the body of the request and generate an HMAC hexdigest using the SHA256 method. The generated hash can then be used to safely compare it against the value in the X-PAYT-SIGNATURE header. Make sure not to parse the body of the request before generating the hash, it must be calculated on the raw request body as it is received.
const crypto = require("crypto");

// rawBody must be the request body exactly as received, before any JSON parsing
function verifySignature(rawBody, signatureHeader, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(signatureHeader, "hex")
  );
}
Last modified on June 15, 2026