Skip to main content
The HTTP API is the recommended way to send emails from your application. It supports single and batch sending with structured JSON requests.

Prerequisites

  1. A Sendmux account with at least one active delivery provider
  2. An API key with the email.send permission (create one under Settings > API Keys)
  3. Sufficient balance (check under Billing)

Send a single email

curl -X POST https://smtp.sendmux.ai/api/v1/emails/send \
  -H "Authorization: Bearer smx_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "from": { "email": "hello@yourdomain.com", "name": "Your App" },
    "to": { "email": "user@example.com", "name": "Jane Doe" },
    "subject": "Welcome to our platform",
    "html_body": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
    "text_body": "Welcome! Thanks for signing up."
  }'

Response

{
  "ok": true,
  "data": {
    "message_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "queued"
  },
  "meta": {
    "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}

Send a batch of emails

Send up to 100 emails in a single request. The API uses a partial success model — individual message failures don’t fail the entire batch.
curl -X POST https://smtp.sendmux.ai/api/v1/emails/send/batch \
  -H "Authorization: Bearer smx_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "from": { "email": "hello@yourdomain.com" },
        "to": { "email": "alice@example.com" },
        "subject": "Hello Alice",
        "html_body": "<p>Hi Alice!</p>"
      },
      {
        "from": { "email": "hello@yourdomain.com" },
        "to": { "email": "bob@example.com" },
        "subject": "Hello Bob",
        "html_body": "<p>Hi Bob!</p>"
      }
    ]
  }'

Batch response

{
  "ok": true,
  "data": {
    "results": [
      { "index": 0, "message_id": "uuid-1", "status": "queued" },
      { "index": 1, "message_id": "uuid-2", "status": "queued" }
    ],
    "summary": { "total": 2, "queued": 2, "failed": 0 }
  },
  "meta": { "request_id": "req_clxxxxxxxxxxxxxxxxxxxxxxxxx" }
}

Optional fields

FieldDescription
text_bodyPlain text fallback (recommended for deliverability)
reply_to{ "email": "...", "name": "..." } — where replies go
cc / bccArrays of { "email": "...", "name": "..." } (max 100 each)
custom_headersObject of X-* headers to include
attachmentsBase64-encoded files — see Attachments guide
idempotency_keyPrevents duplicate sends — see Idempotency guide
return_pathCustom envelope sender for bounce handling (VERP)

Error handling

Always check the ok field in the response:
const data = await response.json();

if (!data.ok) {
  console.error(`Error ${data.error.code}: ${data.error.message}`);
  // Handle specific error codes
  if (data.error.code === "insufficient_credits") {
    // Top up balance
  }
}
See the full error reference for all error codes.