Developer Preview · Test and pilot use only
V VelarumPay Docs
Webhook HMAC · SHA-256

Verify the exact raw request body before processing an event

VelarumPay signs timestamp + "." + rawBody. The signature is carried in x-velarumpay-signature as t=<unix-seconds>,v1=<hex-hmac>.

Keep endpoint secrets in a server-side secret manager. Never expose them to browser code, mobile clients, logs, error responses, or documentation. The downloadable vector uses an intentionally public non-production test key.

Node.js verification

import { createHmac, timingSafeEqual } from "node:crypto";

function verifyWebhook(publicOrSecretKey, rawBody, signatureHeader, nowSeconds) {
  const parts = Object.fromEntries(signatureHeader.split(",").map((part) => {
    const [name, ...value] = part.trim().split("=");
    return [name, value.join("=")];
  }));
  if (!/^\d{10,16}$/.test(parts.t || "") || !/^[0-9a-f]{64}$/i.test(parts.v1 || "")) return false;
  if (Math.abs(nowSeconds - Number(parts.t)) > 300) return false;

  const expected = createHmac("sha256", publicOrSecretKey)
    .update(Buffer.from(`${parts.t}.`, "utf8"))
    .update(rawBody)
    .digest();
  const supplied = Buffer.from(parts.v1, "hex");
  return expected.length === supplied.length && timingSafeEqual(expected, supplied);
}

Pass the original bytes from the HTTP framework. Parsing and re-serializing JSON changes the byte sequence and invalidates the signature. Reject stale timestamps before business processing.

Headers and replay handling

HeaderUse
x-velarumpay-signatureTimestamped HMAC described above.
x-velarumpay-event-idStable event identity; deduplicate business processing on this value.
x-velarumpay-delivery-idUnique attempt identity for delivery diagnostics.

Return a 2xx response only after durable acceptance. Retries and manual replay may produce new delivery IDs for the same event ID. Always reconcile final Payment Request state through the authenticated REST API.

Fixed HMAC vector

Download the public deterministic HMAC vector. Its exact raw body, timestamp, signed payload, and expected header are checked during the docs build. The test key is public and must never be used for an endpoint.

Endpoint lifecycle

Use createWebhookEndpoint, verifyWebhookEndpoint, rotateWebhookSecret, and revokeWebhookEndpoint through the merchant session boundary. Rotation and revocation require step-up authentication; overlap is bounded and old secrets expire.