Integration guide
Send email with Node.js
Rovela's email API is a plain HTTPS endpoint that accepts JSON. Any Node.js HTTP client works: the native fetch in Node 18+, Axios, or got. This guide covers a minimal send, retries with idempotency keys, and a few patterns that make transactional email more reliable in production.
No SDK is required. Rovela's API is one POST endpoint, and the full integration is under 20 lines of JavaScript. The guide below covers the minimal case first, then adds retries and idempotency — the two things most teams add after their first production incident.
Prerequisites
You need a Rovela account (free, no card), an API key from the dashboard, and a verified sending domain. Node.js 18 or later is assumed throughout because it ships fetch globally. The same code works in Node 16 with node-fetch installed, and in Deno or Bun without changes.
A minimal send
A single POST to /emails with your API key in the Authorization header and a JSON body. The response includes the message ID you can store for later lookup.
const res = await fetch('https://api.rovela.dev/emails', {
method: 'POST',
headers: {
'Authorization': 'Bearer re_your_api_key',
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Welcome aboard',
html: '<p>Thanks for signing up. Your account is ready.</p>',
}),
})
const { id } = await res.json()
console.log('Sent:', id)Adding retries and idempotency
Generate the idempotency key once, before the loop, and reuse it on every attempt. This way a network error or a 5xx response triggers a retry, but the same message is never sent twice regardless of how many attempts succeed at the server.
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
async function sendWithRetry(payload, retries = 3) {
const key = crypto.randomUUID()
for (let i = 0; i <= retries; i++) {
const res = await fetch('https://api.rovela.dev/emails', {
method: 'POST',
headers: {
'Authorization': 'Bearer re_your_api_key',
'Content-Type': 'application/json',
'Idempotency-Key': key, // same key on every attempt
},
body: JSON.stringify(payload),
})
if (res.status < 500) return res // 2xx or 4xx — stop
await sleep(Math.min(1000 * 2 ** i, 8000)) // backoff, capped
}
throw new Error('send failed after ' + retries + ' retries')
}Storing the message ID
The ID Rovela returns links the send to delivery events in webhooks and logs. Store it against the transaction in your own database. When a webhook arrives for email.bounced or email.complained, the message ID in the payload tells you exactly which send it relates to and which customer to update.
Environment variables
Never put an API key in source code. Use process.env.ROVELA_API_KEY and load it from a .env file with dotenv in development, or from your deployment platform's secret store in production. Rotate the key from the Rovela dashboard if it is ever exposed; the new key takes effect immediately and the old one stops working.
Common questions
- Do I need the Rovela SDK, or can I use plain fetch?
- Plain fetch works fine. Rovela's API is a single JSON endpoint; there is no SDK required. An SDK can reduce boilerplate if you are integrating from TypeScript, but it is optional.
- What Node.js version do I need?
- Node 18 or later for the native global fetch. In Node 16, install node-fetch and import it. The API itself has no version requirements beyond HTTPS support.
- How do I send to multiple recipients?
- Pass an array to the 'to' field: ["alice@example.com", "bob@example.com"]. Each address receives an individual copy of the message; recipients do not see each other's addresses. The to, cc, and bcc fields all accept strings or arrays.
- How do I send HTML and a plain-text fallback?
- Include both the 'html' and 'text' fields in the request body. Mail clients that cannot render HTML display the text version. Rovela sends both parts in a multipart/alternative message automatically.