Skip to main content
Every delivery carries an X-Elapse-Signature header:
  • t is the Unix time the delivery was signed.
  • v1 is HMAC-SHA256(secret, "{t}.{raw_body}"), hex encoded. There may be more than one v1 during a secret roll; any one matching is enough.
  • The secret is the endpoint’s whsec_…, shown once when you create the endpoint in the dashboard, or printed by elapse listen.
Verification rejects a header older than 300 seconds, and compares in constant time. Sign the raw body bytes: a body re-serialised by a JSON middleware will not match.

With the SDK

constructEvent accepts a string or a byte buffer, one secret or an array of them for a roll, and returns the parsed event only after the signature passes. Two frameworks that eat the raw body by default:

Verify by hand

This vector is checked by the SDK’s own test suite, so it cannot go stale.
raw body, exactly these bytes
Both print the v1 above.

Rolling a secret

Roll from the dashboard with a grace period of 0, 1 or 24 hours. During the grace period deliveries carry two v1 values, one per secret, so pass both secrets to constructEvent and swap the old one out when the window closes.