Skip to main content
Every delivery from Flexprice Cloud carries an HMAC-SHA256 signature computed with your endpoint’s signing secret. Verifying it proves the request came from Flexprice and that the body was not changed in transit. Reject anything that fails; do not fall back to processing an unsigned body.

The webhook signature headers

The secret is shown on the endpoint’s page in the dashboard and starts with whsec_. Each endpoint has its own.

Verifying the signature with the Svix library

The simplest route. The library checks the signature, tolerates a five-minute clock skew, and rejects replays outside that window.
Install with npm i svix, pip install svix, or go get github.com/svix/svix-webhooks/go.
Verify the raw request body. Frameworks that parse JSON before your handler runs hand you a re-serialized string whose bytes differ from what was signed, and verification fails. In Express use express.raw() for the webhook route; in FastAPI read await request.body(); in Next.js App Router read await req.text().

Verifying the webhook signature by hand

If you would rather not add a dependency, the algorithm is short:
  1. Strip the whsec_ prefix from the secret and base64-decode the rest. That is the HMAC key.
  2. Build the signed content: ${svix-id}.${svix-timestamp}.${raw body}.
  3. Compute HMAC-SHA256 over the signed content with the key and base64-encode the result.
  4. Compare it, in constant time, against each v1,... entry in svix-signature. One match is enough.
  5. Reject if svix-timestamp is more than five minutes from now.

Rotating a webhook signing secret

Rotate from the endpoint’s page in the dashboard. For a grace period, deliveries are signed with both the old and the new secret and svix-signature carries two v1 entries. Deploy the new secret to your handler during that window; a handler that accepts any matching entry keeps working throughout.

Signature verification on self-hosted deployments

Flexprice Cloud always delivers through Svix. A self-hosted instance uses Svix only if you enable it in configuration; otherwise it uses native delivery, which sends the JSON body with the headers configured for the tenant and no signature. To authenticate native deliveries, configure a static secret header on the tenant’s webhook settings and check it in your handler, or enable Svix. See Configuration.

Retries and ordering

Svix verification reference