Faivelo
Dashboard
AI & Developers

Webhooks

Get a signed POST the moment mail arrives, a send bounces or a domain needs attention. No polling.

A webhook is a URL on your server that Faivelo calls when something happens in your account. Instead of asking the API "anything new?" every few seconds, you hear about it the moment it happens.

Webhooks are included on the Growth, Pro and Business plans (not on free trials). Every plan can have up to 10 endpoints. The delivery log and Events list keep 3 days on Growth, 7 on Pro and 30 on Business. Manage them in Settings → Developers → Webhooks.

Add an endpoint

  1. Open Settings → Developers → Webhooks and choose Add endpoint.
  2. Enter an https URL, pick the events you want, and choose whether to listen to the whole account or only some domains or mailboxes.
  3. Copy the signing secret. It is shown once.
  4. Press Send test event. You see what your server answered straight away.

Events

EventFires when
message.receivedA new message landed in a mailbox, spam folder included. Pro and Business.
message.sentA message left a mailbox for the outside world, from webmail, a mail app or the API. Pro and Business.
email.deliveredThe recipient's server accepted an email sent through the API.
email.bouncedAn email could not be delivered.
email.complainedThe recipient marked an email as spam.
mailbox.createdA mailbox was created.
mailbox.deletedA mailbox was deleted.
account.sending_pausedWe paused sending for the whole account, usually for bounces or spam reports.
account.sending_resumedSending was restored after a pause.
account.storage_warningStorage passed 80% or 95% of the plan. Repeats daily while it stays there.
domain.verifiedA domain passed verification.
domain.dns_brokenA required DNS record on a verified domain went missing or changed.
domain.expiringA domain registered with us expires in 30 days, and again at 7 days.

The payload

Every event has the same envelope. data depends on the event type.

{
  "id": "evt_01J8ZK3V5QXR7",
  "type": "email.bounced",
  "created_at": "2026-09-20T14:02:11Z",
  "data": {
    "email_id": "em_01J8ZJW2HN",
    "from": "billing@testcompany.com",
    "to": ["dana@northwind.io"],
    "subject": "Your receipt from Test Company",
    "bounce": { "type": "permanent", "reason": "Mailbox does not exist" }
  }
}

Message events

message.received and message.sent carry a summary of the message, not the whole thing:

{
  "id": "evt_01J8ZK3V5QXR7",
  "type": "message.received",
  "created_at": "2026-09-20T14:02:11Z",
  "data": {
    "mailbox": "support@testcompany.com",
    "message_id": "eaaaaab",
    "thread_id": "b",
    "folder": "INBOX",
    "from": { "name": "Dana Whitfield", "address": "dana@northwind.io" },
    "to": [{ "name": "Test Company Support", "address": "support@testcompany.com" }],
    "subject": "Question about our invoice",
    "snippet": "Hi team, I noticed the March invoice lists two seats we removed in February...",
    "received_at": "2026-09-20T14:02:11Z",
    "attachments": [{ "name": "invoice-march.pdf", "content_type": "application/pdf", "size": 48213 }]
  }
}

message_id is the message's permanent id. Pass it to the API wherever a message UID goes, for example GET /api/v1/mailboxes/support@testcompany.com/messages/eaaaaab, to read the full body, download attachments, flag, move or delete it. Unlike a UID it stays the same when the message moves to another folder.

Two things to know about message.sent. It arrives about 20 seconds after the send, because mail apps save the Sent copy after sending. And an app that keeps no Sent copy (plain SMTP senders) still fires the event, with message_id, thread_id, subject and snippet set to null.

An endpoint narrowed to certain domains or mailboxes only hears about those. One account can cause at most 2,000 message events an hour; past that they are dropped, not delayed.

Partner endpoints

Partners add endpoints in the partner console under Developers. One endpoint receives events for every customer you created, and every payload carries a customer_id. Partner endpoints also get customer.created, customer.plan_changed, customer.paused and customer.resumed (the last two are your own pauses; a pause by Faivelo arrives as account.sending_paused). Customers created with a sandbox key fire events too, marked "sandbox": true.

message.received and message.sent reach a partner endpoint only for customers where you hold a mailbox key with the mail:read scope, and they carry a pointer rather than the mail itself: mailbox, message_id, thread_id, folder and received_at. No sender, subject or snippet. Fetch the message with that customer's key, GET /api/v1/mailboxes/{address}/messages/{message_id}, which is also what puts the read on the customer's audit trail.

Verify the signature

Each request has an X-Faivelo-Signature header: t=<unix timestamp>,v1=<signature>. The signature is HMAC-SHA256 of <timestamp>.<raw body> with your signing secret. The SDK (0.6.0 and later) checks it, and rejects timestamps older than 5 minutes, in one call. It throws FaiveloWebhookError when a request cannot be trusted; answer those with a 400.

import { Faivelo } from 'faivelo'

const event = await Faivelo.webhooks.verify(
  rawBody, // the raw request body, not parsed JSON
  request.headers['x-faivelo-signature'],
  process.env.FAIVELO_WEBHOOK_SECRET
)

Limits

To keep webhooks from being pointed at other people's servers, test events and resends are limited to 20 per 10 minutes per account, and the URL must resolve to a public address. We do not follow redirects.

Delivery and retries

  • Answer with any 2xx within 10 seconds. Do slow work after you respond.
  • A failed delivery is retried with growing pauses for 24 hours.
  • An event can arrive more than once. Use its id to ignore repeats.
  • Events can arrive out of order. Use created_at if order matters.
  • An endpoint that fails every delivery for 5 days is turned off, and we email you. Turn it back on from its page once your server is fixed.

Debugging

Each endpoint has a Deliveries log: every attempt, the exact body we sent, what your server answered, and a Resend button. The Events tab lists everything that happened since you added your first endpoint, for the last 30 days, including events no endpoint was subscribed to.