Verify signatures
Validate Styrar-Signature on every delivery with HMAC-SHA256.
The signature follows a Stripe-style scheme. It signs "{timestamp}.{raw_body}" with HMAC-SHA256 using your endpoint secret.
- Parse
Styrar-Signatureintot(unix timestamp) andv1(hex digest). - Reject if
tis outside your tolerance (we recommend 5 minutes). - Compute the expected digest and compare with
v1using a constant-time check.
JavaScript
import crypto from 'node:crypto'
function verifyStyrarWebhook(secret, signatureHeader, rawBody, toleranceSeconds = 300) {
const parts = Object.fromEntries(
signatureHeader.split(',').map((part) => part.trim().split('=')),
)
const timestamp = Number(parts.t)
const receivedDigest = parts.v1 || ''
if (!Number.isFinite(timestamp)) return false
if (Math.abs(Date.now() / 1000 - timestamp) > toleranceSeconds) return false
const expectedDigest = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex')
try {
return crypto.timingSafeEqual(
Buffer.from(expectedDigest, 'utf8'),
Buffer.from(receivedDigest, 'utf8'),
)
} catch {
return false
}
}
Always verify against the raw request body before parsing JSON.
Reliability
- Deliveries are at-least-once. Deduplicate using
Styrar-Event-Idor the envelopeid. - Failed deliveries retry with exponential backoff until success or max attempts.
- If your server returns HTTP 410, Styrar disables the endpoint automatically.
- Respond with 2xx as soon as you have accepted the event; process heavy work asynchronously.
Limits
- HTTPS required in production for callback URLs.
- 25 endpoints per personal or company workspace scope.
- Signing secrets are shown once on create and rotate; store them in your secrets manager.