Skip to content

Receive transactional email events

Eza posts delivery events to your webhook endpoint and signs every request.

Eza webhooks are not Resend-compatible. Events are also available in the dashboard log, as a CSV export and from a paginated API endpoint.

  • Beta
  • Sending API
  • SMTP relay

Events

Supported events

  • email.delivered
  • email.bounced
  • email.complained

Signature

Verify the signature

Request header
Eza-Signature: t=<timestamp>,v1=<signature>

Calculate HMAC-SHA256 using the timestamp, a period and the raw request body. Compare it with the signature using the endpoint signing secret. Reject timestamps older than 5 minutes.

verify.ts
import { createHmac, timingSafeEqual } from 'node:crypto' export function verify(header, rawBody, secret) {  const parts = Object.fromEntries(    header.split(',').map((part) => part.split('='))  )  const age = Date.now() / 1000 - Number(parts.t)  if (age > 300) return false   const expected = createHmac('sha256', secret)    .update(`${parts.t}.${rawBody}`)    .digest('hex')  const given = Buffer.from(parts.v1 ?? '')  return given.length === expected.length &&    timingSafeEqual(given, Buffer.from(expected))}

Pending engineering: confirm the signature encoding (hex) and timestamp unit (seconds) against the implementation.

Retries

Retries and replay

If your endpoint does not return a 2xx response, Eza retries after:

  1. About 10 seconds
  2. 1 minute
  3. 5 minutes
  4. 30 minutes
  5. 2 hours
  6. 6 hours
  7. 12 hours

Retries stop after 24 hours.

Failed events remain available for replay in the dashboard for 30 days.