Docs/API Reference

API Reference

Complete reference for all SendMailOS API endpoints.

Base URL

https://sendmailos.com/api/v1

Endpoints

POST
/messages

Send Message

Send a single email via the streaming delivery engine.

GET
/messages/:id

Get Message Status

Get the lifecycle status of a sent message.

GET
/messages/:id/events

Get Message Events

Get the append-only event timeline for a message.

POST
/message-batches

Send Batch

Send emails to multiple recipients in a single request.

GET
/message-batches/:id

Get Batch Status

Get batch status with aggregate delivery counts.

GET
/message-batches/:id/events

Get Batch Events

Get aggregated events across all messages in a batch.

POST
/send

Send Email (Legacy)

Send transactional or marketing emails with templates and personalization.

POST
/campaigns/send

Send Campaign

Queue bulk email campaigns to subscribers based on tags.

POST
/subscribers

Create Subscriber

Add or update a subscriber in your email list.

GET
/subscribers

List Subscribers

Retrieve all subscribers with pagination.

POST
/domains

Add Domain

Register a new sending domain with AWS SES verification.

GET
/domains

List Domains

Get all verified sending domains for your organization.

GET
/workflows

List Workflows

Get all automation workflows for your organization.

POST
/workflows

Create Workflow

Create a new email automation workflow.

POST
/workflows/:id/activate

Activate Workflow

Activate a workflow to start processing triggers.

POST
/workflows/:id/pause

Pause Workflow

Pause a workflow to stop processing new triggers.

GET
/webhooks

List Webhooks

Get all registered webhook endpoints.

POST
/webhooks

Create Webhook

Register a new webhook endpoint for event notifications.

POST
/webhooks/:id

Test Webhook

Send a test payload to verify webhook configuration.

GET
/pixels

List Pixels

Get all tracking pixels for email open and click tracking.

POST
/ghost/inboxes

Create Test Inbox

Create a temporary inbox for testing email delivery.

POST
/api/v1/messages

Send Message

Send a single email via the streaming delivery engine. Returns a message ID and status URL for tracking delivery.

Request Body

ParameterTypeRequiredDescription
tostringRequiredRecipient email address
fromobjectRequired{ "email": "[email protected]", "name": "Sender Name" }
subjectstringRequiredEmail subject line
htmlstringOptional*HTML content (required if no text)
textstringOptional*Plain text content (required if no html)
reply_tostringOptionalReply-to email address
external_idstringOptionalYour system's ID for correlation
metadataobjectOptionalCustom key-value data stored with the message
attachmentsarrayOptionalFile 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

bash
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)

json
{
  "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": []
}
GET
/api/v1/messages/:id

Get Message Status

Get the full lifecycle status of a sent message including delivery timestamps.

Path Parameters

ParameterTypeDescription
iduuidThe message_id returned from POST /messages

Example Request

bash
curl -X GET https://sendmailos.com/api/v1/messages/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer sk_live_..."

Response

json
{
  "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": {}
}
GET
/api/v1/messages/:id/events

Get Message Events

Get the append-only event timeline for a message. Events are ordered chronologically.

Example Request

bash
curl -X GET https://sendmailos.com/api/v1/messages/550e8400-e29b-41d4-a716-446655440000/events \
  -H "Authorization: Bearer sk_live_..."

Response

json
{
  "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" }
    }
  ]
}
POST
/api/v1/message-batches

Send 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

ParameterTypeRequiredDescription
messagesarrayRequiredArray of message objects (see below)
fromobjectRequired{ "email": "[email protected]", "name": "Sender Name" }
reply_tostringOptionalReply-to email address
scheduled_atstringOptionalISO 8601 datetime for scheduled delivery
external_idstringOptionalYour system's ID for correlation
metadataobjectOptionalCustom key-value data stored with the batch

Message Object

FieldTypeRequiredDescription
tostringRequiredRecipient email address
subjectstringRequiredEmail subject line
htmlstringOptional*HTML content (required if no text)
textstringOptional*Plain text content (required if no html)
external_idstringOptionalPer-message external ID
metadataobjectOptionalPer-message custom data

Example Request

bash
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)

json
{
  "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"
}
GET
/api/v1/message-batches/:id

Get Batch Status

Get the batch status with aggregate delivery counts.

Example Request

bash
curl -X GET https://sendmailos.com/api/v1/message-batches/770a9600-g40d-63f6-c938-668877662222 \
  -H "Authorization: Bearer sk_live_..."

Response

