Documentation Index
Fetch the complete documentation index at: https://docs.fernhq.com/llms.txt
Use this file to discover all available pages before exploring further.
Signature Headers
Each webhook HTTP request includes the following headers to assist with verification:x-api-signature– The HMAC SHA-256 signature of the payload (hex-encoded). This is what you will compare against your own computed signature.x-api-timestamp– The UNIX timestamp (in seconds or milliseconds) at which the request was sent. This is used in the signature computation and to prevent replay attacks.
x-api-timestamp and ensure it is within an acceptable range (for example, within 1 minutes of your server’s current time) before trusting the webhook. If the timestamp is too far out-of-sync, it could indicate a replay attack or an extremely delayed request, and you may want to ignore it. Also, use the payload id to guard against processing the same event twice.
Signature Generation (TypeScript)
Fern generates thex-api-signature header by computing an HMAC using SHA-256. The signing string is composed of the timestamp and the request body, separated by a dot. In pseudo-code, Fern does:
SHA-256 algorithm with your webhook secret. The output is a hexadecimal string. Fern performs this same computation for each webhook it sends. Your goal in verification is to perform the same computation and compare the result with the signature provided by Fern.
Signature Validation (TypeScript)
To validate a webhook in your handler, follow these steps:- Retrieve the headers and body: Get the
x-api-signatureandx-api-timestampfrom the request headers, and get the raw request body string. - Recompute the signature: Use your secret and the received timestamp and body to compute the expected signature (using a function like
generateSignatureabove). - Compare signatures securely: Check if the computed signature matches the X-Api-Signature from the header. Use a constant-time comparison to avoid timing attacks.
- Check timestamp freshness: Verify that the timestamp from
x-api-timestampis recent (e.g., within the last few minutes). If it’s too old or far in the future, you may reject the request as a replay attempt. - Process the webhook if valid: Only if the signature is valid and the timestamp is acceptable should you proceed to process the webhook (e.g., update your database or trigger other actions). If verification fails, you should reject the request (e.g., respond with 4xx status) or ignore it.\
generateSignature is the function defined in the previous section. We compare the signatures using crypto.timingSafeEqual which helps prevent timing attacks by making sure the comparison takes the same amount of time regardless of how much of the string matches. We also ensure the buffers are of equal length before comparing (as a safety check).