Signature Verification
Every webhook request includes an X-Formtorch-Signature header. This is an HMAC-SHA256 signature of the raw request body, signed with your webhook secret.
Always verify this signature before processing any webhook payload.
How it works
- Formtorch signs the raw request body using HMAC-SHA256 with your webhook secret
- The signature is sent in the
X-Formtorch-Signatureheader assha256=<hex> - Your server recomputes the signature and compares it to the header value
Verification examples
Node.js
lib/verify-webhook.ts
import { createHmac, timingSafeEqual } from "crypto";
export function verifyWebhookSignature(
body: string,
signature: string,
secret: string
): boolean {
const expected = `sha256=${createHmac("sha256", secret)
.update(body)
.digest("hex")}`;
// Use timing-safe comparison to prevent timing attacks
return timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}Usage in a Next.js route handler:
app/api/webhooks/formtorch/route.ts
import { verifyWebhookSignature } from "@/lib/verify-webhook";
export async function POST(req: Request) {
const body = await req.text();
const signature = req.headers.get("x-formtorch-signature") ?? "";
if (
!verifyWebhookSignature(
body,
signature,
process.env.FORMTORCH_WEBHOOK_SECRET!
)
) {
return new Response("Unauthorized", { status: 401 });
}
const event = JSON.parse(body);
// handle event...
return new Response("OK");
}Important: read the raw body
Signature verification requires the raw request body string, not the parsed JSON. If you parse the body first, the string representation may differ and the check will fail.
In Express, use express.raw({ type: 'application/json' }) on the webhook
route instead of express.json(). In Next.js, call req.text() before
JSON.parse().
Where to find your webhook secret
Go to Form Settings → Webhooks in the dashboard. Click the endpoint to reveal its secret. If you lose the secret, delete the endpoint and create a new one.
Last updated on