Use the transactional API for app-triggered messages (password resets, receipts, alerts). This is not for bulk campaigns — those use Marketing domains and the campaign/automation UI.
Before you send
- Verify a transactional domain (example:
acme.com). - Complete account approval (Settings → Request Approval). Wait until status is approved.
- Create a token under Account → API Tokens.
- Send from an address on that verified domain (example:
noreply@acme.com).
Marketing-only domains will be rejected. Live sends on this endpoint require the same account approval as campaigns and automations.
Endpoint
POST https://mailivate.com/api/email
| Header | Value |
|---|---|
Authorization |
Bearer {your-api-token} |
Accept |
application/json |
Content-Type |
application/json |
Request body
Postmark-style field names and Mailivate aliases both work.
| Field | Aliases | Required | Description |
|---|---|---|---|
From |
from |
Yes | Name <email@verified-domain> or bare email on a transactional verified domain |
To |
to |
Yes | One address, or comma-separated list |
Subject |
subject |
Yes | Subject line |
HtmlBody |
html, html_body |
Yes* | HTML body |
TextBody |
text, plain_body |
No | Plain text; used to build HTML if HtmlBody is omitted |
Cc |
cc |
No | Carbon copy recipients |
Bcc |
bcc |
No | Blind carbon copy recipients |
ReplyTo |
reply_to |
No | Reply-To address |
store |
— | No | Defaults to true; set false to skip storing the send in the transactional log |
* Provide HtmlBody/html, or provide TextBody/text so Mailivate can derive HTML.
Example JSON
{
"From": "Acme App <noreply@acme.com>",
"To": "jane@example.com",
"Subject": "Your password reset link",
"HtmlBody": "<p>Click <a href=\"https://acme.com/reset\">here</a> to reset your password.</p>",
"TextBody": "Open https://acme.com/reset to reset your password."
}
Success response
{
"MessageID": "…",
"SubmittedAt": "2026-08-14T01:00:00+00:00",
"To": "jane@example.com",
"ErrorCode": 0,
"Message": "OK"
}
Standard examples
Replace the token and From domain with your values. Base URL for hosted Mailivate is always https://mailivate.com.
cURL
export MAILIVATE_URL="https://mailivate.com"
export MAILIVATE_TOKEN="your-api-token"
curl -sS -X POST "${MAILIVATE_URL}/api/email" \
-H "Authorization: Bearer ${MAILIVATE_TOKEN}" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"From": "Acme App <noreply@acme.com>",
"To": "jane@example.com",
"Subject": "Your password reset link",
"HtmlBody": "<p>Click <a href=\"https://acme.com/reset\">here</a> to reset your password.</p>"
}'
Node.js
const MAILIVATE_URL = process.env.MAILIVATE_URL ?? 'https://mailivate.com';
const MAILIVATE_TOKEN = process.env.MAILIVATE_TOKEN;
const response = await fetch(`${MAILIVATE_URL}/api/email`, {
method: 'POST',
headers: {
Authorization: `Bearer ${MAILIVATE_TOKEN}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
From: 'Acme App <noreply@acme.com>',
To: 'jane@example.com',
Subject: 'Your password reset link',
HtmlBody:
'<p>Click <a href="https://acme.com/reset">here</a> to reset your password.</p>',
}),
});
if (!response.ok) {
throw new Error(`Mailivate error ${response.status}: ${await response.text()}`);
}
const result = await response.json();
console.log(result.MessageID);
Python
import os
import requests
MAILIVATE_URL = os.environ.get("MAILIVATE_URL", "https://mailivate.com")
MAILIVATE_TOKEN = os.environ["MAILIVATE_TOKEN"]
response = requests.post(
f"{MAILIVATE_URL}/api/email",
headers={
"Authorization": f"Bearer {MAILIVATE_TOKEN}",
"Accept": "application/json",
"Content-Type": "application/json",
},
json={
"From": "Acme App <noreply@acme.com>",
"To": "jane@example.com",
"Subject": "Your password reset link",
"HtmlBody": '<p>Click <a href="https://acme.com/reset">here</a> to reset your password.</p>',
},
timeout=30,
)
response.raise_for_status()
print(response.json()["MessageID"])
PHP
<?php
$token = getenv('MAILIVATE_TOKEN');
$url = rtrim(getenv('MAILIVATE_URL') ?: 'https://mailivate.com', '/').'/api/email';
$payload = [
'From' => 'Acme App <noreply@acme.com>',
'To' => 'jane@example.com',
'Subject' => 'Your password reset link',
'HtmlBody' => '<p>Click <a href="https://acme.com/reset">here</a> to reset your password.</p>',
];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.$token,
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status < 200 || $status >= 300) {
throw new RuntimeException("Mailivate error {$status}: {$body}");
}
$result = json_decode($body, true);
echo $result['MessageID'];
Ruby
require "json"
require "net/http"
require "uri"
mailivate_url = ENV.fetch("MAILIVATE_URL", "https://mailivate.com")
token = ENV.fetch("MAILIVATE_TOKEN")
uri = URI.join(mailivate_url, "/api/email")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{token}"
request["Accept"] = "application/json"
request["Content-Type"] = "application/json"
request.body = {
From: "Acme App <noreply@acme.com>",
To: "jane@example.com",
Subject: "Your password reset link",
HtmlBody: '<p>Click <a href="https://acme.com/reset">here</a> to reset your password.</p>'
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
raise "Mailivate error #{response.code}: #{response.body}" unless response.is_a?(Net::HTTPSuccess)
puts JSON.parse(response.body)["MessageID"]
Template sends
To send a saved transactional template by name, use:
POST https://mailivate.com/api/transactional-mails/send
curl -sS -X POST "${MAILIVATE_URL}/api/transactional-mails/send" \
-H "Authorization: Bearer ${MAILIVATE_TOKEN}" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"mail_name": "order-receipt",
"from": "Store <orders@acme.com>",
"to": "jane@example.com",
"replacements": {
"order_number": "ORD-12345",
"total": "$99.00"
}
}'
See Transactional templates for creating named templates in the UI.
Common errors
| Status / message | Cause | Fix |
|---|---|---|
401 |
Missing or invalid token | Create/copy a token under Account → API Tokens |
422 on from / From |
Domain not verified for transactional use | Verify under Transactional domains; do not use a marketing-only subdomain |
406 |
Account not approved, or recipient suppressed | Complete account approval, or check Settings → Suppressions |
| Empty body / network error | Wrong host or blocked egress | Call https://mailivate.com from your backend, never from browser JavaScript |
Security
- Store
MAILIVATE_TOKENin server environment variables or a secrets manager. - Call the API only from your backend.
- Rotate and revoke unused tokens regularly.
See also
- API overview — auth, lists, subscribers, automations
- Sending domains overview — transactional vs marketing
- Transactional email overview — log and templates in the UI