Sending Emails

4 min read

This guide covers everything you need to know about sending emails through the MailingAPI.

Basic email

The simplest email requires four fields:

curl -X POST https://api.mailingapi.com/v1/messages/send \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "notifications@yourdomain.com",
    "to": "user@example.com",
    "subject": "Your order has shipped",
    "html": "<h1>Order Shipped</h1><p>Your package is on the way!</p>",
    "text": "Order Shipped\n\nYour package is on the way!"
  }'

Required fields:

  • from — Sender address (must match your verified domain)
  • to — Recipient address
  • subject — Email subject line
  • html or text — Email body (at least one required)

Sender details

From address

The from field can be just an email or include a name:

{
  "from": "hello@yourdomain.com"
}
{
  "from": "Your Company <hello@yourdomain.com>"
}

Reply-To address

Set a different reply address:

{
  "from": "notifications@yourdomain.com",
  "reply_to": "support@yourdomain.com"
}

Recipients

Single recipient

{
  "to": "user@example.com"
}

With name:

{
  "to": "John Doe <john@example.com>"
}

Multiple recipients

For the same email to multiple people (they see each other):

{
  "to": ["alice@example.com", "bob@example.com"]
}

CC and BCC

{
  "to": "primary@example.com",
  "cc": ["manager@example.com"],
  "bcc": ["archive@yourdomain.com"]
}

Note: For personalized emails to multiple recipients, use batch sending instead.

Email content

HTML and plain text

Always provide both for maximum deliverability:

{
  "html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
  "text": "Welcome!\n\nThanks for signing up."
}

If you only provide HTML, we automatically generate a text version.

Dynamic variables

Use template variables for personalization:

{
  "to": "john@example.com",
  "subject": "Welcome, {{name}}!",
  "html": "<p>Hi {{name}}, your account is ready.</p>",
  "variables": {
    "name": "John"
  }
}

Supported syntax:

  • Mustache: {{variable}}
  • Mailgun-style: %recipient.variable%

Attachments

Add files to your email (max 10 files, 10 MB each):

{
  "attachments": [
    {
      "filename": "invoice.pdf",
      "content": "base64-encoded-content-here",
      "content_type": "application/pdf"
    }
  ]
}

For inline images (displayed in HTML):

{
  "attachments": [
    {
      "filename": "logo.png",
      "content": "base64-encoded-content",
      "content_type": "image/png",
      "content_id": "logo"
    }
  ],
  "html": "<img src=\"cid:logo\" alt=\"Logo\">"
}

Custom headers

Add custom email headers:

{
  "headers": {
    "X-Campaign-ID": "welcome-series-2024",
    "X-Customer-ID": "cust_123"
  }
}

Reserved headers (set automatically):

  • From, To, Subject, Date
  • Message-ID, MIME-Version
  • DKIM-Signature

Tracking

Control open and click tracking per message:

{
  "tracking": {
    "opens": true,
    "clicks": true
  }
}

Default: both enabled (inherits from domain settings).

Transactional vs marketing emails

When both opens and clicks are disabled, the email is treated as transactional:

  • No tracking pixel (open tracking)
  • No link rewriting (click tracking)
  • No List-Unsubscribe header — this header signals to Gmail that the email is promotional/bulk, which hurts inbox placement for transactional messages

Disable tracking for:

  • Password resets and security alerts
  • Order confirmations and receipts
  • System notifications (new login, account changes)
  • 1:1 automated notifications

Keep tracking enabled for:

  • Marketing campaigns and newsletters
  • Promotional offers
  • Product updates and announcements

Example — transactional notification without tracking:

{
  "from": "alerts@yourdomain.com",
  "to": "user@example.com",
  "subject": "Your order #12345 has shipped",
  "html": "<p>Your package is on the way!</p>",
  "tracking": {
    "opens": false,
    "clicks": false
  }
}

Scheduled sending

Send emails at a specific time:

{
  "scheduled_at": "2024-12-25T09:00:00Z"
}
  • Use ISO 8601 format with timezone
  • Maximum 7 days in advance
  • Cancel with DELETE /v1/messages/{id}/schedule

List scheduled messages:

curl https://api.mailingapi.com/v1/messages/scheduled \
  -H "Authorization: Bearer $API_KEY"

Batch sending

Send personalized emails to multiple recipients efficiently:

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"}
    }
  }'

Or send completely different messages:

{
  "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>"
    }
  ]
}

Limits:

  • Maximum 1,000 messages per request
  • Each message processed independently
  • Partial failures don’t block others

Using templates

Send using a pre-defined template:

{
  "from": "hello@yourdomain.com",
  "to": "user@example.com",
  "template_id": "tmpl_welcome_email",
  "variables": {
    "name": "John",
    "activation_link": "https://example.com/activate/abc123"
  }
}

See Templates guide for creating and managing templates.

Tags and metadata

Add tags for filtering in analytics:

{
  "tags": ["welcome", "onboarding", "2024"]
}

Add metadata for your own tracking:

{
  "metadata": {
    "user_id": "usr_123",
    "campaign": "black-friday"
  }
}

Metadata is returned in webhooks and message details.

Response

Successful send returns:

{
  "id": "msg_1234567890abcdef",
  "status": "queued",
  "message": "Email queued for delivery"
}

Batch send returns:

{
  "results": [
    {"id": "msg_abc", "status": "queued", "to": "alice@example.com"},
    {"id": "msg_xyz", "status": "queued", "to": "bob@example.com"}
  ],
  "queued": 2,
  "failed": 0
}

Pre-send validation

Check your email before sending:

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",
    "html": "<p>Content here</p>"
  }'

Returns spam score, potential issues, and recommendations.

Best practices

  1. Always include text version — Some clients don’t render HTML
  2. Use templates for consistency — Avoid inline HTML when possible
  3. Set reply-to appropriately — Don’t use no-reply@ if you want responses
  4. Track with metadata — Link emails to your internal systems
  5. Test before production — Use /analyze endpoint first
  6. Handle bounces — Monitor webhooks and clean your lists

Next steps