json
{
  "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": {}
}
GET
/api/v1/message-batches/:id/events

Get Batch Events

Get a unified event timeline across all messages in the batch, sorted chronologically.

Example Request

bash
curl -X GET https://sendmailos.com/api/v1/message-batches/770a9600-g40d-63f6-c938-668877662222/events \
  -H "Authorization: Bearer sk_live_..."

Response

json
{
  "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": {}
    }
  ]
}
POST
/api/v1/send

Send 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

ParameterTypeRequiredDescription
tostringRequiredRecipient email address
subjectstringRequiredEmail subject line
htmlstringOptional*HTML content (required if no templateId)
templateIduuidOptional*Template ID (required if no html)
from_namestringOptionalSender display name (default: "System")
from_emailstringOptionalSender email (must be from verified domain)
variablesobjectOptionalHandlebars template variables
typestringOptional"transactional" or "marketing" (default: transactional)
attachmentsarrayOptionalFile attachments (max 5 files, 7MB total)
external_idstringOptionalYour system's ID for correlation
metadataobjectOptionalCustom key-value data to store with email

Attachments

Attach files using Base64 content or a URL (fetched at send time).

FieldTypeRequiredDescription
filenamestringRequiredFilename shown to recipient
contentstringOptional*Base64-encoded file content (required if no url)
urlstringOptional*URL to fetch file from (required if no content)
contentTypestringRequiredMIME type (e.g., "application/pdf")
cidstringOptionalContent-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

bash
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

json
{
  "success": true,
  "message": "Email queued (policy: transactional 5/sec)",
  "id": "550e8400-e29b-41d4-a716-446655440000"
}
POST
/api/v1/campaigns/send

Send Campaign

Queue a bulk email campaign to subscribers. Filter by tags or send to all subscribers.

Request Body

ParameterTypeRequiredDescription
subjectstringRequiredEmail subject line
from_namestringRequiredSender display name
from_emailstringRequiredSender email (must be from verified domain)
htmlstringOptional*HTML content (required if no templateId)
templateIduuidOptional*Template ID to use
namestringOptionalCampaign name (auto-generated if omitted)
tagsstring[]OptionalFilter subscribers by tags
variablesobjectOptionalTemplate variables
external_idstringOptionalYour system's ID for tracking
metadataobjectOptionalCustom key-value data to store with campaign

Example Request

bash
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)

json
{
  "success": true,
  "message": "Campaign queued with 1,234 subscribers",
  "campaignId": "550e8400-e29b-41d4-a716-446655440000"
}
POST
/api/v1/subscribers

Create Subscriber

Add or update a subscriber. Uses upsert logic to handle existing emails gracefully.

Request Body

ParameterTypeRequiredDescription
emailstringRequiredSubscriber email address
first_namestringOptionalFirst name
last_namestringOptionalLast name
tagsstring[]OptionalCustom tags for segmentation
domain_iduuidOptionalPrimary domain association
external_idstringOptionalYour system's user/contact ID
metadataobjectOptionalCustom key-value data (e.g., source, plan)

Example Request

bash
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)

json
{
  "success": true,
  "subscriber": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "[email protected]",
    "status": "subscribed",
    "created_at": "2024-01-15T10:30:00Z",
    "source": "api"
  }
}
GET
/api/v1/subscribers

List Subscribers

Retrieve all subscribers with pagination support.

Query Parameters

ParameterTypeDefaultDescription
limitnumber20Results per page
offsetnumber0Pagination offset
external_idstring-Filter by your system's ID

Example Request

bash
curl -X GET "https://sendmailos.com/api/v1/subscribers?limit=50&offset=0" \
  -H "Authorization: Bearer sk_live_..."

Response

json
{
  "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
}
POST
/api/v1/domains

Add Domain

Register a new sending domain. Returns DNS records for DKIM verification.

Request Body

ParameterTypeRequiredDescription
domainstringRequiredDomain name to register
external_idstringOptionalYour system's domain/client ID
metadataobjectOptionalCustom key-value data (e.g., client_name)

Example Request

bash
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)

json
{
  "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.

StatusDescription
200Success
201Created - Resource created successfully
202Accepted - Request queued for processing
400Bad Request - Invalid parameters
401Unauthorized - Invalid or missing API key
403Forbidden - Domain not verified or restricted
409Conflict - Resource already exists
429Rate Limited - Too many requests
500Server Error - Try again later
json
{
  "success": false,
  "error": "Invalid email format",
  "code": "VALIDATION_ERROR"
}

Related Resources