Skip to content

Email API

Send Email

POST /api/v1/emails
Authorization: Bearer {api_key}

Required scope: email:send. Keys with all_domains=false must use a from address whose domain is in the allowlist; empty from is rejected.

Request

json
{
  "from": "[email protected]",
  "to": ["[email protected]"],
  "cc": ["[email protected]"],
  "bcc": ["[email protected]"],
  "subject": "Hello World",
  "html": "<h1>Hello</h1><p>World</p>",
  "text": "Hello World",
  "reply_to": "[email protected]",
  "headers": {
    "X-Custom-Header": "value"
  }
}
FieldRequiredDescription
fromYesSender email (must be from a verified domain)
toYesArray of recipient emails
subjectYesEmail subject line
htmlYes*HTML body
textNoPlain text body (auto-generated from HTML if omitted)
ccNoCC recipients
bccNoBCC recipients
reply_toNoReply-to address
template_idNoUse a saved template instead of inline content
variablesNoTemplate variable substitutions

* Required unless template_id is provided.

Response

json
{
  "message_id": "msg_abc123",
  "status": "queued"
}

Errors

StatusCodeMeaning
403INSUFFICIENT_SCOPEAPI key lacks the email:send scope
403DOMAIN_NOT_ALLOWEDKey has all_domains=false and the from domain is not in its allowlist. Scoped keys must always supply a from.
400INVALID_FROM_ADDRESSfrom header is malformed
400DOMAIN_NOT_FOUNDfrom domain is not owned by the user
400DOMAIN_NOT_VERIFIEDfrom domain exists but DNS verification has not completed

Send Batch

POST /api/v1/emails/batch
Authorization: Bearer {api_key}

Required scope: email:send. Same allowlist rules as POST /emails — every recipient uses the same from, so the domain check runs once per batch.

json
{
  "from": "[email protected]",
  "emails": [
    { "to": "[email protected]", "subject": "Hi Alice", "html": "<p>Hello Alice</p>", "variables": { "name": "Alice" } },
    { "to": "[email protected]",   "subject": "Hi Bob",   "html": "<p>Hello Bob</p>",   "variables": { "name": "Bob"   } }
  ],
  "template_id": "tmpl_abc123"
}

Response

json
{
  "batch_id": "batch_abc123",
  "total": 2,
  "queued": 2
}

TechTrans Lab