Webhooks
Security
Every webhook delivery includes a Svix-compatible signature so you can verify it originated from eusend.
Every webhook delivery includes a signature so you can verify it originated from eusend. The signature scheme is Svix-compatible.
Headers
| Parameter | Type | Description |
|---|---|---|
webhook-id | string | Unique delivery ID for this event. |
webhook-timestamp | string | Unix timestamp (seconds) of delivery time. |
webhook-signature | string | HMAC-SHA256 signature prefixed with v1,. |
Verification
The signature is computed as
HMAC-SHA256(secret, "{webhook-id}.{webhook-timestamp}.{body}"), then
base64-encoded and prefixed with v1,. The webhook-id and webhook-timestamp
values are the ones sent in the request headers (each delivery has a unique
webhook-id).
import { createHmac } from 'crypto'
function verifyWebhook(req, secret) {
const id = req.headers['webhook-id']
const timestamp = req.headers['webhook-timestamp']
const signature = req.headers['webhook-signature']
const body = req.rawBody // must be the raw string, not parsed JSON
const signed = `${id}.${timestamp}.${body}`
const expected = 'v1,' + createHmac('sha256', secret)
.update(signed)
.digest('base64')
// Constant-time comparison to prevent timing attacks
if (expected !== signature) throw new Error('Invalid webhook signature')
return JSON.parse(body)
}✦
Always compare signatures using a constant-time comparison function to prevent
timing-based attacks. In Node.js use crypto.timingSafeEqual().