Отправляйте по одному исходящему письму на получателя из интеграции FORM или CONTACT_FORM, используя SMTP этой интеграции (outboundMail). Вызов выполняется между серверами с X-API-Key и областью ``transactional.send``.
Это не SMTP-ретранслятор без сохранения состояния. Mailoo создаёт полный жизненный цикл отправки внутри интеграции: TransactionalSend, Message (OUTBOUND), опциональная синхронизация Subscriber, отслеживание открытий/кликов и опциональные вебхуки доставки. Подробнее об отличиях от экспорта SMTP-реквизитов см. outbound-smtp{.interpreted-text role="doc"}.
Связанные материалы: уровень SMTP --- outbound-smtp{.interpreted-text role="doc"}; токены отписки --- website-forms{.interpreted-text role="doc"}; OpenAPI --- https://api.mailoo.app/docs/v1.
Архитектура
- Инициирование, а не ретрансляция: Ваш бэкенд вызывает Mailoo; Mailoo рендерит сообщение, сохраняет записи и отправляет через ``integration.config.outboundMail`` (тот же SMTP, что и для ответов из панели управления и приветственных писем).
- Секреты: Используйте ``X-API-Key`` с ``transactional.send`` (или FULL) только с сервера или BFF --- никогда в браузерных сборках.
- Идемпотентность: Каждый запрос требует ``idempotencyKey`` (макс. 256 символов, уникальный для интеграции). Первый успешный запрос возвращает 201; повторные --- 200 с
idempotentReplay: true. - Подписчики: Mailoo создаёт или обновляет
Subscriberдля e-mail получателя. ЕслиunsubscribedAtустановлен, отправка пропускается (409, статусSKIPPED_UNSUBSCRIBED). - События доставки: Опциональные исходящие вебхуки (
delivered,opened,clicked,unsubscribed,bounced) с HMAC-подписью и повторами --- см. Вебхуки доставки ниже.
Эндпоинт отправки
``POST {baseUrl}/api/v1/webhooks/transactional/{projectUid}/{integrationId}/send``
Заголовки: Content-Type: application/json, X-API-Key (область ``transactional.send`` или FULL)
Тело (JSON):
- ``idempotencyKey`` (обязательно) --- стабильный ключ для этой логической отправки (например,
daily-2026-06-20-user123) - ``to`` (обязательно) --- e-mail получателя
- ``name`` (необязательно) --- отображаемое имя; используется для
{{User.name}}/{{firstName}} - ``templateId`` (необязательно) --- id кампании (кампания панели управления на этой интеграции); используйте либо
templateId, либо инлайнsubject+text/html - ``vars`` (необязательно) --- объект строковых/числовых/булевых переменных Mustache (см. ниже)
- ``subject``, ``text``, ``html`` (необязательно) --- инлайн-контент без
templateId; для инлайн-отправки обязательны subject и хотя бы одно изtextилиhtml
Ответы:
- 201 --- письмо отправлено (
status: SENT,idempotentReplay: false) - 200 --- идемпотентный повтор предыдущей отправки
- 409 --- получатель отписался (
status: SKIPPED_UNSUBSCRIBED) - 502 --- ошибка SMTP-отправки (
status: FAILED;Messageи вебхукBOUNCEDмогут быть записаны) - 400 --- ошибка валидации
- 403 --- у API-ключа отсутствует ``transactional.send``
- 404 --- проект/интеграция не найдены или тип не FORM/CONTACT_FORM
Пример (инлайн):
curl -X POST "https://api.mailoo.app/api/v1/webhooks/transactional/{projectUid}/{integrationId}/send" \
-H "Content-Type: application/json" \
-H "X-API-Key: mai_live_..." \
-d '{
"idempotencyKey": "daily-2026-06-20-user1",
"to": "user@example.com",
"name": "Jane Doe",
"subject": "Hi {{firstName}}",
"html": "<p>{{affirmationText}} <a href=\"{{writeUrl}}\">Write</a></p><p><a href=\"{{unsubLink}}\">Unsubscribe</a></p>",
"vars": {
"affirmationText": "You are enough.",
"writeUrl": "https://app.example.com/write"
}
}'
Пример ответа (201):
{
"success": true,
"data": {
"sendId": "clx...",
"messageId": "clx...",
"status": "SENT",
"idempotentReplay": false
}
}
Переменные Mustache
Шаблоны (templateId кампании или инлайн subject/text/html) рендерятся через Mustache перед SMTP-отправкой.
Встроенный контекст:
- ``User.email``, ``User.name`` --- из
to/name - ``firstName`` --- из
vars.firstNameили первый токенname - ``unsubLink`` --- URL для отписки в один клик (секрет подписи интеграции + API ``MAILOO_PUBLIC_APP_URL``)
- ``affirmationText``, ``writeUrl``, ``streak`` --- из
vars, когда указаны (часто используются в retention/nudge-потоках)
Дополнительные строковые/числовые/булевы ключи в vars включаются в контекст.
Отслеживание открытий и кликов
Если HTML-тело непустое, Mailoo внедряет:
- Пиксель отслеживания открытий 1×1
- Перезаписанные
https://(и//) ссылки через редиректы отслеживания кликов
Публичные маршруты (без API-ключа):
- ``GET /api/v1/public/transactional/open/{trackingToken}`` --- возвращает прозрачный GIF; фиксирует первое открытие
- ``GET /api/v1/public/transactional/click/{trackingToken}?u={urlencodedTarget}`` --- фиксирует клик, 302 редирект на целевой URL
Установите ``MAILOO_PUBLIC_API_URL`` на хосте API, чтобы URL пикселей и кликов указывали на ваш публичный API. Установите ``MAILOO_PUBLIC_APP_URL``, когда ссылки отписки и приложения должны указывать на домен панели управления.
Вебхуки доставки
При настройке Mailoo отправляет JSON-события POST-запросом на ваш эндпоинт уведомлений.
Настройка (на уровне интеграции):
integration.config.deliveryWebhook.url и .secret --- задаются в панели управления (Вебхуки доставки на вкладке Setup интеграции) или через PATCH …/integrations/{id} с deliveryWebhook.
События: delivered (после успешного SMTP), opened, clicked, unsubscribed (после вебхука отписки), bounced (ошибка SMTP).
Формат тела (JSON):
{
"event": "delivered",
"integrationId": "...",
"messageId": "...",
"idempotencyKey": "...",
"recipientEmail": "user@example.com",
"timestamp": "2026-06-20T12:00:00.000Z",
"metadata": {}
}
Подпись: Заголовок ``X-Mailoo-Signature: t={unixSeconds},v1={hex}``, где v1 --- HMAC-SHA256 строки "{timestamp}.{rawBody}" с использованием секрета вебхука. Заголовок ``X-Mailoo-Event`` дублирует имя перечисления (например, DELIVERED).
Повторы: Воркер очереди (интервал 10 с в процессе API) повторяет неудачные доставки до 8 раз с экспоненциальной задержкой (максимум 5 минут). Установите ``DISABLE_DELIVERY_WEBHOOK_WORKER=1`` только для тестов или при использовании отдельного процессора.
Предварительные требования
- Интеграция FORM или CONTACT_FORM со статусом ACTIVE
- Настроенный ``outboundMail`` (панель управления → Подключение и настройки → Исходящая почта)
- ``MAIL_SMTP_ENCRYPTION_KEY`` на API при хранении зашифрованного SMTP-пароля или секрета отписки
- API-ключ RESTRICTED или FULL с ``transactional.send``
Подпись отписки
Каждая интеграция FORM/CONTACT_FORM хранит зашифрованный HMAC-секрет отписки в integration.config. Mailoo автоматически генерирует {{unsubLink}} в транзакционных шаблонах. Владельцы могут ротировать секрет в панели управления (это инвалидирует ссылки в уже отправленных письмах). Внешние бэкенды, подписывающие собственные ссылки, должны один раз получить ротированный открытый текст или вызывать ``POST /api/v1/webhooks/unsubscribe`` с API-ключом.