Every webhook Sly sends is HMAC-signed. You MUST verify the signature before trusting the payload — otherwise an attacker could POST forged events to your endpoint.
Sly includes two headers on every delivery:
t — Unix timestamp of signing
v1 — HMAC-SHA256 signature of {timestamp}.{raw_body} using your webhook secret
Verification algorithm
Node.js (with SDK)
verifyWebhook throws on any failure (stale, malformed, or bad signature).
Node.js (manual, no SDK)
Use the raw body. If your framework parses JSON before handing it to you, re-serialization will change whitespace and break the signature. Register the webhook route with a raw-body parser or read from the stream directly.
Python
Ruby
Where to find your secret
From the dashboard: Settings → Webhooks → [endpoint] → Secret. Or from the API:
Rotating secrets
Create a new secret before rotating:
Overlap mode accepts both old and new secrets for overlap_seconds. Deploy the new secret during the overlap, verify, then let the old one expire.
Common pitfalls
- Parsing the body before verifying. Most frameworks do this by default. Opt out for the webhook route.
- Timing-unsafe comparison. Always use
crypto.timingSafeEqual / hmac.compare_digest / fixed_length_secure_compare.
- Clock drift. If your server clock is more than 5 minutes off, every webhook will fail verification. Use NTP.
- Stripping headers at the proxy. Check your reverse proxy or WAF isn’t removing
X-Sly-* headers.