Signup webhooks
Pro waitlists can POST each confirmed signup to your URL. Requests use safeFetch (HTTPS only, private IPs blocked).
Headers
X-Timestamp— Unix seconds when we signedX-Signature—sha256=+ hex HMAC-SHA256 of${timestamp}.${rawBody}using your per-list secretx-waitlist-kit-event—signup.confirmed
Signing secret
Each waitlist has its own secret (32+ random bytes). Create or rotate it from the waitlist dashboard. We show the plaintext once. Existing lists created before this feature have no secret until you rotate; those deliveries omit signature headers until then.
The secret is stored encrypted. It is never logged. Auth secret rotation does not break webhook verification.
Verify in Node
import crypto from "node:crypto";
function verify(req, secret) {
const timestamp = req.headers["x-timestamp"];
const signature = String(req.headers["x-signature"] || "").replace(/^sha256=/, "");
const body = typeof req.body === "string" ? req.body : JSON.stringify(req.body);
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${body}`)
.digest("hex");
const a = Buffer.from(expected, "utf8");
const b = Buffer.from(signature, "utf8");
if (a.length !== b.length) return false;
return crypto.timingSafeEqual(a, b);
}