MailEndpoints
- Scope
mail- Tier
- Build and up
- Price
- $0.001 per message + $0.0005 per recipient
- Free credit
- No, paid credit only
Send transactional email from Kaer's own sending domain. Messages leave from api-<your account id>@kaer.dev with the display name <from_name> via Kaer (your account's email domain when from_name is empty), and a short footer naming that domain and the message id for abuse reports. Replies go to reply_to.
Request body
| Parameter | Type | Default | Description |
|---|---|---|---|
toRequired | string or string[] | · | Plain addresses, up to your tier's recipients per message. Duplicates are removed; Kaer's own domains are refused. |
subjectRequired | string | · | Up to 200 characters. Line breaks become spaces. |
text | string | · | Plain-text body, up to 128 KB. Send text, html or both. |
html | string | · | HTML body, up to 256 KB. |
from_name | string | · | Display name, up to 64 characters. Quotes, <, >, @ and \ are removed. |
reply_to | string | · | One plain address. Cannot be a Kaer address. |
Idempotency-Key | header | · | Optional, up to 200 characters. See Idempotency. |
from, cc, bcc, headers and attachments are refused with 400 unsupported_field. The body is limited to 512 KB.
Response
| Field | Type | Description |
|---|---|---|
id | string | msg_ and 24 hex characters. |
object | string | mail.message |
status | string | sent when the mail server accepted it. |
from | string | The sending address. |
recipients | integer | Recipients after removing duplicates. |
idempotent_replay | boolean | true when an Idempotency-Key repeat returned the first result. |
kaer.cost_usd | number | What the message cost. Also in x-kaer-cost-usd. |
{
"id": "msg_63bd80dded23e6452659ed84",
"object": "mail.message",
"status": "sent",
"from": "api-…@kaer.dev",
"recipients": 1,
"kaer": { "request_id": "req_…", "cost_usd": 0.0015 }
}Headers: x-request-id, the x-ratelimit-* headers and x-kaer-cost-usd on a sent message. An idempotent replay has no x-kaer-cost-usd and no from.
Check a message's status
Returns id, object, status (sending, sent or failed), recipients, error (a code, or null), created_at and kaer.cost_usd. An unknown id is 404 message_not_found. We keep recipient counts and domains, never addresses, subjects or bodies.
Price
| One message to 3 recipients | $0.001 + 3 × $0.0005 | $0.0025 |
|---|---|---|
| 1,000 messages, one recipient each | 1,000 × ($0.001 + $0.0005) | $1.50 |
A message the mail server does not accept is not charged.
Stay within your tier's limits
| Tier | Recipients per day (UTC) | Messages per minute | Recipients per message |
|---|---|---|---|
| Build | 100 | 5 | 10 |
| Scale | 1,000 | 30 | 50 |
| Pro | 10,000 | 120 | 100 |
The minute cap counts messages sent in the last 60 seconds; the daily cap counts recipients since 00:00 UTC. Failed messages do not count. Over a cap you get 429 mail_rate_limit (Retry-After: 60) or mail_daily_limit (Retry-After until midnight UTC).
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_json | The body is not valid JSON. Images also needs a JSON object. |
| 400 | invalid_body | The mail body is not a JSON object. |
| 400 | unsupported_field | Mail got from, cc, bcc, headers or attachments. |
| 400 | to_required | to is missing or empty. |
| 400 | invalid_recipient | A recipient is not a plain email address. |
| 400 | reserved_recipient | A recipient is on a Kaer sending domain. |
| 400 | too_many_recipients | More recipients than your tier allows in one message. |
| 400 | subject_required | subject is missing or blank. |
| 400 | subject_too_long | subject is over 200 characters. |
| 400 | body_required | Neither text nor html was sent. |
| 400 | text_too_large | text is over 128 KB. |
| 400 | html_too_large | html is over 256 KB. |
| 400 | invalid_from_name | from_name is not a string. |
| 400 | invalid_reply_to | reply_to is not a plain email address. |
| 400 | reserved_reply_to | reply_to is a Kaer address. |
| 413 | body_too_large | The body is over the endpoint's limit: chat 1 MB, search 16 KB, batch 64 KB, images 8 KB, mail 512 KB. |
| 403 | tier_required | Your tier does not include this service yet. |
| 402 | insufficient_credits | Your balance cannot cover the call's hold. Free credit never pays for mail. |
| 429 | mail_rate_limit | Messages in the last minute reached your tier's cap. |
| 429 | mail_daily_limit | Recipients today (UTC) would pass your tier's cap. |
| 502 | mail_rejected | The mail server refused the message. Nothing was charged. |
| 502 | mail_transport_failed | The message could not be handed to the mail server. Nothing was charged. |
| 503 | mail_unavailable | Mail sending is not available. Nothing was charged. |
| 404 | message_not_found | No message with that id on this account. |
Send a message
This request sends a receipt with an Idempotency-Key, so a retry cannot send it twice.
curl https://api.kaer.ai/v1/mail/send \
-H "Authorization: Bearer $KAER_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-4812-receipt" \
-d '{
"to": ["[email protected]"],
"subject": "Your receipt",
"text": "Thanks for your order.",
"from_name": "Acme",
"reply_to": "[email protected]"
}'