Signature verification
# Signature verification
Self signs every webhook delivery with HMAC-SHA256. Verify the signature before trusting the payload, and don't roll your own check, the SDK does it correctly in one call.
## What the SDK verifies
* The signature matches the raw request body and your `whsec_...` signing secret.
* The timestamp is recent (a 5-minute tolerance, which defends against replay).
## Node
```ts
import { SelfWebhooks } from '@selfxyz/enterprise-sdk';
const event = SelfWebhooks.verify(rawBody, headers, secret);
```
`SelfWebhooks.verify` reads the signature and timestamp off the request headers for you, so just pass the request headers through unchanged. See [SDK: Verify webhooks](/docs/self-enterprise/sdk/verify-webhooks/) for the full setup including raw-body wiring.
## Rotating the secret
The signing secret is shown once, at endpoint creation. To roll the secret, delete the endpoint and recreate it, then update `SELF_WEBHOOK_SECRET` in your handler and redeploy.
## Common failure modes
* **Parsed body.** Verification runs on bytes; if your framework JSON-parsed the body, the canonical form is lost. Capture `rawBody` before parsing.
* **Trimming or transforming.** A trailing newline added by your proxy will break the signature. Configure the proxy to pass the body unchanged.
* **Wrong secret.** Each endpoint has its own. Triple-check you're using the right one.
* **Clock skew.** A drifted server clock can fail the timestamp tolerance check. Make sure NTP is healthy.
Self signs every webhook delivery with HMAC-SHA256. Verify the signature before trusting the payload, and don’t roll your own check, the SDK does it correctly in one call.
What the SDK verifies
- The signature matches the raw request body and your
whsec_...signing secret. - The timestamp is recent (a 5-minute tolerance, which defends against replay).
Node
import { SelfWebhooks } from '@selfxyz/enterprise-sdk';
const event = SelfWebhooks.verify(rawBody, headers, secret);
SelfWebhooks.verify reads the signature and timestamp off the request headers for you, so just pass the request headers through unchanged. See SDK: Verify webhooks for the full setup including raw-body wiring.
Rotating the secret
The signing secret is shown once, at endpoint creation. To roll the secret, delete the endpoint and recreate it, then update SELF_WEBHOOK_SECRET in your handler and redeploy.
Common failure modes
- Parsed body. Verification runs on bytes; if your framework JSON-parsed the body, the canonical form is lost. Capture
rawBodybefore parsing. - Trimming or transforming. A trailing newline added by your proxy will break the signature. Configure the proxy to pass the body unchanged.
- Wrong secret. Each endpoint has its own. Triple-check you’re using the right one.
- Clock skew. A drifted server clock can fail the timestamp tolerance check. Make sure NTP is healthy.
Was this page helpful?
Thanks for your feedback!