API Reference
Complete reference for all SendMailOS API endpoints.
Base URL
Endpoints
/messagesSend Message
Send a single email via the streaming delivery engine.
/messages/:idGet Message Status
Get the lifecycle status of a sent message.
/messages/:id/eventsGet Message Events
Get the append-only event timeline for a message.
/message-batchesSend Batch
Send emails to multiple recipients in a single request.
/message-batches/:idGet Batch Status
Get batch status with aggregate delivery counts.
/message-batches/:id/eventsGet Batch Events
Get aggregated events across all messages in a batch.
/sendSend Email (Legacy)
Send transactional or marketing emails with templates and personalization.
/campaigns/sendSend Campaign
Queue bulk email campaigns to subscribers based on tags.
/subscribersCreate Subscriber
Add or update a subscriber in your email list.
/subscribersList Subscribers
Retrieve all subscribers with pagination.
/domainsAdd Domain
Register a new sending domain with AWS SES verification.
/domainsList Domains
Get all verified sending domains for your organization.
/workflowsList Workflows
Get all automation workflows for your organization.
/workflowsCreate Workflow
Create a new email automation workflow.
/workflows/:id/activateActivate Workflow
Activate a workflow to start processing triggers.
/workflows/:id/pausePause Workflow
Pause a workflow to stop processing new triggers.
/webhooksList Webhooks
Get all registered webhook endpoints.
/webhooksCreate Webhook
Register a new webhook endpoint for event notifications.
/webhooks/:idTest Webhook
Send a test payload to verify webhook configuration.
/pixelsList Pixels
Get all tracking pixels for email open and click tracking.
/ghost/inboxesCreate Test Inbox
Create a temporary inbox for testing email delivery.
/api/v1/messagesSend Message
Send a single email via the streaming delivery engine. Returns a message ID and status URL for tracking delivery.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| to | string | Required | Recipient email address |
| from | object | Required | { "email": "[email protected]", "name": "Sender Name" } |
| subject | string | Required | Email subject line |
| html | string | Optional* | HTML content (required if no text) |
| text | string | Optional* | Plain text content (required if no html) |
| reply_to | string | Optional | Reply-to email address |
| external_id | string | Optional | Your system's ID for correlation |
| metadata | object | Optional | Custom key-value data stored with the message |
| attachments | array | Optional | File attachments (max 10, 25 MB total). Each object: { "filename": "invoice.pdf", "content": "<base64>", "content_type": "application/pdf" }. Add cid for inline images. |
Idempotency
Include an Idempotency-Key header to prevent duplicate sends on retries.
Example Request
curl -X POST https://sendmailos.com/api/v1/messages \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-key-123" \
-d '{
"to": "[email protected]",
"from": {
"email": "[email protected]",
"name": "Your Company"
},
"subject": "Your order has shipped!",
"html": "<h1>Order Shipped</h1><p>Your order is on the way.</p>",
"attachments": [
{
"filename": "receipt.pdf",
"content": "JVBERi0xLjQK...",
"content_type": "application/pdf"
}
]
}'Response (202 Accepted)
{
"request_id": "req_abc123def456...",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"delivery_run_id": "660f9500-f39c-52e5-b827-557766551111",
"accepted": true,
"status": "queued",
"mode": "production",
"status_url": "/api/v1/messages/550e8400-e29b-41d4-a716-446655440000",
"events_url": "/api/v1/messages/550e8400-e29b-41d4-a716-446655440000/events",
"warnings": []
}/api/v1/messages/:idGet Message Status
Get the full lifecycle status of a sent message including delivery timestamps.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
| id | uuid | The message_id returned from POST /messages |
Example Request
curl -X GET https://sendmailos.com/api/v1/messages/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer sk_live_..."Response
{
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"request_id": "req_abc123def456...",
"delivery_run_id": "660f9500-f39c-52e5-b827-557766551111",
"status": "delivered",
"mode": "production",
"recipient": "[email protected]",
"from_email": "[email protected]",
"from_name": "Your Company",
"subject": "Your order has shipped!",
"external_id": null,
"provider_message_id": "01234567890abcdef",
"failure_code": null,
"failure_reason": null,
"accepted_at": "2026-03-29T10:00:00Z",
"queued_at": "2026-03-29T10:00:01Z",
"processing_at": "2026-03-29T10:00:02Z",
"provider_accepted_at": "2026-03-29T10:00:03Z",
"delivered_at": "2026-03-29T10:00:05Z",
"opened_at": null,
"clicked_at": null,
"failed_at": null,
"metadata": {}
}/api/v1/messages/:id/eventsGet Message Events
Get the append-only event timeline for a message. Events are ordered chronologically.
Example Request
curl -X GET https://sendmailos.com/api/v1/messages/550e8400-e29b-41d4-a716-446655440000/events \
-H "Authorization: Bearer sk_live_..."Response
{
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"events": [
{
"type": "accepted",
"at": "2026-03-29T10:00:00Z",
"payload": {}
},
{
"type": "queued",
"at": "2026-03-29T10:00:01Z",
"payload": {}
},
{
"type": "delivered",
"at": "2026-03-29T10:00:05Z",
"payload": { "provider_message_id": "01234567890abcdef" }
}
]
}/api/v1/message-batchesSend Batch
Send emails to multiple recipients in a single request. Small batches (100 or fewer) stream immediately; larger or scheduled batches are queued for the scheduler.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| messages | array | Required | Array of message objects (see below) |
| from | object | Required | { "email": "[email protected]", "name": "Sender Name" } |
| reply_to | string | Optional | Reply-to email address |
| scheduled_at | string | Optional | ISO 8601 datetime for scheduled delivery |
| external_id | string | Optional | Your system's ID for correlation |
| metadata | object | Optional | Custom key-value data stored with the batch |
Message Object
| Field | Type | Required | Description |
|---|---|---|---|
| to | string | Required | Recipient email address |
| subject | string | Required | Email subject line |
| html | string | Optional* | HTML content (required if no text) |
| text | string | Optional* | Plain text content (required if no html) |
| external_id | string | Optional | Per-message external ID |
| metadata | object | Optional | Per-message custom data |
Example Request
curl -X POST https://sendmailos.com/api/v1/message-batches \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"from": {
"email": "[email protected]",
"name": "Your Company"
},
"messages": [
{
"to": "[email protected]",
"subject": "March Newsletter",
"html": "<h1>Hello Alice!</h1><p>Here are your updates...</p>"
},
{
"to": "[email protected]",
"subject": "March Newsletter",
"html": "<h1>Hello Bob!</h1><p>Here are your updates...</p>"
}
]
}'Response (202 Accepted)
{
"request_id": "req_abc123def456...",
"batch_id": "770a9600-g40d-63f6-c938-668877662222",
"delivery_run_id": "880b0700-h51e-74g7-d049-779988773333",
"accepted": true,
"status": "queued",
"mode": "production",
"accepted_count": 2,
"status_url": "/api/v1/message-batches/770a9600-g40d-63f6-c938-668877662222",
"events_url": "/api/v1/message-batches/770a9600-g40d-63f6-c938-668877662222/events"
}/api/v1/message-batches/:idGet Batch Status
Get the batch status with aggregate delivery counts.
Example Request
curl -X GET https://sendmailos.com/api/v1/message-batches/770a9600-g40d-63f6-c938-668877662222 \
-H "Authorization: Bearer sk_live_..."Response
{
"batch_id": "770a9600-g40d-63f6-c938-668877662222",
"request_id": "req_abc123def456...",
"delivery_run_id": "880b0700-h51e-74g7-d049-779988773333",
"status": "completed",
"mode": "production",
"accepted_count": 500,
"queued_count": 0,
"sent_count": 498,
"failed_count": 2,
"scheduled_at": null,
"completed_at": "2026-03-29T10:05:00Z",
"accepted_at": "2026-03-29T10:00:00Z",
"external_id": null,
"metadata": {}
}/api/v1/message-batches/:id/eventsGet Batch Events
Get a unified event timeline across all messages in the batch, sorted chronologically.
Example Request
curl -X GET https://sendmailos.com/api/v1/message-batches/770a9600-g40d-63f6-c938-668877662222/events \
-H "Authorization: Bearer sk_live_..."Response
{
"batch_id": "770a9600-g40d-63f6-c938-668877662222",
"event_count": 4,
"events": [
{
"message_id": "550e8400-...",
"recipient": "[email protected]",
"type": "accepted",
"at": "2026-03-29T10:00:00Z",
"payload": {}
},
{
"message_id": "661f9511-...",
"recipient": "[email protected]",
"type": "accepted",
"at": "2026-03-29T10:00:00Z",
"payload": {}
},
{
"message_id": "550e8400-...",
"recipient": "[email protected]",
"type": "delivered",
"at": "2026-03-29T10:00:05Z",
"payload": {}
},
{
"message_id": "661f9511-...",
"recipient": "[email protected]",
"type": "delivered",
"at": "2026-03-29T10:00:06Z",
"payload": {}
}
]
}/api/v1/sendSend Email (Legacy)
Send transactional or marketing emails. Supports raw HTML content or saved templates with Handlebars variable interpolation.
Rate Limits
Transactional: 5/sec (300/min) soft limit, auto-demotes to marketing if exceeded.
Marketing: 500/sec (30,000/min) hard limit.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| to | string | Required | Recipient email address |
| subject | string | Required | Email subject line |
| html | string | Optional* | HTML content (required if no templateId) |
| templateId | uuid | Optional* | Template ID (required if no html) |
| from_name | string | Optional | Sender display name (default: "System") |
| from_email | string | Optional | Sender email (must be from verified domain) |
| variables | object | Optional | Handlebars template variables |
| type | string | Optional | "transactional" or "marketing" (default: transactional) |
| attachments | array | Optional | File attachments (max 5 files, 7MB total) |
| external_id | string | Optional | Your system's ID for correlation |
| metadata | object | Optional | Custom key-value data to store with email |
Attachments
Attach files using Base64 content or a URL (fetched at send time).
| Field | Type | Required | Description |
|---|---|---|---|
| filename | string | Required | Filename shown to recipient |
| content | string | Optional* | Base64-encoded file content (required if no url) |
| url | string | Optional* | URL to fetch file from (required if no content) |
| contentType | string | Required | MIME type (e.g., "application/pdf") |
| cid | string | Optional | Content-ID for inline images (use cid:value in HTML) |
Attachment Limits
Max 5 attachments per email • Max 5MB per file • Max 7MB total
Example Request
curl -X POST https://sendmailos.com/api/v1/send \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"to": "[email protected]",
"from_email": "[email protected]",
"from_name": "Your Company",
"subject": "Your order has shipped!",
"html": "<h1>Order Shipped</h1><p>Your order #{{order_id}} is on the way.</p>",
"variables": {
"order_id": "12345",
"tracking_url": "https://track.example.com/12345"
}
}'Response
{
"success": true,
"message": "Email queued (policy: transactional 5/sec)",
"id": "550e8400-e29b-41d4-a716-446655440000"
}/api/v1/campaigns/sendSend Campaign
Queue a bulk email campaign to subscribers. Filter by tags or send to all subscribers.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| subject | string | Required | Email subject line |
| from_name | string | Required | Sender display name |
| from_email | string | Required | Sender email (must be from verified domain) |
| html | string | Optional* | HTML content (required if no templateId) |
| templateId | uuid | Optional* | Template ID to use |
| name | string | Optional | Campaign name (auto-generated if omitted) |
| tags | string[] | Optional | Filter subscribers by tags |
| variables | object | Optional | Template variables |
| external_id | string | Optional | Your system's ID for tracking |
| metadata | object | Optional | Custom key-value data to store with campaign |
Example Request
curl -X POST https://sendmailos.com/api/v1/campaigns/send \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "January Newsletter",
"subject": "What'\''s new this month",
"from_name": "Your Company",
"from_email": "[email protected]",
"html": "<h1>January Updates</h1><p>Check out our latest features...</p>",
"tags": ["newsletter", "active"]
}'Response (202 Accepted)
{
"success": true,
"message": "Campaign queued with 1,234 subscribers",
"campaignId": "550e8400-e29b-41d4-a716-446655440000"
}/api/v1/subscribersCreate Subscriber
Add or update a subscriber. Uses upsert logic to handle existing emails gracefully.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | Required | Subscriber email address | |
| first_name | string | Optional | First name |
| last_name | string | Optional | Last name |
| tags | string[] | Optional | Custom tags for segmentation |
| domain_id | uuid | Optional | Primary domain association |
| external_id | string | Optional | Your system's user/contact ID |
| metadata | object | Optional | Custom key-value data (e.g., source, plan) |
Example Request
curl -X POST https://sendmailos.com/api/v1/subscribers \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"tags": ["newsletter", "premium"]
}'Response (201 Created)
{
"success": true,
"subscriber": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "[email protected]",
"status": "subscribed",
"created_at": "2024-01-15T10:30:00Z",
"source": "api"
}
}/api/v1/subscribersList Subscribers
Retrieve all subscribers with pagination support.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| limit | number | 20 | Results per page |
| offset | number | 0 | Pagination offset |
| external_id | string | - | Filter by your system's ID |
Example Request
curl -X GET "https://sendmailos.com/api/v1/subscribers?limit=50&offset=0" \
-H "Authorization: Bearer sk_live_..."Response
{
"success": true,
"subscribers": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"status": "subscribed",
"tags": ["newsletter", "premium"],
"source": "api",
"created_at": "2024-01-15T10:30:00Z",
"primary_domain": {
"id": "...",
"domain_name": "yourcompany.com"
}
}
],
"total": 1234,
"limit": 50,
"offset": 0
}/api/v1/domainsAdd Domain
Register a new sending domain. Returns DNS records for DKIM verification.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain | string | Required | Domain name to register |
| external_id | string | Optional | Your system's domain/client ID |
| metadata | object | Optional | Custom key-value data (e.g., client_name) |
Example Request
curl -X POST https://sendmailos.com/api/v1/domains \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"domain": "yourcompany.com",
"external_id": "client_123",
"metadata": { "client_name": "Acme Corp" }
}'Response (201 Created)
{
"success": true,
"domain": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"domain_name": "yourcompany.com",
"status": "pending",
"dkim_tokens": ["abc123...", "def456...", "ghi789..."],
"created_at": "2024-01-15T10:30:00Z",
"dns_records": [
{
"type": "CNAME",
"name": "abc123._domainkey.yourcompany.com",
"value": "abc123.dkim.amazonses.com"
},
{
"type": "CNAME",
"name": "def456._domainkey.yourcompany.com",
"value": "def456.dkim.amazonses.com"
},
{
"type": "CNAME",
"name": "ghi789._domainkey.yourcompany.com",
"value": "ghi789.dkim.amazonses.com"
}
]
}
}Error Responses
The API uses standard HTTP status codes to indicate success or failure.
| Status | Description |
|---|---|
200 | Success |
201 | Created - Resource created successfully |
202 | Accepted - Request queued for processing |
400 | Bad Request - Invalid parameters |
401 | Unauthorized - Invalid or missing API key |
403 | Forbidden - Domain not verified or restricted |
409 | Conflict - Resource already exists |
429 | Rate Limited - Too many requests |
500 | Server Error - Try again later |
{
"success": false,
"error": "Invalid email format",
"code": "VALIDATION_ERROR"
}