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"
}
}| Field | Required | Description |
|---|---|---|
| from | Yes | Sender email (must be from a verified domain) |
| to | Yes | Array of recipient emails |
| subject | Yes | Email subject line |
| html | Yes* | HTML body |
| text | No | Plain text body (auto-generated from HTML if omitted) |
| cc | No | CC recipients |
| bcc | No | BCC recipients |
| reply_to | No | Reply-to address |
| template_id | No | Use a saved template instead of inline content |
| variables | No | Template variable substitutions |
* Required unless template_id is provided.
Response
json
{
"message_id": "msg_abc123",
"status": "queued"
}Errors
| Status | Code | Meaning |
|---|---|---|
| 403 | INSUFFICIENT_SCOPE | API key lacks the email:send scope |
| 403 | DOMAIN_NOT_ALLOWED | Key has all_domains=false and the from domain is not in its allowlist. Scoped keys must always supply a from. |
| 400 | INVALID_FROM_ADDRESS | from header is malformed |
| 400 | DOMAIN_NOT_FOUND | from domain is not owned by the user |
| 400 | DOMAIN_NOT_VERIFIED | from 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
}