curl --request POST \
--url https://email-api.mailercloud.com/email-api \
--header 'Authorization: <api-key>' \
--header 'Content-Type: <content-type>' \
--data '
{
"email": {
"from": "from@example.com",
"fromName": "John Doe",
"replyTo": [
"from@example.com"
],
"subject": "Hi {{first_name}}, your order {{order.id}} shipped",
"text": "Hi {{first_name}}, order {{order.id}} ships to {{order.city}}.",
"html": "<html><body><p>Hi {{first_name}} from {{company}},</p><p>Order <b>{{order.id}}</b> ships to {{order.city}}.</p></body></html>",
"recipients": {
"to": [
{
"name": "Recipient One",
"email": "recipient1@example.com",
"merge_vars": {
"first_name": "Alice",
"company": "Acme",
"order": {
"id": "A-100",
"city": "Berlin"
}
}
},
{
"name": "Recipient Two",
"email": "recipient2@example.com",
"merge_vars": {
"first_name": "Bob",
"company": "Acme",
"order": {
"id": "A-101",
"city": "Paris"
}
}
}
],
"cc": [
"cc1@example.com"
],
"bcc": [
"bcc1@example.com"
]
}
},
"metadata": {
"campaignType": "TRANSACTIONAL",
"timestamp": "2026-04-15T10:00:00Z",
"custom": {
"inbox_tracking": "false",
"campaign_id": ""
}
},
"version": "1.0"
}
'{
"status": "SUCCESS",
"statusCode": 1000,
"message": "NA"
}{
"status": "ERROR",
"statusCode": 9999,
"message": "merge_vars must be an object"
}{
"status": "ERROR",
"statusCode": 9999,
"message": "merge_vars exceeds 100 KB limit"
}Send Personalized Email
Send transactional or marketing emails with per-recipient personalization (mail merge). Same request structure as POST /email, plus an optional merge_vars object on each recipients.to[] entry.
Personalization:
{{variable}}placeholders insubject,text,html,amp_htmlandfromNameare replaced with that recipient’smerge_varsvalues.- In
html,{{var}}is HTML-escaped; use{{{var}}}(triple brace) to inject raw HTML (pre-trusted content only). - Dot-notation walks nested objects:
{{order.id}},{{order.shipping.city}}. - A missing key renders as an empty string (never blocks the send).
- Rendering activates only when at least one recipient carries a non-empty
merge_vars; otherwise{{...}}is delivered literally (identical to/email).
CC / BCC: cc and bcc recipients receive an audit copy rendered against the first to recipient’s merge_vars scope.
Notes:
merge_varsmust be a JSON object — a non-object value returns400.- The combined size of all recipients’
merge_varsmust be ≤ 100 KB, else413. replyTomust be a verified sender address; it does not support{{var}}templates.- Mail merge is supported only on this HTTP endpoint (not on SMTP relay).
POST
/
email-api
curl --request POST \
--url https://email-api.mailercloud.com/email-api \
--header 'Authorization: <api-key>' \
--header 'Content-Type: <content-type>' \
--data '
{
"email": {
"from": "from@example.com",
"fromName": "John Doe",
"replyTo": [
"from@example.com"
],
"subject": "Hi {{first_name}}, your order {{order.id}} shipped",
"text": "Hi {{first_name}}, order {{order.id}} ships to {{order.city}}.",
"html": "<html><body><p>Hi {{first_name}} from {{company}},</p><p>Order <b>{{order.id}}</b> ships to {{order.city}}.</p></body></html>",
"recipients": {
"to": [
{
"name": "Recipient One",
"email": "recipient1@example.com",
"merge_vars": {
"first_name": "Alice",
"company": "Acme",
"order": {
"id": "A-100",
"city": "Berlin"
}
}
},
{
"name": "Recipient Two",
"email": "recipient2@example.com",
"merge_vars": {
"first_name": "Bob",
"company": "Acme",
"order": {
"id": "A-101",
"city": "Paris"
}
}
}
],
"cc": [
"cc1@example.com"
],
"bcc": [
"bcc1@example.com"
]
}
},
"metadata": {
"campaignType": "TRANSACTIONAL",
"timestamp": "2026-04-15T10:00:00Z",
"custom": {
"inbox_tracking": "false",
"campaign_id": ""
}
},
"version": "1.0"
}
'{
"status": "SUCCESS",
"statusCode": 1000,
"message": "NA"
}{
"status": "ERROR",
"statusCode": 9999,
"message": "merge_vars must be an object"
}{
"status": "ERROR",
"statusCode": 9999,
"message": "merge_vars exceeds 100 KB limit"
}Authorizations
Your Mailercloud API key (plain text, no Bearer prefix). Create keys in Settings → API.
Headers
Request body type
Body
application/json