Events

The complete catalog, and the payload each event carries.

This is every event type Rovela fires. Registering an endpoint with a name that is not on this list is rejected rather than accepted and quietly never fired, so a typo surfaces at registration instead of at three in the morning.

Envelope

Every event, whatever its type, is delivered in the same envelope:

{
  "id": "evt_<uuid>",
  "type": "email.delivered",
  "created_at": "2026-09-25T09:14:02.481+00:00",
  "data": { ... }
}

Only data varies by event type. Deduplicate on id: a retry carries the same event id and the same created_at.

The catalog

Email delivery

What happened to a message after it was accepted.

  • email.sent — Accepted by the SMTP relay. Not yet delivered.
  • email.delivered — The receiving server accepted it for the recipient.
  • email.delivery_delayed — Still being retried. Not an outcome — it may yet deliver or bounce.
  • email.bounced — Permanent failure. The address does not exist or refuses mail.
  • email.failed — Delivery failed for a reason that is not a recipient bounce.
  • email.suppressed — Blocked before sending by the suppression list.
  • email.scheduled — Queued for a future `scheduled_at`.
  • email.received — An inbound message was accepted for a hosted mailbox.

Engagement

What the recipient did. Only fires when tracking is enabled for the sending domain.

  • email.opened — The tracking pixel was fetched.
  • email.clicked — A rewritten link was followed.
  • email.complained — The recipient marked the message as spam.

Broadcasts

Campaign fan-out.

  • broadcast.sent — The fan-out finished and every recipient was queued.

Contacts

Changes to your audience.

  • contact.created — A contact was added.
  • contact.updated — A contact's details changed.
  • contact.deleted — A contact was removed.
  • contact.unsubscribed — A contact opted out. Worth acting on — see the note below.

Suppressions

The list of addresses mail is withheld from.

  • suppression.added — An address was suppressed, by a bounce or by hand.
  • suppression.removed — An address was un-suppressed.

Domains

Sending-domain lifecycle.

  • domain.created — A domain was added.
  • domain.updated — Its settings changed.
  • domain.deleted — It was removed. Sending from it is refused afterwards.

Automations

Multi-step flows.

  • automation.started — A run began for a contact.
  • automation.completed — The run reached the end.
  • automation.failed — The run stopped on an error.

Mailboxes

Hosted mailboxes filling up.

  • mailbox.quota_alert — Nearly full, full, or cleared again. The distinction is in `severity` (warning|critical) and `status` (opened|escalated|resolved) rather than in separate event names.

Example payloads

Delivery events identify the message and its participants:

{
  "id": "evt_2f9c1a...",
  "type": "email.delivered",
  "created_at": "2026-09-25T09:14:02.481+00:00",
  "data": {
    "email_id": "9f1c2e40-...",
    "from": "hello@mail.example.com",
    "to": ["user@example.com"]
  }
}

Contact events carry the contact rather than a message:

{
  "id": "evt_7b3d84...",
  "type": "contact.unsubscribed",
  "created_at": "2026-09-25T09:20:11.004+00:00",
  "data": {
    "contact_id": "<uuid>",
    "email": "user@example.com"
  }
}
Treat the exact field set of data as additive. New fields can appear as the product grows, and a handler that rejects an event because it contained something unexpected will lose that event permanently — see the retry rules in Overview. Parse the fields you need and ignore the rest.

Which events you actually want

  • email.bounced, email.complained and contact.unsubscribed are the three that should change something on your side. A bounce means stop mailing that address; a complaint means the same, more urgently. Ignoring them is how a domain loses its sending reputation.
  • email.delivered is the one people subscribe to first, and it is the least actionable — it confirms what usually happens anyway.
  • email.opened and email.clicked only fire where tracking is enabled for the sending domain. A domain with tracking switched off produces no engagement events at all, which looks identical to a domain nobody engages with.