Home/Email API/Multiple recipients

Send email to multiple recipients in Python

Loop one REST call per recipient for small personalised sends. For a real list, don't: bulk on the transactional path is a deliverability trap. Use a campaign.

Verified By George Hartley, Co-founder · Updated July 20, 2026

The loop, and where it stops being fine

For a handful of personalised messages, the honest answer is a loop: one POST per recipient, each with its own message ID and its own delivery events. Clean, trackable, done.

Pythonone send per recipient
for user in users:
    requests.post(
      "https://api.nitrosend.com/v1/my/messages",
      headers={"Authorization": "Bearer $NITROSEND_API_KEY"},
      json={"from": "[email protected]", "to": user["email"],
            "subject": f"Welcome, {user['name']}", "html": user["body"]},
    )

Bulk on the transactional path is a trap

Here is the line I hold: a bulk send should not be built on the transactional messages path. That is a deliverability and compliance trap. Transactional infrastructure is tuned and trusted for one-to-one, event-triggered mail; push a thousand marketing messages through it and you burn the reputation your receipts depend on, with no unsubscribe handling to keep you legal.

Real lists go through campaigns: import the contacts, define the segment, send once, and let the platform handle suppression, unsubscribes, and per-recipient events.

Under the hood, a campaign resolves its recipients into a durable outbox in 5,000-row batches before anything fires, so the send phase reads from a prepared queue instead of segmenting mid-flight. Rate limits bracket the same design: the free plan caps at 200 emails an hour, while a warmed, trusted domain at the other end clears 500,000 messages in about an hour and a half. The platform is built so the wire is the bottleneck, never the queue.

I hold this line because I've watched it get tested. A spammer once bought a paid plan specifically to shove bulk mail through our transactional path, because that path is documented to skip warmup, CAN-SPAM footers, and List-Unsubscribe. That is exactly the loophole your own bulk loop exploits, against your own domain.

Full parameters and responses live in the REST API docs and the API reference.

The trap
Gmail app password
abcd efgh ijkl mnop
✕ 500 emails/day cap
✕ breaks when 2FA settings change
✕ a full-inbox credential in your code
The fix
POST /v1/messages
Authorization: Bearer ns_live_…
✓ scoped API key, revoke anytime
✓ 8,000 free sends, no daily cliff
✓ delivery events you can act on

Go deeper

Cleaning the list first matters more than the loop: read the email validation API guide, because every bad address in that loop is a bounce against your domain.

First send in thirty seconds.

Simple pricing. Unlimited contacts.

Every plan includes full stack emailing: Flows, Newsletter Campaigns and Transactional Email, plus our NitroWheel LLM and all agent integrations (Claude, ChatGPT, Codex, Cursor and others). Pay for what you send, not who you store.

Free
$0
forever
  • Emails 8,000then 500/mo
  • Email types Transactional & Marketing
  • AI actions 20/mo
  • Contacts Free & Unlimited
  • Brands 1
  • Seats 1
Start free
Ultra
$100
per month
  • Emails 125,000/month
  • AI actions 5,000/mo
  • Brands 5
  • Seats 10 · Domains 3
  • Frontier AI Included
  • Dedicated IP Available
Get started
Enterprise
$300
per month
  • AI actions Unlimited
  • Unlimited brands & domains Included
  • SSO / SAML Included
  • 99.9% SLA Included
Get started

Free forever. No credit card required. See full comparison →