API Documentation

Build with ApiMailer

Everything you need to integrate email sending, tracking, and management into your application.

Quickstart

Send your first email in under five minutes.

1. Create an account

Sign up for a free ApiMailer account. No credit card required.

2. Add and verify your domain

Add your sending domain in the dashboard and configure the DNS records we provide (SPF and DKIM). Verification is usually instant once the records propagate.

3. Generate an API key

Navigate to Settings → API Keys and create a new key. Copy it somewhere safe — it won't be shown again.

4. Send your first email

cURL
curl -X POST https://api.apimailer.com/v1/send \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "hello@yourdomain.com",
    "to": "user@example.com",
    "subject": "Hello from ApiMailer!",
    "html": "<h1>It works!</h1><p>Your first email via ApiMailer.</p>"
  }'
Looking for language-specific examples? Check out our SDKs & Libraries page for Node.js, Python, Ruby, PHP, Go, and more.

Authentication

All API requests require a valid API key sent in the Authorization header using Bearer token format:

Header
Authorization: Bearer YOUR_API_KEY

API keys can be created and managed from the dashboard. Each key can be scoped with specific permissions:

PermissionDescription
sendSend emails via API and SMTP
readAccess analytics, events, and logs
domainsAdd, verify, and manage sending domains
templatesCreate and manage email templates
webhooksManage webhook endpoints
adminFull account access including billing
Keep your API keys secret. Never commit them to source control. Use environment variables in production.

Base URL

All API requests should be made to:

Base URL
https://api.apimailer.com/v1

All requests must use HTTPS. HTTP requests will be rejected.

Errors

ApiMailer uses standard HTTP status codes. Errors return a JSON body with a code and message field:

Error Response
{
  "error": {
    "code": "validation_error",
    "message": "The 'to' field is required.",
    "field": "to"
  }
}
StatusMeaning
200Success
400Bad request — check your parameters
401Unauthorized — invalid or missing API key
403Forbidden — insufficient permissions
404Not found
422Validation error
429Rate limit exceeded
500Server error — try again or contact support

Send Email

Send a single email message.

POST /v1/send

Parameters

FieldTypeDescription
from requiredstringSender email address (must be on a verified domain)
to requiredstring | string[]Recipient email address(es)
subject requiredstringEmail subject line
htmlstringHTML body content
textstringPlain text body (auto-generated from HTML if omitted)
ccstring | string[]CC recipients
bccstring | string[]BCC recipients
reply_tostringReply-to address
headersobjectCustom email headers
tagsstring[]Tags for analytics and filtering
template_idstringUse a stored template instead of html/text
variablesobjectDynamic variables for template rendering

Response

200 OK
{
  "id": "msg_8f3k2j5n9x",
  "status": "queued",
  "from": "hello@yourdomain.com",
  "to": ["user@example.com"],
  "created_at": "2026-02-13T10:30:00Z"
}

Batch Send

Send up to 1,000 individual emails in a single API call. Each message can have unique recipients, subjects, and content.

POST /v1/send/batch
Request Body
{
  "messages": [
    {
      "from": "hello@yourdomain.com",
      "to": "user1@example.com",
      "subject": "Welcome!",
      "template_id": "tmpl_welcome",
      "variables": { "name": "Alice" }
    },
    {
      "from": "hello@yourdomain.com",
      "to": "user2@example.com",
      "subject": "Welcome!",
      "template_id": "tmpl_welcome",
      "variables": { "name": "Bob" }
    }
  ]
}

Templates

Create reusable email templates with dynamic variables.

POST /v1/templates
GET /v1/templates
GET /v1/templates/:id
PUT /v1/templates/:id
DELETE /v1/templates/:id

Templates use {{variable}} syntax for dynamic content, with support for conditionals and loops:

Template Example
<h1>Welcome, {{name}}!</h1>
<p>Thanks for joining {{company}}.</p>

{{#if has_coupon}}
  <p>Use code <strong>{{coupon_code}}</strong> for 20% off.</p>
{{/if}}

Add Domain

Register a new sending domain with ApiMailer.

POST /v1/domains
Request
{
  "domain": "yourdomain.com"
}
Response
{
  "id": "dom_abc123",
  "domain": "yourdomain.com",
  "status": "pending",
  "dns_records": [
    { "type": "TXT", "name": "@", "value": "v=spf1 include:_spf.apimailer.com ~all" },
    { "type": "TXT", "name": "am._domainkey", "value": "v=DKIM1; k=rsa; p=MIGf..." }
  ]
}

Verify Domain

Trigger a verification check for your domain's DNS records.

POST /v1/domains/:id/verify

Webhooks

Receive real-time notifications when email events occur. Configure webhook endpoints in the dashboard or via the API.

POST /v1/webhooks
GET /v1/webhooks
DELETE /v1/webhooks/:id
Webhook Payload Example
{
  "event": "delivered",
  "timestamp": "2026-02-13T10:30:05Z",
  "message_id": "msg_8f3k2j5n9x",
  "recipient": "user@example.com",
  "tags": ["welcome"],
  "metadata": {
    "smtp_response": "250 OK"
  }
}

All webhook payloads include an X-ApiMailer-Signature header that you should verify to ensure authenticity.

Event Types

EventDescription
queuedEmail accepted and queued for delivery
deliveredEmail successfully delivered to the recipient's server
openedRecipient opened the email
clickedRecipient clicked a link in the email
bouncedEmail bounced (hard or soft)
complainedRecipient marked email as spam
unsubscribedRecipient clicked the unsubscribe link

SMTP Relay

Use ApiMailer as an SMTP relay for existing applications. Configure your application with these settings:

SettingValue
Hostsmtp.apimailer.com
Port587 (STARTTLS) or 465 (SSL) or 25
Usernameapikey
PasswordYour API key
EncryptionTLS (recommended)
SMTP relay supports the same tracking features as the REST API. Opens, clicks, and bounces are tracked automatically.

Rate Limits

API requests are rate limited based on your plan:

PlanRequests / secondBatch size
Starter5100
Growth20500
Business1001,000
EnterpriseCustomCustom

When you exceed the rate limit, the API returns a 429 status with a Retry-After header indicating how many seconds to wait.