Skip to main content
Webhooks push email events to your server as they happen, so you don’t have to poll GET /v1/emails/{id}.

Create an endpoint

Add an endpoint in the dashboard. Choose the events it receives and the payload format:
  • SendFlit format (default): the body is described below and is signed with X-Sendflit-Signature.
  • Resend format: the payload and Svix-style signature headers match Resend’s, so existing Resend webhook code keeps working. See Switching from Resend.
Each endpoint has its own signing secret, shown once when you create it.

Events

Transient bounces, such as a full mailbox, don’t suppress the address and don’t produce email.bounced.

Payload

Requests are POST with a JSON body:
data contains the email’s id, from, to, subject, and status, plus event-specific fields such as the clicked URL for email.clicked. Read unknown fields without failing, because new fields can be added.

Verify the signature

Every SendFlit-format request includes:
The value is an HMAC-SHA256 of the raw request body, keyed with the endpoint’s secret.
1

Read the raw body

Read the body as bytes before any JSON parsing. Parsing and re-serializing changes the bytes, and the signature no longer matches.
2

Compute the expected signature

Compute "sha256=" + hex(HMAC_SHA256(secret, raw_body)).
3

Compare in constant time

Use a constant-time comparison. Reject the request with 401 if they differ.
Each SDK has a helper. See the SDK pages.

Respond and process

  • Return a 2xx status once you’ve verified and stored the event. Return 401 for a bad signature.
  • Do slow work, such as updating a CRM or sending an alert, after you respond, or from a queue.
  • Deliveries can repeat and can arrive out of order. Make processing idempotent by keying on the email id and the event type.
  • A tutorial shows a complete handler: Handle bounces with webhooks.