Emails
Send transactional and marketing emails via the REST API.
Base URL
https://api.sendr.dev/v1
All endpoints require Authorization: Bearer <api_key>.
Send email
POST /v1/emails
Requires sending_access scope.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
from | string | Yes | Sender address. Format: Name <email@domain.com> or email@domain.com. Domain must be verified. |
to | string | string[] | Yes | Recipient(s). Up to 50 addresses. |
subject | string | Yes | Email subject line. |
html | string | No* | HTML body. Max 5 MB. At least one of html or text is required (unless using template_id). |
text | string | No* | Plain-text body. Max 1 MB. |
cc | string | string[] | No | CC recipients. |
bcc | string | string[] | No | BCC recipients. |
reply_to | string | No | Reply-to address. |
attachments | Attachment[] | No | Base64-encoded file attachments. |
tags | Tag[] | No | Custom key/value tags for filtering in analytics. |
headers | Record<string, string> | No | Custom email headers (e.g., X-* headers). |
scheduled_at | string (ISO 8601) | No | Schedule delivery for a future time. Must be in the future, max 1 year ahead. |
template_id | string | No | Use a saved template. Overrides html/text. |
variables | Record<string, any> | No | Template substitution variables. |
tracking | boolean | No | Enable open/click tracking. Default true. |
Attachment object:
{
filename: string; // e.g., "invoice.pdf"
content: string; // Base64-encoded file content
content_type?: string; // MIME type, default "application/octet-stream"
}
Tag object:
{
name: string; // e.g., "category"
value: string; // e.g., "welcome"
}
Example request
curl -X POST https://api.sendr.dev/v1/emails \
-H "Authorization: Bearer $SENDR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "Acme <hello@acme.com>",
"to": "user@example.com",
"subject": "Welcome to Acme!",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
"tags": [{"name": "category", "value": "welcome"}]
}'
Response
{
"id": "em_abc123",
"from": "Acme <hello@acme.com>",
"to": ["user@example.com"],
"subject": "Welcome to Acme!",
"status": "queued",
"created_at": "2025-03-12T09:00:00Z"
}
Send marketing email
POST /v1/emails/marketing
Requires sending_access scope. Marketing emails automatically include List-Unsubscribe and List-Unsubscribe-Post headers for CAN-SPAM compliance.
Request body
Same as Send email, plus:
| Field | Type | Required | Description |
|---|---|---|---|
unsubscribe_url | string | Yes | URL added to List-Unsubscribe header. Required for CAN-SPAM. |
list_id | string | No | Mailing list identifier used for list-level unsubscribe tracking. |
Send batch
POST /v1/emails/batch
Requires sending_access scope. Send up to 100 emails in a single request. All emails are queued atomically.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
emails | EmailItem[] | Yes | Array of 1–100 email objects. |
from | string | No | Default sender address for all emails (can be overridden per-email). |
subject | string | No | Default subject for all emails (can be overridden per-email). |
template_id | string | No | Default template for all emails. |
Each item in emails accepts all send fields except from, subject, and template_id at the top level can serve as defaults.
Example request
curl -X POST https://api.sendr.dev/v1/emails/batch \
-H "Authorization: Bearer $SENDR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "Acme <hello@acme.com>",
"subject": "Your order update",
"emails": [
{"to": "alice@example.com", "html": "<p>Alice, your order shipped!</p>"},
{"to": "bob@example.com", "html": "<p>Bob, your order shipped!</p>"}
]
}'
Response
{
"data": [
{"id": "em_abc123", "status": "queued"},
{"id": "em_abc124", "status": "queued"}
]
}
Get email
GET /v1/emails/:id
Requires read_only scope.
Response
{
"id": "em_abc123",
"from": "Acme <hello@acme.com>",
"to": ["user@example.com"],
"subject": "Welcome to Acme!",
"status": "delivered",
"created_at": "2025-03-12T09:00:00Z",
"sent_at": "2025-03-12T09:00:01Z",
"last_event": "opened",
"region": "us-east-1",
"attachments": []
}
Status values: queued, sent, delivered, bounced, complained
List emails
GET /v1/emails
Requires read_only scope.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Results per page (1–100). |
cursor | string | Pagination cursor from previous response's next_cursor. | |
status | string | Filter by status: queued, sent, delivered, bounced, complained. |
Response
{
"data": [
{
"id": "em_abc123",
"from": "Acme <hello@acme.com>",
"to": ["user@example.com"],
"subject": "Welcome to Acme!",
"status": "delivered",
"created_at": "2025-03-12T09:00:00Z",
"sent_at": "2025-03-12T09:00:01Z"
}
],
"has_more": false,
"next_cursor": null
}
Pagination is cursor-based. Pass next_cursor as the cursor parameter to get the next page.
Cancel email
DELETE /v1/emails/:id
Requires full_access scope. Cancels a scheduled or queued email. Returns an error if the email has already been sent.
Response
{
"id": "em_abc123",
"status": "cancelled"
}