Messages API
4 min read
The Messages API lets you send transactional emails, track delivery status, and manage scheduled messages.
Send email
Send a single email message.
POST /v1/messages/send
Request body
| Field | Type | Required | Description |
|---|---|---|---|
from |
string | Yes | Sender address (must match verified domain) |
to |
string/array | Yes | Recipient address(es) |
subject |
string | Yes | Email subject line |
html |
string | * | HTML body (* at least one of html/text required) |
text |
string | * | Plain text body |
cc |
array | No | CC recipients |
bcc |
array | No | BCC recipients |
reply_to |
string | No | Reply-to address |
headers |
object | No | Custom email headers |
attachments |
array | No | File attachments |
template_id |
string | No | Template ID to use |
variables |
object | No | Template variables |
tags |
array | No | Tags for analytics |
metadata |
object | No | Custom metadata |
tracking |
object | No | Tracking settings |
scheduled_at |
string | No | ISO 8601 datetime for scheduled send |
Example request
curl -X POST https://api.mailingapi.com/v1/messages/send \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "Your Company <hello@yourdomain.com>",
"to": "John Doe <john@example.com>",
"subject": "Your order has shipped",
"html": "<h1>Order Shipped</h1><p>Hi {{name}}, your order #{{order_id}} is on the way!</p>",
"text": "Order Shipped\n\nHi {{name}}, your order #{{order_id}} is on the way!",
"variables": {
"name": "John",
"order_id": "12345"
},
"tags": ["transactional", "shipping"],
"metadata": {
"user_id": "usr_123",
"order_id": "ord_456"
}
}'
Response
{
"id": "msg_1a2b3c4d5e6f",
"status": "queued",
"message": "Email queued for delivery"
}
Attachments
{
"attachments": [
{
"filename": "invoice.pdf",
"content": "base64-encoded-content",
"content_type": "application/pdf"
},
{
"filename": "logo.png",
"content": "base64-encoded-content",
"content_type": "image/png",
"content_id": "logo"
}
]
}
Use content_id for inline images, then reference with <img src="cid:logo">.
Tracking options
Control open and click tracking per message:
{
"tracking": {
"opens": true,
"clicks": true
}
}
| Field | Type | Default | Description |
|---|---|---|---|
opens |
boolean |
true |
Track email opens (inserts a tracking pixel) |
clicks |
boolean |
true |
Track link clicks (rewrites URLs through tracking domain) |
When both opens and clicks are set to false, the email is treated as transactional:
- No tracking pixel is inserted
- Links are not rewritten
-
List-Unsubscribeheader is not added (prevents Gmail from classifying the email as promotional/bulk)
Best practice: Disable tracking for transactional notifications (password resets, order confirmations, system alerts) to improve inbox placement. Keep tracking enabled for marketing and newsletter emails.
{
"from": "alerts@yourdomain.com",
"to": "user@example.com",
"subject": "New login detected",
"html": "<p>A new login was detected on your account.</p>",
"tracking": {
"opens": false,
"clicks": false
}
}
Batch send
Send multiple personalized emails in one request.
POST /v1/messages/batch
Using recipient variables
curl -X POST https://api.mailingapi.com/v1/messages/batch \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "hello@yourdomain.com",
"subject": "Welcome, {{name}}!",
"html": "<p>Hi {{name}}, your code is {{code}}.</p>",
"recipient_variables": {
"alice@example.com": {"name": "Alice", "code": "ABC123"},
"bob@example.com": {"name": "Bob", "code": "XYZ789"}
}
}'
Using messages array
curl -X POST https://api.mailingapi.com/v1/messages/batch \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"from": "hello@yourdomain.com",
"to": "alice@example.com",
"subject": "Your invoice",
"html": "<p>Invoice #001 attached.</p>"
},
{
"from": "hello@yourdomain.com",
"to": "bob@example.com",
"subject": "Your receipt",
"html": "<p>Receipt #002 attached.</p>"
}
]
}'
Response
{
"results": [
{"id": "msg_abc123", "status": "queued", "to": "alice@example.com"},
{"id": "msg_def456", "status": "queued", "to": "bob@example.com"}
],
"queued": 2,
"failed": 0
}
Limits
- Maximum 1,000 messages per request
- Each message processed independently
- Partial failures don’t block others
Get message
Retrieve details of a sent message.
GET /v1/messages/{message_id}
Example request
curl https://api.mailingapi.com/v1/messages/msg_1a2b3c4d5e6f \
-H "Authorization: Bearer $API_KEY"
Response
{
"id": "msg_1a2b3c4d5e6f",
"from": "hello@yourdomain.com",
"to": "john@example.com",
"subject": "Your order has shipped",
"status": "delivered",
"created_at": "2024-01-15T10:30:00Z",
"delivered_at": "2024-01-15T10:30:05Z",
"tags": ["transactional", "shipping"],
"metadata": {
"user_id": "usr_123",
"order_id": "ord_456"
},
"events": [
{"type": "queued", "timestamp": "2024-01-15T10:30:00Z"},
{"type": "sent", "timestamp": "2024-01-15T10:30:02Z"},
{"type": "delivered", "timestamp": "2024-01-15T10:30:05Z"},
{"type": "opened", "timestamp": "2024-01-15T11:45:00Z"}
]
}
Message statuses
| Status | Description |
|---|---|
queued |
Message accepted, waiting to send |
sending |
Message being sent |
sent |
Message sent to recipient server |
delivered |
Message accepted by recipient server |
bounced |
Message rejected by recipient server |
deferred |
Temporary failure, will retry |
failed |
Permanent failure |
List messages
Retrieve a list of sent messages.
GET /v1/messages
Query parameters
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
per_page |
integer | Items per page (default: 25, max: 100) |
from |
string | Start date (ISO 8601) |
to |
string | End date (ISO 8601) |
status |
string | Filter by status |
tag |
string | Filter by tag |
recipient |
string | Filter by recipient email |
Example request
curl "https://api.mailingapi.com/v1/messages?status=delivered&from=2024-01-01&per_page=50" \
-H "Authorization: Bearer $API_KEY"
Response
{
"data": [
{
"id": "msg_1a2b3c4d5e6f",
"from": "hello@yourdomain.com",
"to": "john@example.com",
"subject": "Your order has shipped",
"status": "delivered",
"created_at": "2024-01-15T10:30:00Z"
}
],
"meta": {
"total": 1250,
"page": 1,
"per_page": 50,
"total_pages": 25
}
}
Analyze message
Validate an email before sending. Returns spam score and potential issues.
POST /v1/messages/analyze
Example request
curl -X POST https://api.mailingapi.com/v1/messages/analyze \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "hello@yourdomain.com",
"to": "user@example.com",
"subject": "Test email",
"html": "<p>Content here</p>"
}'
Response
{
"valid": true,
"spam_score": 1.2,
"issues": [],
"recommendations": [
"Consider adding a text version for better deliverability"
],
"preview": {
"html": "<rendered html>",
"text": "<generated text>"
}
}
Schedule message
Schedule an email for future delivery. Use scheduled_at in send request:
curl -X POST https://api.mailingapi.com/v1/messages/send \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "hello@yourdomain.com",
"to": "user@example.com",
"subject": "Holiday greeting",
"html": "<p>Happy holidays!</p>",
"scheduled_at": "2024-12-25T09:00:00Z"
}'
List scheduled messages
GET /v1/messages/scheduled
Response
{
"data": [
{
"id": "msg_abc123",
"to": "user@example.com",
"subject": "Holiday greeting",
"scheduled_at": "2024-12-25T09:00:00Z",
"status": "scheduled"
}
]
}
Cancel scheduled message
DELETE /v1/messages/{message_id}/schedule
Example request
curl -X DELETE https://api.mailingapi.com/v1/messages/msg_abc123/schedule \
-H "Authorization: Bearer $API_KEY"
Response
{
"id": "msg_abc123",
"status": "cancelled",
"message": "Scheduled message cancelled"
}
Error codes
| Code | Description |
|---|---|
invalid_from_address |
From address invalid or not from verified domain |
invalid_to_address |
To address is invalid |
missing_subject |
Subject line required |
missing_body |
HTML or text body required |
attachment_too_large |
Attachment exceeds 10 MB |
too_many_attachments |
Maximum 10 attachments |
invalid_template |
Template not found or inactive |
domain_not_verified |
Sending domain not verified |
rate_limit_exceeded |
Too many requests |