One event per state change
From the moment a message is sent to the moment a reader clicks a link, each state change fires its own event. Contact and domain events are available too; the docs list them all.
email.deliveredemail.bouncedemail.complainedemail.openedemail.clickedcontact.unsubscribed
{
"id": "evt_2f9c1a...",
"type": "email.delivered",
"created_at": "2026-10-15T12:00:00.000+00:00",
"data": {
"email_id": "3f6a1b2c-...",
"from": "billing@yourdomain.com",
"to": ["user@example.com"]
}
}Built for production
Full event coverage
Sent, delivered, delayed, bounced, complained, opened, clicked and received, plus contact and domain events, each as its own type so your app can react precisely.
No polling
A delivery is queued the moment the event happens and sent on the next worker pass, normally within a minute.
HMAC-signed payloads
Every request carries an HMAC-SHA256 signature and a timestamp computed with your endpoint’s secret, so you can verify it came from Rovela and reject replays.
Automatic retries
If your endpoint times out or answers 5xx, 408 or 429, the delivery is retried with exponential back-off, up to five attempts. Every attempt is visible in the dashboard.
Consistent payload shape
Every event shares one envelope: id, type, created_at and a data object with the event’s fields. Deduplicate on id; a retry carries the same one.
Per-endpoint filtering
Subscribe each endpoint to only the events it needs. Send delivery events to your CRM and complaint events to your suppression service without extra routing logic.