API Reference
Send emails from your custom domain with a simple REST API. Available on all plans, including free.
Base URL
https://bottled.email/api/v1Authentication
Include your API key in the Authorization header. Keys are per-domain, prefixed with btl_, and generated in Dashboard > API.
header
Authorization: Bearer btl_YOUR_API_KEYQuick Start
Send your first email in one API call:
curl
curl -X POST https://bottled.email/api/v1/send \
-H "Authorization: Bearer btl_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "hello@yourdomain.com",
"to": "recipient@example.com",
"subject": "Hello from Bottled",
"text": "This email was sent via the Bottled API.",
"html": "<p>This email was sent via the Bottled API.</p>"
}'Endpoints
GET
/statusGET
/domainsGET
/domains/:namePOST
/domains/:nameGET
/emailsPOST
/emailsPOST
/sendPOST /send
Send an email from one of your verified addresses.
Request fields
| Field | Type | Required | Notes |
|---|---|---|---|
| from | string | yes | Must be a verified email |
| to | string | yes | Validated before send |
| subject | string | yes | Max 998 chars |
| text | string | one of text/html | Plain-text body |
| html | string | one of text/html | HTML body (auto-wrapped) |
| replyTo | string | no | Reply-to address |
Response
json
{
"data": {
"id": 42,
"messageId": "<abc123@mail.bottled.email>",
"from": "hello@yourdomain.com",
"to": "recipient@example.com",
"subject": "Hello from Bottled",
"status": "sent",
"sentAt": "2026-06-18T15:30:00.000Z"
}
}Code Examples
JavaScript / TypeScript
javascript
const response = await fetch("https://bottled.email/api/v1/send", {
method: "POST",
headers: {
"Authorization": "Bearer btl_YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "hello@yourdomain.com",
to: "recipient@example.com",
subject: "Hello from Bottled",
html: "<p>Sent via the Bottled API.</p>",
text: "Sent via the Bottled API.",
}),
});
const data = await response.json();
console.log(data.data.messageId);Python
python
import requests
response = requests.post(
"https://bottled.email/api/v1/send",
headers={
"Authorization": "Bearer btl_YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"from": "hello@yourdomain.com",
"to": "recipient@example.com",
"subject": "Hello from Bottled",
"html": "<p>Sent via the Bottled API.</p>",
"text": "Sent via the Bottled API.",
},
)
print(response.json())GET /status
Check your plan, current usage, and remaining quota.
json
{
"data": {
"status": "active",
"plan": "free",
"usage": {
"sent": { "used": 5, "limit": 25, "remaining": 20 },
"received": { "used": 12, "limit": 100, "remaining": 88 }
},
"period": {
"start": "2026-06-01T00:00:00.000Z",
"end": "2026-06-30T23:59:59.999Z"
}
}
}Error Codes
| Code | Status | Meaning |
|---|---|---|
| UNAUTHORIZED | 401 | Missing or invalid API key |
| VALIDATION_ERROR | 400 | Invalid request body |
| NOT_FOUND | 404 | Resource not found |
| LIMIT_EXCEEDED | 403 | Plan limit reached |
| SEND_LIMIT_REACHED | 429 | Monthly send quota exceeded |
| INVALID_RECIPIENT | 422 | Undeliverable address |
| DOMAIN_WARMUP_LIMIT | 429 | Daily warmup cap hit |
| MISSING_BODY | 400 | Email body required |
Plan Limits
| Plan | Domains | Addresses | Sent/mo | Received/mo |
|---|---|---|---|---|
| Starter (Free) | 1 | 2 | 25 | 100 |
| Essentials ($9/mo) | 3 | 10 | 300 | 1,000 |
| Pro ($29/mo) | 15 | 50 | 5,000 | 10,000 |
Ready to integrate?
Generate your API key in Dashboard > API. Free tier includes 25 sends/month.
Get Your API Key