Email Notification API (2026): Alerts and System Notices via Rovela HTTP
Send system and product notifications with Rovela’s email API: incident-scoped Idempotency-Key, server-only sending_access, digests, and bounce webhooks — not newsletters.
An email notification API for alerts your systems already know about
An email notification API is how an application turns an internal event — a threshold crossed, a job failed, an incident opened, a nightly digest ready — into a short, trustworthy message to a person who should act. It is still transactional mail: one (or a few) recipients, content they caused or are responsible for, sent over HTTP. It is not a promotional newsletter.
This post focuses on system and product notifications. The general transactional pillar is Transactional Email API; SaaS lifecycle mail (OTP, invites, receipts) is Email API for SaaS Apps. Scheduler wiring for a particular cron library belongs in those integration posts, not here. Start from the Email API product page, the Quick Start, the Send Email API, and Authentication.
Related product guides in this series:
- Transactional Email API
- HTTP Email API
- Migrate SMTP to an Email API
- Email API for SaaS Apps
- Send Email with curl
- Transactional Email API + Hosted Mailboxes
- Inbound and Outbound Email API
- Email Sending API
- Email API Integration
- Batch Transactional Email API
- Transactional Email Webhooks
- A Simple Transactional Email API
- Send Transactional Email from Your App
- Verified Domain Email API
When a notification should be email
Email fits notifications that must reach someone who is not staring at your dashboard: on-call backups, founders, a customer’s billing contact, a weekly ops digest. In-app bells and Slack are faster for people already online; email is the durable copy.
Good candidates:
- Threshold and anomaly alerts from your monitoring pipeline (the transactional product page lists system alerts as a first-class use).
- “A background job failed N times” to the owning team.
- Daily or weekly digests whose HTML is built at send time.
- Customer-facing notices that are not marketing: “your export is ready,” “a new device signed in.”
Leave list-style announcements to broadcasts. If the body is already finished and you only need “deliver at 09:00,” use scheduled_at (Scheduled Email Sending). If you must query fresh metrics at 09:00, run your own scheduler and POST /emails at fire time — Rovela does not host your cron.
A notification send
Keep ROVELA_API_KEY (sending_access) and MAIL_FROM on the worker. Use a window- or incident-scoped idempotency key so retries and overlapping alerts do not multiply messages:
import json, os, urllib.request
def send_transactional(*, to, subject, html, text, idempotency_key, tags=None):
body = {
"from": os.environ["MAIL_FROM"],
"to": to,
"subject": subject,
"html": html,
"text": text,
}
if tags:
body["tags"] = tags
req = urllib.request.Request(
"https://api.rovela.dev/emails",
data=json.dumps(body).encode(),
headers={
"Authorization": "Bearer " + os.environ["ROVELA_API_KEY"],
"Content-Type": "application/json",
"Idempotency-Key": idempotency_key,
},
method="POST",
)
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read().decode())
# example: one mail per incident, not per retry of the monitor
send_transactional(
to=os.environ["ONCALL_EMAIL"],
subject=f"[Acme] incident {incident_id} is open",
html=f"<p>Incident <b>{incident_id}</b> is open. {summary}</p>",
text=f"Incident {incident_id} is open. {summary}",
idempotency_key=f"incident-open:{incident_id}",
tags={"kind": "incident-open", "incident": incident_id},
)
For a digest that must not send twice on a worker restart, key off the business window (ops-digest:{yyyy-mm-dd}) as in Idempotency Keys for Email APIs. Several personalized digests in one job belong on Batch Transactional Email API (up to 100, no templates on the batch endpoint).
Set reply_to to a mailbox a human reads if the on-call might reply (Transactional Email API + Hosted Mailboxes). Send both HTML and text: the text part is what many phones show on the lock screen.
Operability
- A
200means queued, not “the on-call has read it.” For critical alerts, also page them; use webhooks (email.bounced,email.failed) so a bouncing on-call address is not silently dropped (Transactional Email Webhooks, Handling bounces). - Honour the 50-recipient cap. An “email the whole company” incident blast is usually the wrong shape; fan out with batch in chunks of 100, or use a broadcast only if the content is truly the same list mail.
- Do not put
full_accesson the monitor process. Sending is enough. Read status from a separate tool or from webhooks. - Tags (
kind,incident,env) make the message log usable when you are reconstructing a bad night.
Automation that starts from incoming Rovela events (bounce → ticket) is Webhook-Driven Email Automation; this post is the other direction: your system event → email.
FAQ
Can the notification process use mailbox SMTP? Only if you accept mailbox limits (send-as-self, 30 messages/minute per client address) and weaker programmatic tooling. The SMTP page tells you to use the HTTP API for programmatic volume (SMTP, HTTP Email API).
How is this different from webhook-driven email? Webhook-driven posts start from a vendor event (Stripe, Shopify, or Rovela itself). A notification API call starts from your metric, job, or incident.
Should I include PII or secrets in the alert body? Prefer a short summary and a link into an authenticated admin view. Email is stored in more places than your database.
What about open tracking on alerts? email.opened / email.clicked only fire when tracking is enabled on the sending domain. Many teams leave tracking off for security and ops mail; do not treat missing opens as “nobody saw the alert.”
Page the human, queue the mail
When your system already knows something went wrong (or something finished), call POST /emails with a window- or incident-scoped idempotency key and a server-only sending key. That is the email notification API: boring, reliable, and easy to audit.