← Back to blog

HTTP Email API (2026): Send Transactional Mail over HTTPS with Rovela

Send transactional email over HTTPS and JSON instead of an SMTP socket: POST /emails, Bearer API keys, Idempotency-Key, and how Rovela mailbox SMTP differs.

Updated November 10, 2026
HTTP Email API (2026): Send Transactional Mail over HTTPS with Rovela

Send email over HTTPS, not over a socket to port 25

An HTTP email API is a transactional mail service you call the same way you call the rest of your backend: HTTPS, a Bearer token, and a JSON body. You do not open an SMTP conversation, negotiate EHLO / STARTTLS / AUTH, or keep a connection pool of mail sockets in your app. Rovela’s Email API is one endpoint — POST https://api.rovela.dev/emails — that queues the message, DKIM-signs it with your domain key, and returns an id.

This is a protocol-level intro to sending mail over HTTP. It is not Send Email from an AI Coding Agent via HTTP (tooling for coding agents), not the comparison in Email API vs SMTP, and not the five-minute first send in Send Your First Email in 5 Minutes. If you are mid-migration from Nodemailer or PHPMailer SMTP, use Migrate SMTP to an Email API. For the category definition of transactional mail, see Transactional Email API.

Start from the Email API product page, the Quick Start, the Send Email API, and Authentication. Rovela also offers mailbox SMTP on mx.rovela.dev port 465 for people and mail apps; that is a different path, described below.

Related product guides in this series:

What the HTTP request looks like

Authenticate with Authorization: Bearer re_your_api_key (Authentication). The body is a flat JSON object: from, to, subject, and at least one of html, text, or template.

curl -X POST https://api.rovela.dev/emails \
  -H "Authorization: Bearer re_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <hello@yourdomain.com>",
    "to": "you@example.com",
    "subject": "Hello from Rovela",
    "html": "<p>It worked.</p>",
    "text": "It worked."
  }'

A successful response looks like {"object": "email", "id": "9f1c2e40-..."}. That 200 means accepted for delivery, not “already in the inbox.” Delivery runs in the background so your request never waits on the receiving mail server (Email API, Quick Start).

The same call from Node or Python is an ordinary HTTP client:

const res = await fetch("https://api.rovela.dev/emails", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.ROVELA_API_KEY,
    "Content-Type": "application/json",
    "Idempotency-Key": `signup-verify:${userId}:${codeId}`,
  },
  body: JSON.stringify({
    from: process.env.MAIL_FROM, // e.g. "Acme <no-reply@yourdomain.com>"
    to: user.email,
    subject: `Your Acme code: ${code}`,
    html: `<p>Your verification code is <b>${code}</b>. It expires in 10 minutes.</p>`,
    text: `Your verification code is ${code}. It expires in 10 minutes.`,
    tags: { kind: "signup-otp", userId },
  }),
});
if (!res.ok) {
  const err = await res.json();
  throw new Error(`Rovela ${res.status}: ${err.message}`);
}
const { id } = await res.json(); // accepted and queued — not yet delivered

Language-specific walk-throughs already exist for How to Send Email in Node.js and How to Send Email with Python; this post stays on the HTTP contract those guides share.

HTTP vs SMTP in the application

ConcernSMTP from your appHTTP email API
TransportTCP to port 25, 465, or 587HTTPS to api.rovela.dev
AuthAUTH / mailbox passwordAuthorization: Bearer API key
PayloadMIME built in your libraryJSON fields (html, text, attachments)
Timeouts / retriesOften your problemRetry the POST; add Idempotency-Key
Delivery statusParse DSNs or poll logsGET /emails/:id, events, or webhooks
Outbound firewallsPort 25 often blocked443 is usually open

Port roles are covered in SMTP Ports 25, 465, and 587. Rovela’s SMTP product page is for business mailboxes: host mx.rovela.dev, port 465 with implicit TLS, username = the mailbox address, password = a device credential. A mailbox can send only as itself, with a documented cap of 50 recipients per message and 30 messages a minute from one client address. The same page says that for programmatic sending at volume, you should use the HTTP API (which adds tracking, logs, and webhooks). Do not treat mailbox SMTP as a hidden high-volume app relay.

Making HTTP sending safe

  • Verified from. Unverified domains are refused with 400 naming the domain. See Verified Domain Email API.
  • sending_access on the server only. Never put a key in a browser, mobile app, or public repo. A leaked sending key is someone sending as your domain (Authentication).
  • Idempotency-Key on anything retried. Queues, serverless retries, and user double-clicks all re-enter the same logical send. Keys last 24 hours and can be up to 256 characters (Idempotency Keys for Email APIs, Idempotency guide).
  • Prefer sending_access in production. full_access is for tooling that must read messages, manage domains, templates, or webhooks.
  • Watch outcomes over HTTP too. Register a webhook (Transactional Email Webhooks) or, with full_access, GET /emails/:id.

Optional fields you will actually use: reply_to, cc / bcc (they count toward the 50-recipient cap and toward quota), scheduled_at, tags, attachments, and stored template objects. Batch sending is a separate HTTP endpoint: POST /emails/batch — see Batch Transactional Email API.

When HTTP is the wrong tool

FAQ

Do I need to install a library? No. curl, fetch, httpx, net/http, or any HTTPS client is enough (Installation).

Can I call the API from the browser? You should not. sending_access in client-side code is a ready-made spam engine from your domain. Put a server in the middle (Email API Integration).

Is this the same as “send email with curl”? curl is one HTTP client. The contract is the same; the curl-specific flags, errors, and cancel examples live in Send Email with curl.

How do I know the mail was delivered? Query GET /emails/:id with a full_access key, or subscribe to email.delivered / email.bounced webhooks. The product page notes that a webhook is typically pushed within about a minute of the receiving server’s decision (Email API).

What about inbound replies? Sending is only half of some products. Inbound and Outbound Email API and Inbound Email API Webhooks cover receiving.

Use HTTPS for app mail

Point your server at POST /emails, keep sending_access in the environment, and let Rovela speak SMTP to the internet. That is the HTTP email API: one request, a message id, and webhooks for what happens after the queue.