Skip to main content
Every delivery is signed with the secret that belongs to the endpoint it was sent to, so your handler can tell a real delivery from a forged request. To get that secret from the panel:
  1. Open Dashboard, Webhooks and register the endpoint you want called.
  2. Copy the whsec_ value from the dialog that confirms it.
It is shown in full once, at creation and again on each rotation. Store it before you close the dialog, then deploy the handler that reads it. If you no longer hold it, rotate the endpoint and keep what that call returns.

How to verify

Verify against the raw request body, not a parsed object that you serialise again. Re-serialising changes key order and whitespace, and the signature no longer matches, so read the body as text before any JSON middleware touches it.
string
required
HMAC-SHA256(secret, "{timestamp}.{rawBody}"), hex encoded.
string
required
Unix seconds at the moment the delivery was signed.
Then send a test event and confirm your handler accepts it. It travels the same signed path as a real delivery, so a signature that verifies there verifies in production. Once it checks out, Webhooks describes the body you can trust.

Why verify

Anyone who learns your endpoint URL can post a body to it that looks like ours. The signature is what separates the two, because it can only be produced by a party holding that endpoint’s secret. A genuine delivery can also be captured and sent again later. The timestamp is what closes that door: it is covered by the signature, so refusing anything older than a few minutes costs an attacker the whole replay. Compare in constant time. A comparison that returns on the first differing byte tells a caller how much of the expected value a guess got right. A request that fails any of these checks is not from us. Return 400 and leave the body alone.

Rotate the signing secret

Issue a new secret and read it once.

Send a test event

Exercise your handler on the real signed path.