Транзакционные и массовые письма из вашего кода плюс верификация адресов. Все запросы — JSON поверх HTTPS, ответы — JSON.
Базовый адрес всех методов:
https://mailermail.ru/api/v1
Контракт построен на привычной модели транзакционных Email API (from/to/subject/html/text/attachments) — миграция с типового провайдера сводится к смене хоста и токена. Машиночитаемая спецификация — openapi.yaml (OpenAPI 3.0), интерактивная версия — Swagger UI.
Метод GET /health не требует токена и отвечает {"ok":true} — удобно для мониторинга.
curl https://mailermail.ru/api/v1/health{
"ok": true,
"ts": "2026-08-03T12:00:00+03:00"
}Все методы, кроме /health и /unsubscribe, требуют токен. Передайте его в одном из заголовков:
Api-Token: mm_live_…Authorization: Bearer mm_live_…Токены выпускаются в кабинете (Настройки → API). Каждый токен несёт scope:
verify — методы верификации (/verify, /verify/batch);send — всё остальное (отправка, шаблоны, стоп-лист, логи).Нет нужного scope → 403.
Токены с префиксом mm_test_ — тестовые: /send и /batch проходят весь конвейер (валидацию, проверку стоп-листа, запись в лог с пометкой sandbox), но письма физически не отправляются. Ответ содержит "sandbox": true.
curl https://mailermail.ru/api/v1/stats \
-H "Api-Token: mm_live_9f3k…"Успех — HTTP 2xx и "success": true. Ошибка — соответствующий код и тело {"success": false, "errors": ["…"]}. Массив errors содержит человекочитаемые сообщения.
| Код | Значение |
|---|---|
| 200 | Запрос обработан. Для /send частичные неудачи по получателям — в skipped/failed, код всё равно 200. |
| 400 | Некорректное тело (не JSON-объект). |
| 401 | Токен отсутствует, некорректен, неизвестен или отозван. |
| 403 | У токена нет нужного scope. |
| 404 | Ресурс не найден (эндпоинт, шаблон, сообщение). |
| 409 | Конфликт Idempotency-Key: такой ключ уже выполняется или использован для другого метода. |
| 413 | Тело или вложения превышают лимит. |
| 422 | Ошибка валидации полей. |
| 429 | Превышен лимит запросов. Заголовок Retry-After — секунд до сброса. |
| 502 | Полный провал отправки (инфраструктура) — ретрай уместен. |
| 503 | БД недоступна или часть API ещё не развёрнута. |
{
"success": false,
"errors": [
"Field 'to' (non-empty array) is required."
]
}На каждый токен — 120 запросов в минуту. При превышении метод отвечает 429 с заголовком Retry-After (секунд до конца текущего минутного окна).
Отдельные лимиты содержимого:
/send — до 50 получателей, вложения ≤10 МБ суммарно, тело ≤15 МБ;/batch — до 500 request'ов, до 1000 писем суммарно;/verify/batch — до 100 адресов.{
"success": false,
"errors": [
"Rate limit exceeded: 120 requests/minute."
]
}Методы /send и /batch принимают заголовок Idempotency-Key (произвольная строка ≤200 символов). Это защищает от двойной отправки при сетевых ретраях.
Idempotency-Replayed: true.409.5xx не кэшируются: ретрай с тем же ключом действительно повторит отправку.curl -X POST https://mailermail.ru/api/v1/send \
-H "Api-Token: mm_live_9f3k…" \
-H "Idempotency-Key: order-4211-confirm" \
-H "Content-Type: application/json" \
-d '{ … }'Синхронная транзакционная отправка: письмо уходит за секунды, у каждого получателя — свой Message-ID. Требует scope send. Домен отправителя должен быть подтверждён в аккаунте (иначе 422) — он же даёт DKIM-подпись.
Задайте subject + html и/или text, либо template_uuid (тогда тему и тело берёт шаблон — они взаимоисключимы). Переменные {{var}} подставляются из template_variables и to[].substitutions.
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
from | object | да | Отправитель: {email, name?}. Домен — verified. |
to | array | да | Получатели {email, name?, substitutions?}, ≤50. |
reply_to | object | нет | Адрес для ответа {email, name?}. |
subject | string | — | Тема, ≤255. Обязательна без template_uuid. |
html | string | — | HTML-тело. Нужно html и/или text. |
text | string | — | Текстовое тело. Если не задано — генерируется из HTML. |
category | string | нет | Метка для группировки в статистике, ≤255. |
attachments | array | нет | {content(base64), filename, type?, disposition?, content_id?}, ≤10 МБ суммарно. |
template_uuid | string | нет | UUID шаблона (взаимоисключим с subject/html/text). |
template_variables | object | нет | Глобальные переменные {{var}} (скаляры). |
options | object | нет | list_unsubscribe (bool), unsubscribe_url (https). |
curl -X POST https://mailermail.ru/api/v1/send \
-H "Api-Token: mm_live_9f3k…" \
-H "Content-Type: application/json" \
-d '{
"from": {"email": "no-reply@shop.ru", "name": "Shop"},
"to": [{"email": "ivan@example.ru"}],
"subject": "Заказ №4211 собран",
"html": "<h1>Спасибо за заказ!</h1>"
}'{
"success": true,
"message_ids": ["a1b2c3d4-…"]
}{
"success": true,
"message_ids": [],
"skipped": [
{"email": "old@dead.ru", "reason": "known_bounce"}
]
}Постановка партии писем в очередь: message_ids выдаются сразу, реально отправляет фоновый воркер (латентность до ~5 минут). Объект base задаёт общие поля, поля каждого request их перекрывают. Вложения не поддерживаются — используйте /send.
HTTP всегда 200 (кроме структурных ошибок тела): пер-письмо статусы — в массиве responses[] в порядке requests.
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
base | object | нет | Общие поля письма (как в /send, без attachments). |
requests | array | да | Массив писем (поля /send), ≤500; суммарно ≤1000 писем. |
options.send_at | string | нет | Отложить: YYYY-MM-DD HH:MM:SS UTC, окно ≤72 ч. |
options.skip_unsubscribe | bool | нет | Отключить List-Unsubscribe (в bulk он включён по умолчанию). |
curl -X POST https://mailermail.ru/api/v1/batch \
-H "Api-Token: mm_live_9f3k…" \
-H "Content-Type: application/json" \
-d '{
"base": {
"from": {"email": "news@shop.ru"},
"subject": "Скидки недели",
"html": "<p>Привет, {{name}}!</p>"
},
"requests": [
{"to": [{"email": "a@ex.ru", "substitutions": {"name": "Анна"}}]},
{"to": [{"email": "b@ex.ru", "substitutions": {"name": "Борис"}}]}
]
}'{
"success": true,
"responses": [
{"success": true, "message_ids": ["…"]},
{"success": true, "message_ids": ["…"]}
]
}Проверка адреса без отправки письма: синтаксис, MX/A домена, ролевые и одноразовые адреса, глобальный реестр недоставляемых, подсказка опечаток. Требует scope verify. Пакетом — до 100 адресов.
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
email | string | да | Один адрес (для /verify). |
emails | array | да | Массив адресов ≤100 (для /verify/batch). |
deliverable | Домен принимает почту, признаков риска нет. |
risky | Ролевой/одноразовый адрес либо вероятная опечатка домена. |
undeliverable | Синтаксис неверен, домен мёртв или адрес в реестре отказов. |
unknown | Домен не удалось проверить (временно). |
curl -X POST https://mailermail.ru/api/v1/verify \
-H "Api-Token: mm_live_9f3k…" \
-H "Content-Type: application/json" \
-d '{"email": "ivan@example.ru"}'{
"success": true,
"email": "ivan@example.ru",
"status": "deliverable",
"checks": {
"syntax": true,
"domain": "ok",
"role": false,
"disposable": false,
"known_bounce": false,
"did_you_mean": null
}
}Хранимые шаблоны письма с переменными {{var}} в теме и теле. При отправке подставляются через template_uuid + template_variables/substitutions. Требует scope send. Лимит — 1000 шаблонов на аккаунт.
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
name | string | да | Название, ≤128. Обязательно при создании. |
subject | string | нет | Тема (с {{var}}), ≤255. |
html | string | — | HTML-тело, ≤2 МБ. Нужно html и/или text. |
text | string | — | Текстовое тело, ≤2 МБ. |
category | string | нет | Метка по умолчанию, ≤255. |
GET /templates принимает ?limit= (≤100) и ?offset=. GET /templates/{uuid} возвращает шаблон целиком (с html/text). PATCH обновляет любое подмножество полей; после патча обязано остаться хотя бы одно тело. DELETE удаляет.
curl -X POST https://mailermail.ru/api/v1/templates \
-H "Api-Token: mm_live_9f3k…" \
-H "Content-Type: application/json" \
-d '{
"name": "Подтверждение заказа",
"subject": "Заказ №{{order}} принят",
"html": "<p>{{name}}, спасибо!</p>"
}'{
"success": true,
"template": {
"uuid": "7c9e6a…",
"name": "Подтверждение заказа",
"subject": "Заказ №{{order}} принят",
"category": ""
}
}curl -X DELETE \
https://mailermail.ru/api/v1/templates/7c9e6a… \
-H "Api-Token: mm_live_9f3k…"Адреса, на которые сервис не отправит письмо. Пополняется автоматически (жёсткие отказы, жалобы, отписки) и вручную через API. Требует scope send.
GET /suppressions — список (?limit= ≤1000, ?offset=, ?reason=). С ?email= — точечная проверка одного адреса.POST — добавить {emails:[…≤1000], reason?}.DELETE — убрать (снять блокировку) {emails:[…≤1000]}.manual | Добавлен вручную (по умолчанию при POST). |
hard_bounce | Жёсткий отказ (ящик не существует). |
complaint | Жалоба на спам (FBL). |
unsubscribed | Отписка через List-Unsubscribe. |
curl -X POST https://mailermail.ru/api/v1/suppressions \
-H "Api-Token: mm_live_9f3k…" \
-H "Content-Type: application/json" \
-d '{"emails": ["a@ex.ru", "b@ex.ru"], "reason": "manual"}'{
"success": true,
"added": 2,
"reason": "manual"
}{
"success": true,
"email": "a@ex.ru",
"suppressed": true,
"reason": "hard_bounce"
}Лог отправок хранится 30 дней. Требует scope send.
GET /messages| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
limit / offset | int | нет | Пагинация (limit ≤200, по умолч. 50). |
status | enum | нет | sent · sandbox · skipped · failed · queued. |
category | string | нет | Фильтр по метке. |
email | string | нет | Фильтр по получателю. |
from / to | string | нет | YYYY-MM-DD или с временем. |
GET /messages/{uuid} возвращает одно сообщение, а для писем из /batch — ещё и состояние очереди (попытки, время отправки). GET /stats?days=7|30 отдаёт агрегаты по статусам, дням и категориям + суммарный объём проверок и отправок.
curl "https://mailermail.ru/api/v1/messages?status=sent&limit=20" \
-H "Api-Token: mm_live_9f3k…"{
"success": true,
"total": 128,
"messages": [
{
"message_id": "a1b2c3-…",
"to": "ivan@example.ru",
"from": "no-reply@shop.ru",
"subject": "Заказ №4211 собран",
"status": "sent",
"created_at": "2026-08-03 12:00:01"
}
]
}curl "https://mailermail.ru/api/v1/stats?days=30" \
-H "Api-Token: mm_live_9f3k…"Публичный endpoint по стандарту RFC 8058 (One-Click). Токен не нужен — ссылку санкционирует HMAC-подпись. Его вызывают почтовые клиенты (кнопка «Отписаться» в Gmail/Yandex) и получатели.
Ссылка автоматически проставляется в заголовок List-Unsubscribe при массовой отправке (в /batch — по умолчанию; в /send — по options.list_unsubscribe). POST добавляет адрес в стоп-лист (reason=unsubscribed) и снимает подписку в кабинете; GET отдаёт человеку страницу подтверждения.
Самостоятельно формировать эти ссылки не нужно — сервис вставляет их сам.
{
"success": true,
"unsubscribed": true
}