Stop looping your send endpoint one recipient at a time. Post an array, give each recipient their own template variables, and get one response back — sent from your own server and IP, billed per send, never per contact.
The bulk endpoint takes an array of messages. Each entry carries its own recipient, subject, and merge variables — so every email is fully personalized without a request per person.
Send a batch of up to 500 individually-addressed messages in a single POST. Chunk your list, fire the calls, done — no client-side rate-limit juggling between every recipient.
Attach a data object to each entry — first name, order number, reset link, anything. Reference it in a stored template or inline HTML with {{ handlebars }} and mailstein renders it per recipient.
Get back an array of results in the same order you sent them, each with its own message ID or error. Persist the IDs, match webhook events, retry only the entries that failed.
The same emails resource you already use, with a batch method. One array in, one array out. Idempotent per entry, so a retried request never double-sends a recipient who already went through.
Transactional receipts, password resets, a 40,000-row broadcast — same endpoint, same auth, same logs on your own infrastructure.
Batch sending is only useful if it stays deliverable and debuggable at scale. mailstein handles the parts that break naive bulk loops.
Every message in the batch leaves with SPF, DKIM, and DMARC applied automatically, from a dedicated IP with managed warm-up. Suppressed addresses (hard bounces, complaints) are skipped before send, so a stale row in your array can't cost you reputation.
A batch of 500 costs 500 sends — that's it. There's no per-contact marketing tax and no separate "broadcast product" to license. The same batch endpoint powers a 12-message receipt run or a 500k-recipient announcement.
results[3] is the outcome of messages[3]. No guessing which recipient a message ID belongs to when you reconcile against your database.
A malformed address or missing variable fails only its own entry. The other 499 send normally and report success — the batch isn't rejected wholesale.
Delivered, opened, bounced, and complained events fire per message ID and land on your webhook — plus every send is queryable in your own message logs.
Batch API, per-recipient variables, your own IP and logs. Start free — 50 emails a month, one domain, no card.
Start free →