A webhook signature covers the exact request bytes Fillo sent. Parsing the JSON and serializing it again changes those bytes, even when the object looks identical.
Verify before parsing
- Read the request body as raw bytes or text.
- Read the Fillo signature header exactly as documented by the webhook endpoint.
- Compute the expected HMAC with that endpoint's current signing secret.
- Compare the provided and expected values with a constant-time comparison.
- Only then parse the JSON and dispatch the event.
import { createHmac, timingSafeEqual } from "node:crypto";
const expected = createHmac("sha256", process.env.FILLO_WEBHOOK_SECRET!)
.update(rawBody)
.digest("hex");
const providedBuffer = Buffer.from(providedSignature, "hex");
const expectedBuffer = Buffer.from(expected, "hex");
const valid = providedBuffer.length === expectedBuffer.length
&& timingSafeEqual(providedBuffer, expectedBuffer);Use the header name and encoding shown for the live webhook configuration. Don't strip prefixes or convert encodings until you've compared them against the received value.
Common causes
- A framework JSON body parser ran before the verifier.
- The secret belongs to a different destination, workspace, or environment.
- The copied secret picked up whitespace or dropped a character.
- A reverse proxy decompressed, decoded, or otherwise changed the body.
- Test tooling supplied a JSON object instead of the captured raw payload.
When you rotate a secret, allow for in-flight deliveries if your deployment can't change atomically. Keep both values private and remove the previous one promptly after verification.
Signature checks aren't deduplication
A valid event can be delivered again. Store the event or response identity your handler has processed and make downstream effects idempotent. Return a successful status only after the event is durably accepted — a timeout after your commit can cause Fillo to retry.
Related
- Webhooks: Configure endpoints, events, retries, and payload handling.
- Delivery health and replay: Inspect terminal failures after verification is repaired.
- Security: Keep signing secrets out of logs and client bundles.