eusend
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

ParameterTypeDescription
webhook-idstringUnique delivery ID for this event.
webhook-timestampstringUnix timestamp (seconds) of delivery time.
webhook-signaturestringHMAC-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).

node.js verification
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().