Webhook Verification

Validate raw signed deliveries before updating local state
View as Markdown

Webhook handling should be intentionally strict: verify first, then trust the payload.

Why this pattern

  • the SDK checks HMAC signature and timestamp freshness
  • the app preserves the exact raw request body for verification
  • downstream handlers switch on a typed eventType
  • local state changes happen only after signature validation succeeds
1import { readFile } from "node:fs/promises";
2
3const rawBody = await readFile(rawBodyPath, "utf8");
4const webhookUrl =
5 `${config.publicBaseUrl ?? `http://127.0.0.1:${config.port}`}` +
6 "/v1/webhooks/gwop";
7
8const event = await webhooks.validateWebhook({
9 rawBody,
10 headers: {
11 "x-gwop-signature": signature,
12 "x-gwop-event-id": eventId,
13 "x-gwop-event-type": eventType,
14 },
15 url: webhookUrl,
16 method: "POST",
17});
18
19console.log(event.body.eventType);
20console.log(event.body.data.invoiceId);
21console.log(event.body.data.publicInvoiceId);

Do not parse and re-stringify the JSON before verification. The signature is computed over the original raw request body bytes.