# Verify webhook signatures

Verify HMAC signatures, check timestamps, and handle duplicate webhooks.

## Preserve the raw body
Verify the received bytes before parsing/re-serializing JSON. Even whitespace changes the MAC. Configure your framework's raw-body handling accordingly.

## Headers
Use `Tembuilder-Event`, `Tembuilder-Delivery-Id`, `Tembuilder-Attempt`, `Tembuilder-Timestamp` and `Tembuilder-Signature`. The signature is `v1=` plus a hex HMAC-SHA256. The revealed signing secret is unpadded base64url; decode it into bytes first.

## Signed bytes
```text
timestamp + "." + raw_body
```

Compute HMAC-SHA256 with the decoded secret and compare in constant time.

## Timestamp and duplicates
Apply an appropriate receiver acceptance window, for example ±5 minutes when suitable for your clocks and operation. This is receiver guidance, not a Tembuilder delivery-time guarantee. Deduplicate delivery IDs and reconcile business state by render ID. Do not assume exactly-once or in-order notifications.

## Test before production
Accept a correctly signed test. Reject a one-byte body change and stale timestamp. Deliver the same ID twice and verify business side effects are not duplicated. Keep secrets and sensitive payloads out of logs.
