Отправка письма
POST /v1/emails
Authorization: Bearer mi_live_…
Content-Type: application/json
Возвращает 202 Accepted и присвоенный id ещё до фактической доставки. Итоговый статус приходит через вебхуки или его можно запросить по id.
Минимальный пример
- cURL
- Python
- TypeScript
- Go
curl -X POST https://api.mailinfra.ru/v1/emails \
-H "Authorization: Bearer mi_live_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"from": "hello@ваш-домен.ru",
"to": ["user@example.com"],
"subject": "Добро пожаловать!",
"html": "<p>Привет!</p>",
"text": "Привет!"
}'
import httpx
r = httpx.post(
"https://api.mailinfra.ru/v1/emails",
headers={"Authorization": "Bearer mi_live_xxxxxxxx"},
json={
"from": "hello@ваш-домен.ru",
"to": ["user@example.com"],
"subject": "Добро пожаловать!",
"html": "<p>Привет!</p>",
"text": "Привет!",
},
)
r.raise_for_status()
print(r.json()["data"]["id"])
const res = await fetch("https://api.mailinfra.ru/v1/emails", {
method: "POST",
headers: {
Authorization: "Bearer mi_live_xxxxxxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "hello@ваш-домен.ru",
to: ["user@example.com"],
subject: "Добро пожаловать!",
html: "<p>Привет!</p>",
text: "Привет!",
}),
});
const { data } = await res.json();
console.log(data.id);
body := strings.NewReader(`{
"from": "hello@ваш-домен.ru",
"to": ["user@example.com"],
"subject": "Добро пожаловать!",
"html": "<p>Привет!</p>"
}`)
req, _ := http.NewRequest("POST", "https://api.mailinfra.ru/v1/emails", body)
req.Header.Set("Authorization", "Bearer mi_live_xxxxxxxx")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
Ответ:
{
"data": {
"id": "018e1b7a-1111-7000-aaaa-111111111111",
"status": "QUEUED",
"skipped_recipients": []
}
}
Параметры запроса
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
from | string | да | Email отправителя. Домен должен быть верифицирован и привязан к проекту. |
from_name | string | — | Отображаемое имя (до 200 символов). В клиенте: Имя <from>. |
to | string[] | да | Получатели. Сумма to + cc + bcc ≤ 50. |
cc | string[] | — | CC. |
bcc | string[] | — | BCC. |
reply_to | string[] | — | До 10 адресов. |
subject | string | * | До 998 символов, без переводов строк. |
html | string | * | HTML-тело письма. |
text | string | * | Текстовая версия. Рекомендуется указывать вместе с html. |
headers | object | — | Пользовательские заголовки (см. ниже). |
tags | string[] | — | До 10 меток, каждая до 32 символов. |
template | string | * | Slug шаблона. |
variables | object | — | Переменные для рендера шаблона. |
* Без template обязательны subject и хотя бы одно из html / text. С template тема и тело берутся из шаблона.
Пользовательские заголовки
{
"headers": {
"X-Order-Id": "12345",
"X-User-Id": "usr_abc"
}
}
Нельзя переопределить системные заголовки: from, to, cc, bcc, subject, message-id, date, dkim-signature, x-mailinfra-*. Попытка → 422.
Идемпотентность
POST /v1/emails
Idempotency-Key: order-12345-welcome
Повтор того же запроса с тем же ключом:
200 OK(вместо202)- заголовок
Idempotent-Replayed: true - тело идентично первому ответу, повторной отправки не происходит
Используйте, если вызываете API по сетевому таймауту — это безопаснее try/except с retry.
Пропущенные получатели
Адреса из списка подавления тихо исключаются:
{
"data": {
"id": "...",
"status": "QUEUED",
"skipped_recipients": [
{ "email": "blocked@example.com", "reason": "HARD_BOUNCE" }
]
}
}
Если все получатели подавлены — письмо не создаётся, возвращается 422 с кодом all_recipients_suppressed.
Статусы письма
QUEUED → SENDING → SENT → DELIVERED
↘ BOUNCED
↘ COMPLAINED
↘ FAILED
| Статус | Значение |
|---|---|
QUEUED | Принято в очередь |
SENDING | Передаётся в MTA |
SENT | Передано SMTP-серверу получателя |
DELIVERED | Получено получателем |
BOUNCED | Недоставка |
COMPLAINED | Жалоба на спам |
FAILED | Внутренняя ошибка отправки |
SIMULATED | TEST-ключ, реальной отправки не было |
Чтение письма и событий
GET /v1/emails
GET /v1/emails/{id}
GET /v1/emails/{id}/events
Доступно ключам с правом чтения (FULL_ACCESS, READ_ONLY). Реал-тайм без поллинга — через вебхуки.
Лимиты
Все лимиты — на странице Ошибки и лимиты →.