Appearance
Batch sending
A batch sends the same message to many people, each getting their own email. You make one request; MarleyFetch works through the list in the background, pacing itself to your connection's quota.
Batch sending is a Pro feature.
Create a batch
POST /v1/send/batch needs content and recipients:
| Content — pick one | |
|---|---|
template | Inline { subject, text_body?, html_body? }. |
template_id | ID of a saved template. |
| Recipients — pick one | |
|---|---|
recipients | Array of up to 1,000 addresses. |
audience_id | ID of a saved audience. Enables personalisation. |
Optional: name (shown in the dashboard) and from (which connection sends).
When each recipient needs different content, send an emails array instead.
To a list of addresses
bash
curl https://api.marleyfetch.com/v1/send/batch \
-H "Authorization: Bearer $MARLEYFETCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "September newsletter",
"from": "news@yourcompany.com",
"template": {
"subject": "What is new in September",
"html_body": "<p>Here is what we shipped this month.</p>"
},
"recipients": ["alice@example.com", "bob@example.com"]
}'ts
const { batch_id } = await mf.batch()
.name('September newsletter')
.from('news@yourcompany.com')
.subject('What is new in September')
.html_body('<p>Here is what we shipped this month.</p>')
.recipients(['alice@example.com', 'bob@example.com'])
.send()To an audience, personalised
When you send to an audience, {{placeholders}} in the subject and bodies are replaced with each member's payload:
json
{
"name": "Renewal reminder",
"template": {
"subject": "{{first_name}}, your {{plan}} plan renews soon",
"html_body": "<p>Hi {{first_name}}, your {{plan}} plan renews next week.</p>"
},
"audience_id": 12
}A member added with "payload": {"first_name": "Alice", "plan": "Pro"} receives "Alice, your Pro plan renews soon". Placeholders are case-sensitive, and a variable the member does not have renders as an empty string — so a sentence like Hi {{first_name}}, degrades to Hi ,. Keep payloads complete for every variable you use.
Recipients passed as a plain recipients array have no payload, so leave placeholders out of those batches.
Different content per recipient
emails takes up to 1,000 fully formed emails — one recipient, subject and body each — and replaces both the content and the recipients:
json
{
"name": "Order updates",
"emails": [
{ "to": "alice@example.com", "subject": "Order 1042 has shipped", "text_body": "Your order is on its way." },
{ "to": "bob@example.com", "subject": "Order 1043 is delayed", "html_body": "<p>Sorry, your order is a day late.</p>" }
]
}Each item goes to exactly one address; cc and bcc are rejected. For a handful of emails, calling /send for each works just as well.
The response
The request returns as soon as the batch is created:
json
{
"success": true,
"batch_id": 77,
"total_count": 2,
"message": "2 emails queued for batch delivery.",
"status_url": "/v1/batches/77"
}Track progress
Poll GET /v1/batches/{id}:
bash
curl https://api.marleyfetch.com/v1/batches/77 \
-H "Authorization: Bearer $MARLEYFETCH_API_KEY"json
{
"success": true,
"batch": {
"id": 77,
"name": "September newsletter",
"status": "running",
"total_count": 500,
"sent_count": 320,
"failed_count": 2,
"progress": 64,
"created_at": "2026-09-28 10:15:00",
"updated_at": "2026-09-28 10:21:40"
}
}status moves from pending to running to completed (or failed). progress is the percentage of recipients handled, sent or failed. Once a minute is plenty for polling; the Batches page shows the same numbers, plus each failed recipient with its error and a retry button.
How pacing works
A batch never breaks your connection's limits:
- It sends only as fast as the connection allows.
- When the connection's quota is used up, the remaining emails wait for the next window and continue — a 5,000-recipient batch on a 2,000/day connection takes three days, and nothing fails.
- If your provider starts rate-limiting, the batch backs off and resumes.
Only permanent problems, such as a deleted connection or an address your server refuses, count as failures.
Delete a finished batch
bash
curl -X DELETE https://api.marleyfetch.com/v1/batches/77 \
-H "Authorization: Bearer $MARLEYFETCH_API_KEY"Only completed or failed batches can be deleted; others return 400 INVALID_STATUS.
Errors specific to batches
| Status | Body | Cause |
|---|---|---|
| 400 | BATCH_TOO_LARGE | More than 1,000 recipients or emails. Use an audience instead. |
| 400 | {"error": "Invalid audience"} | audience_id does not exist or is not yours. |
| 400 | {"error": "Audience has no members"} | The audience is empty. |
| 404 | RESOURCE_NOT_FOUND | template_id does not exist or is not yours. |
| 403 | FEATURE_NOT_AVAILABLE | Batches need the Pro plan. |