Guides

Verify incoming webhooks

Check every request's authenticity before it is stored or delivered.

Anyone who learns a source URL can post to it. Verification proves a request came from the sender you expect, before Ensue stores it or creates an event. A request that fails is refused with 401, logged with the reason, and never delivered.

Verification methods

Set the method with auth_type when you create or update a source.

auth_type Use it when the sender…
none doesn’t sign requests. Fine for testing, not for production.
stripe is Stripe. Checks the Stripe-Signature header (t=…,v1=…) with the endpoint’s whsec_ secret.
hmac signs the body with a shared secret in a header, as GitHub does.
hmac_ts signs a timestamp plus the body, with a replay window.
standard follows the Standard Webhooks scheme (webhook-id, webhook-timestamp, webhook-signature). Svix senders, which use the same scheme under svix-* header names, work too.
bearer sends Authorization: Bearer <token>.
basic sends a username and password.
apikey sends a fixed key in a header you name.

Set it up

  1. Open the source and choose Verification.
  2. Select the method and enter the secret or token the sender uses.
  3. Save, then trigger a test event from the sender.

Over the API:

curl -X POST https://api.getensue.com/v1/sources \
  -H "authorization: Bearer ens_<key>" -H "content-type: application/json" \
  -d '{
    "name": "github-main",
    "auth_type": "hmac",
    "header": "x-hub-signature-256",
    "prefix": "sha256=",
    "encoding": "hex",
    "secret": "<shared secret>"
  }'

HMAC options

Field Meaning
header The header that carries the signature.
prefix Text before the signature in the header, such as sha256=.
encoding hex (default) or base64.

Standard Webhooks options

tolerance sets how many seconds the timestamp may differ from Ensue’s clock, from 0 to 3600. The default is 300. A request outside the window is refused with a message naming the tolerance, which stops an attacker replaying a captured request later.

Check what happened

A refused request shows in the source’s log with its reason, for example a missing header or a signature mismatch. The log keeps the request’s headers and body so you can compare it against what the sender documents.

Rotating secrets

Update the secret in Ensue and at the sender at the same time. Requests signed with the old secret are refused as soon as you save. If the sender supports two active secrets, add the new one at the sender first, update Ensue, then remove the old one.

Verifying Ensue’s own requests

Verification works in both directions. Ensue signs what it delivers to your destinations with x-ensue-signature; see Destinations. To verify in your service, compute the HMAC-SHA256 of "<timestamp>.<raw body>" with the destination’s secret, compare it in constant time with the v1 value, and reject old timestamps.