Email API
Send from your code, exactly once.
One call sends a message or a batch of a hundred. Every send has an id before it leaves, and a retry replays instead of sending again.
In short
What is a transactional email API?
It is how an app sends its own mail, like receipts, sign-in links and alerts, with an HTTP request instead of a person pressing Send.
100
messages in one batch call
365
days a send can be scheduled ahead
900
seconds of undo on an immediate send
How it works
A batch that is never all or nothing
Up to 100 messages per call, each checked on its own. A bad address fails that item and the rest still go.
Now, later, or with an undo window
Schedule up to a year ahead, or hold an immediate send for up to 15 minutes. Cancel or reschedule until it goes.
A trail for every message
Each send gets a msg_ id at once. Read its status, the events for each recipient, and its opens and clicks.
Send a batch
The TypeScript SDK, or the same JSON over plain HTTP.
import { init, openemail } from '@openemail/sdk' init({ apiKey: process.env.OPENEMAIL_API_KEY }) const result = await openemail.emails.sendBatch( [ { from: '[email protected]', to: '[email protected]', subject: 'Order AC-4192 has shipped', text: 'It is on its way.' }, { from: '[email protected]', to: '[email protected]', subject: 'Order AC-4193 has shipped', text: 'It is on its way.' }, ], { idempotencyKey: 'shipments:2026-09-23' },) console.log(result.sent, result.failed)What you get
In the product today
Templates by id
Send a stored template and pin the version you tested.
In their language
Add translate and each recipient reads it in theirs, or it is not sent at all.
Resend-shaped too
Point the Resend SDK at /compat/resend and keep your code.
Good practice
Getting the most out of it
- 01
Derive the idempotency key
Use what caused the send, like an order number, never a timestamp.
- 02
Read the status
202 means queued or scheduled. Check status before you call it delivered.
- 03
Tag what you send
Up to 10 tags per message, echoed back on every read.
Where it stands
Good to know
- No test mode
- Every key is live, so every send delivers for real.
- No bounced status on a send
- A bounce reaches the thread and the email.bounced webhook, not GET /emails.
- Composer sends are not listed
- Mail sent from the app does not appear in GET /emails.
Questions
Asked often
Keep going
Works well with
Start
Your domain,
your mail.
Point a domain at OpenEmail and read it in a mailbox built around it. The free plan covers one domain.