Send Email
Send a single transactional or marketing email.
POST /api/v1/emails
Sends a single email. The from address must belong to a verified domain on the account. Authenticate with an X-API-Key header.
Headers
| Header | Required | Description |
|---|---|---|
X-API-Key | Yes | API key for the developer account |
Idempotency-Key | No | Deduplicates successful retries for 24 hours. Reusing the same key with a different request returns 409 Conflict. Maximum 256 characters. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
from | string | Yes | Sender address (must be on a verified domain) |
to | string[] | Yes | Recipient addresses |
subject | string | Yes | Email subject line |
html | string | No | HTML body |
text | string | No | Plain-text body |
template | object | No | Published template reference and variables. When provided, omit html and text |
cc | string[] | No | Carbon copy recipients |
bcc | string[] | No | Blind carbon copy recipients |
reply_to | string | No | Reply-to address |
tags | string[] | No | Labels for filtering in the dashboard |
attachments | object[] | No | Files to attach. Maximum 10 files, 10 MB per file, 20 MB total |
scheduled_at | string | No | RFC3339 timestamp for future delivery. Omit to send immediately |
type | string | No | "transactional" (default) or "marketing" |
At least one of html or text is required.
When using template, either the request or the template must provide from and subject.
Template object
| Field | Type | Required | Description |
|---|---|---|---|
id | string | No | Template ID. Required if alias is omitted |
alias | string | No | Template alias. Required if id is omitted |
variables | object | No | Values used to render {{{KEY}}} placeholders |
Attachment object
| Field | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | File name shown to the recipient |
content | string | Yes | Base64-encoded file bytes |
content_type | string | No | MIME type. If omitted, Smail guesses from the filename extension or uses application/octet-stream |
Response
Returns 200 OK with an email object:
| Field | Type | Description |
|---|---|---|
id | string | Unique email ID |
status | string | "queued", "sent", "failed", or "suppressed" |
from | string | Sender address |
to | string | Primary recipient address |
subject | string | Subject line |
created_at | string | ISO 8601 timestamp |
scheduled_at | string | Scheduled delivery timestamp, when provided |
{
"email": {
"id": "em_01hx...",
"status": "queued",
"from": "noreply@yourdomain.com",
"to": "user@example.com",
"subject": "Your order has shipped",
"created_at": "2024-01-15T10:30:00Z"
}
}Code examples
curl https://api.smail.dev/api/v1/emails \
-H "X-API-Key: sk_live_..." \
-H "Idempotency-Key: order-1234-shipped" \
-H "Content-Type: application/json" \
-d '{
"from": "noreply@yourdomain.com",
"to": ["user@example.com"],
"subject": "Your order has shipped",
"html": "<p>Your order #1234 is on its way!</p>",
"text": "Your order #1234 is on its way!",
"scheduled_at": "2026-05-14T15:30:00Z",
"attachments": [
{
"filename": "invoice.txt",
"content_type": "text/plain",
"content": "SW52b2ljZSAjMTIzNA=="
}
]
}'const { email } = await smail.emails.send({
from: "noreply@yourdomain.com",
to: ["user@example.com"],
subject: "Your order has shipped",
html: "<p>Your order #1234 is on its way!</p>",
text: "Your order #1234 is on its way!",
scheduled_at: "2026-05-14T15:30:00Z",
attachments: [
{
filename: "invoice.txt",
content_type: "text/plain",
content: "SW52b2ljZSAjMTIzNA==",
},
],
}, {
idempotencyKey: "order-1234-shipped",
});request := smail.SendEmailRequest{
From: "noreply@yourdomain.com",
To: []string{"user@example.com"},
Subject: "Your order has shipped",
HTML: "<p>Your order #1234 is on its way!</p>",
Text: "Your order #1234 is on its way!",
ScheduledAt: "2026-05-14T15:30:00Z",
Attachments: []smail.EmailAttachment{
{
Filename: "invoice.txt",
ContentType: "text/plain",
Content: "SW52b2ljZSAjMTIzNA==",
},
},
}
email, err := client.Emails.SendWithOptions(ctx, request, smail.SendOptions{
IdempotencyKey: "order-1234-shipped",
})Error responses
| Status | Error | Description |
|---|---|---|
401 | unauthorized | Missing or invalid API key |
400 | from domain not verified | The from address domain is not verified |
400 | invalid request | Missing required fields |