Send the same email template to multiple recipients with personalization.
Mail merge functionality for:
- Newsletters with personalized greetings
- Marketing campaigns with custom variables
- Bulk transactional emails with recipient-specific data
Features:
- Template variables: Use
{{variable}}syntax in subject, HTML, and text - Built-in placeholders:
{{unsubscribe}}for unsubscribe links - Per-recipient personalization via
varsobject - Automatic variable substitution for each recipient
- Single template, many recipients
- File attachments (same for all recipients)
- Calendar invites (same for all recipients)
Limits:
- Recommended: Up to 10,000 recipients per call
- Each recipient gets their own personalized copy
Use cases:
- Newsletter campaigns: "Hi {{name}}, check out our new {{product}}..."
- Promotional emails with unique discount codes
- Event invitations with personalized details
Built-in Placeholders:
{{unsubscribe}}- Secure unsubscribe link (unique per recipient)
Not for: Different emails to each recipient → Use /api/batch instead
Constraints: 1-255 characters; must not contain / (the id becomes a path segment of the report URL) or control characters. Other characters are allowed but must be percent-encoded when building report URLs.
Optional campaign identifier for this send. Supply your own id (for example your application-side campaign id) to correlate reports with your system; if you omit it, a UUID is minted for this send and returned as campaign_id.
Whatever value is used is stamped on every recipient of this send, and is the key the /api/v1/campaigns/{campaignId}/... report endpoints scope on.
Maximum 255 characters.
Auto-pause protection: If bounce rate exceeds thresholds, the campaign will be automatically paused to protect IP reputation.
How Campaign Grouping Works:
- Every recipient of this call carries this
campaign_id - Campaign reports return exactly the recipients of the sends carrying this id
- Reusing an id across calls deliberately merges those calls into one report
- Auto-pause is applied per reputation session (
bulk_session_idin the response), which groups sends by subject over 24 hours and is NOT the campaign id
⚠️ Splitting one campaign across several calls: if you chunk a large recipient list into multiple /bulk-send calls, you MUST pass the SAME campaign_id on every chunk. Omitting it mints a fresh id per call, so each chunk becomes its own campaign and a report covers only the chunk whose id you kept.
⚠️ CRITICAL: Each campaign MUST use a UNIQUE campaign_id
Best Practices:
- ✅ DO: Use unique IDs per campaign send
- Good:
"monthly-newsletter-2026-03-05" - Good:
"spring-sale-2026-week1" - Good:
"product-launch-v2-2026-03"
- Good:
- ❌ DON'T: Reuse campaign_id across different campaigns
- Bad:
"newsletter"(reused every month) - Bad:
"promo"(reused for all promos) - Bad:
"bulk-send"(too generic)
- Bad:
Why This Matters: If you reuse a campaign_id:
- Bounce rates from OLD campaigns affect NEW campaigns
- New campaign might be immediately paused due to old bounces
- Campaign reports mix data from different time periods
- Cannot track individual campaign performance
Recommended Format: {campaign-name}-{date} or {campaign-name}-{version}-{date}
Examples:
- Monthly newsletters:
"newsletter-2026-03","newsletter-2026-04" - Sales campaigns:
"spring-sale-2026-w1","spring-sale-2026-w2" - Product launches:
"product-x-launch-2026-03-05"
If not provided, system auto-generates: bulk-{timestamp}-{customer_id}
Email subject with optional variables like {{name}} or {{code}}.
Important: If using personalization, also provide subject_template for proper campaign tracking.
Recommended when using personalized subjects. The template before variable substitution.
Why needed: Helps system track campaigns correctly when subjects are personalized.
Example:
subject_template: "Hello {{name}}! Your code is {{code}}"- Actual
subjectfor each recipient: "Hello John! Your code is SAVE20"
If not provided, system normalizes the subject automatically (less accurate).
Preview/preheader text shown in email clients next to subject (40-130 characters recommended). Appears in inbox list view before opening the email.
HTML email body with variables
Plain text email body with variables. Supports the same {{variable}} merge fields as html.
Auto-generation: If omitted, a plain-text version is automatically generated from html before sending. Supplying your own text is recommended for best plain-text client rendering.
From email (must use verified domain, optional)
Sending domain (optional - auto-extracted from from email if not provided). If provided, must match the domain in from email address.
Stream type is locked to broadcast for bulk sending. Bulk/mail merge emails are marketing/newsletter content and must use the broadcast stream to protect transactional IP reputation.
File attachments sent with every email (sent directly, not stored). Same attachments sent to all recipients.
iCal calendar event in RFC 5545 format (sent directly, not stored). Same calendar invite sent to all recipients.
- US Data Centerhttps://api.mailerlogic.net/api/v1/bulk-send
- EU Data Center (coming soon)https://eu-api.mailerlogic.net/api/v1/bulk-send
curl -i -X POST \
https://api.mailerlogic.net/api/v1/bulk-send \
-H 'Content-Type: application/json' \
-H 'X-API-Key: YOUR_API_KEY_HERE' \
-d '{
"campaign_id": "spring-sale-2026-discount-20",
"subject": "Hello {{name}}! Special offer inside",
"subject_template": "Hello {{name}}! Special offer inside",
"preview_text": "Exclusive discount code just for you - save 20% today!",
"html": "<h1>Hi {{name}}</h1><p>Use code <strong>{{code}}</strong> for 20% off!</p><p><a href=\"{{unsubscribe}}\">Unsubscribe</a></p>",
"text": "Hi {{name}}, Use code {{code}} for 20% off!\n\nUnsubscribe: {{unsubscribe}}",
"from": "hello@mail.yourdomain.com",
"from_name": "Your Company",
"track_opens": true,
"track_clicks": true,
"tag": "holiday-sale-2025",
"stream_type": "broadcast",
"recipients": [
{
"email": "john@example.com",
"vars": {
"name": "John",
"code": "JOHN20"
}
},
{
"email": "jane@example.com",
"vars": {
"name": "Jane",
"code": "JANE20"
}
}
]
}'Bulk send request accepted and queued for delivery
Campaign identifier for this send. Pass this to the /api/v1/campaigns/{campaignId}/... report endpoints.
Echoes the campaign_id you supplied, or a UUID minted for this call if you did not supply one. Reports cover exactly the recipients of the calls carrying this id — so when you chunk one campaign across several calls, supply the SAME campaign_id on every chunk; only an omitted id is minted fresh per call.
IMPORTANT: Save this ID to track campaign performance, bounce rates, opens, and clicks.
Not a campaign id — do not pass it to the report endpoints.
The reputation/auto-pause session this send joined. Sessions group every send that shares a subject within a 24-hour window, so one session can span several distinct campaigns. It is exposed only to correlate auto-pause events.
Previously this field was an alias of campaign_id. It is now a separate value, and reports keyed on it return only sends made before per-send campaign ids existed.
{ "message": "Emails queued for delivery", "queued": 2, "errors": 0, "campaign_id": "spring-sale-2026-week1", "bulk_session_id": "a7b8c9d0-1234-5678-9abc-def012345678", "jobs": [ { … }, { … } ] }