V
Voxtar DevelopersAPI Reference / v1
Webhooksv1

Security

Because webhook events can carry patient-derived signals, every delivery is signed. Verify the signature before trusting a payload — it proves the request came from Voxtar and was not altered in transit.

Signature header

Each delivery includes a Voxtar-Signature header: a timestamp and an HMAC-SHA256 of {timestamp}.{raw_body}, keyed with your endpoint's signing secret (shown once when you create the webhook).

Voxtar-Signature: t=1752226002,v1=3b8f...c1a9

Verifying

Recompute the HMAC over the raw request body and compare in constant time. Reject if the timestamp is more than five minutes old to prevent replay.

import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody, header, secret) {
const [t, sig] = header.split(",").map((p) => p.split("=")[1]);
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const expected = createHmac("sha256", secret)
.update(t + "." + rawBody)
.digest("hex");
return timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

Good practice

Verify against the raw body (not a re-serialized object), serve your endpoint over HTTPS, rotate the signing secret if it may have leaked, and scope the receiving service so it can only enqueue work — never expose it publicly beyond what Voxtar needs to reach.