Skip to main content
Every webhook request includes a signature so you can verify it was sent by Formable and wasn’t tampered with in transit. Always verify the signature before acting on a webhook.

How signing works

Formable computes an HMAC-SHA256 over the exact raw JSON body of the request, using your endpoint’s signing secret as the key, and encodes the result as base64. That value is sent in the Content-Sha256 header.
Your signing secret is provided as a base64-encoded string. Decode it to raw bytes and use those bytes as the HMAC key.
To verify a request:
1

Read the raw body

Capture the request body exactly as received, before any JSON parsing or re-serialization. Re-serializing can change whitespace or key order and break verification.
2

Compute the expected signature

HMAC-SHA256 the raw body using the base64-decoded secret as the key, then base64-encode the digest.
3

Compare

Compare your computed value with the Content-Sha256 header using a constant-time comparison. If they match, the request is authentic.

Examples

Common pitfalls

Frameworks that auto-parse JSON discard the original bytes. Re-serializing the parsed object almost always produces a slightly different string (whitespace, key order), so the HMAC won’t match. Always sign over the raw request body.
The secret is a base64 string. Use its decoded bytes as the HMAC key — don’t pass the base64 string directly.
Compare signatures with a constant-time function (crypto.timingSafeEqual, hmac.compare_digest) to avoid timing attacks.
Keep your signing secret confidential and store it as an environment secret. If you believe it has been exposed, contact support@formabledocs.com to rotate it.