Документация для разработчиков

Даша.Роутер

обработка входящих писем — приём, маршрутизация, webhook и хранение для API

Что такое Даша.Роутер?

Это сервис обработки входящих писем — аналог Mailgun Inbound Routes и SendGrid Inbound Parse. Вы получаете адреса вида test@rand-animal.route.dashamail.ru или moretest@your-domain.com, на которые приходят письма, и настраиваете правила: что с ними делать.

Типовые сценарии:

  • Тикет-системы и саппорт — клиент пишет на help@your-app.ru, ваш бэкенд получает HTTP POST с разобранным письмом и создаёт тикет
  • Email-to-CRM — входящие лиды автоматически попадают в воронку
  • Парсинг служебных писем — служебные уведомления (от платёжных систем, маркетплейсов) обрабатываются программно
  • Email-команды — пользователь пишет на спец. адрес типа note+task@your-app.ru, и письмо превращается в задачу

Может быть удобнее в Postman?

Все методы Даша.Роутера доступны в нашей Postman-коллекции. Импортируйте и пробуйте: DashaMail Postman Коллекции

Как обращаться к API?

API доступно по тому же адресу, что и весь остальной DashaMail API:

api.dashamail.ru

Авторизация — параметром api_key. Все методы Даша.Роутера начинаются с префикса router.. Пример вызова списка маршрутов:

https://api.dashamail.ru/?method=router.routesList&api_key=YOUR_API_KEY

На бесплатном тарифном плане API по умолчанию отключен. Для работы попросите тех. поддержку открыть его для вашего аккаунта.

Начало работы: домены

Каждому аккаунту автоматически выдан системный поддомен на route.dashamail.ru. Идентификатор — детерминированная пара «прилагательное-цвет-животное» от вашего user_id: например, bold-gold-owl.route.dashamail.ru. На этот поддомен принимаются любые localpart'ы — support@bold-gold-owl.route.dashamail.ru, tasks@bold-gold-owl.route.dashamail.ru и т. д.

Подключение своего поддомена

Если хотите принимать письма на адресах вида support@inbound.your-app.ru:

Шаг 1. В DNS-зоне своего домена создайте MX-запись на этот поддомен:

inbound.your-app.ru.  IN  MX  10  mta.dashasender.ru.

Шаг 2. В личном кабинете → Аккаунт → Интеграции → Обработка входящих → Домены добавьте свой поддомен и нажмите «Проверить» (проверка MX через DNS-резолв).

Шаг 3. После успешной проверки Даша начинает принимать SMTP на этом поддомене.

Кириллические и другие национальные домены не поддерживаются.

Создание маршрута

Маршрут — это фильтр + действия. Письмо последовательно проходит через все маршруты юзера по приоритету (от меньшего числа к большему); каждый совпавший фильтр триггерит свои действия, пока не встретится stop (как у Mailgun).

Фильтр

Структура — JSON-объект (тоже можно передавать через Mailgun-совместимую expression-строку, см. ниже):

{
  "combinator": "and",     // "and" или "or"
  "conditions": [
    {"field": "recipient", "op": "matches", "value": "support@.*"},
    {"field": "header", "name": "subject", "op": "matches", "value": "(?i)urgent"}
  ]
}
ПолеЗначение
combinatorand (все условия должны совпасть) или or (хотя бы одно)
conditionsМассив условий. Пустой = catch_all — маршрут срабатывает на любое письмо
fieldrecipient | from | sender | header
nameОбязателен при field=header. Имя заголовка (case-insensitive)
opmatches (PCRE regex) | equals (точное совпадение, case-insensitive) | contains (подстрока, case-insensitive)
valueЗначение для сравнения. Для matches — PCRE-регулярка без делимитеров (Mailgun-стиль)

Mailgun-совместимая expression-строка

Если привычнее писать фильтр одной строкой (как в Mailgun routes), API принимает параметр expression вместо filter:

match_recipient("support@.*") and match_header("subject", "(?i)urgent")

Поддерживаемые функции: match_recipient(value), match_header(name, value), catch_all(). Объединяются через and или or (один тип на выражение).

Действия

Массив объектов. Каждое действие — отдельный объект с обязательным полем type:

[
  {"type": "webhook", "url": "https://app.your-domain.ru/inbound", "attachments": "url"},
  {"type": "store", "ttl_days": 3},
  {"type": "stop"}
]
ТипПоляОписание
webhookurl (обязательное, http/https, до 2048 байт), attachments (опц., см. ниже)HTTP POST с разобранным письмом
storettl_days (опц., 1-30, default 3), notify_url (опц.)Сохранить письмо для последующего получения через API
stopПрервать обработку остальных маршрутов

На один маршрут можно задать до 5 действий.

Webhook payload

Когда срабатывает действие webhook, мы отправляем HTTP POST на ваш URL с Content-Type: application/x-www-form-urlencoded и следующими полями:

ПолеОписание
recipientSMTP envelope recipient (RCPT TO)
senderEmail отправителя (envelope sender)
fromПолный заголовок From: — расшифрованный из MIME encoded-words в UTF-8
subjectТема письма, расшифрованная из MIME encoded-words
body-plainText-версия тела (или сгенерированная из HTML, если text отсутствует)
body-htmlHTML-версия тела (если есть)
stripped-textText-тело без цитированного reply chain (только новая часть)
stripped-htmlHTML-тело без цитированного reply chain
Message-IdЗаголовок Message-ID (для дедупликации на вашей стороне)
message-headersJSON-массив пар [[name, value], ...] — все заголовки письма как есть (без декодирования)
attachment-countЧисло вложений
attachmentsJSON-массив метаданных вложений (см. раздел «Вложения»)
spfРезультат проверки SPF: pass / fail / neutral / softfail / пусто
dkimРезультат проверки DKIM: pass / fail / пусто (для писем без подписи)
dmarcРезультат проверки DMARC
route-capturesJSON-объект с именованными и numbered regex-захватами из совпавшего фильтра
timestampUnix epoch seconds момента отправки
tokenРандомная hex-строка (50 chars) — уникальна для каждой попытки
signatureHMAC-SHA256 hex от timestamp + token с signing_key маршрута

Верификация HMAC-подписи

Подпись считается по формуле:

signature = HMAC_SHA256(signing_key, timestamp + token)

где signing_key — секрет конкретного маршрута (показывается в UI при редактировании, можно перегенерировать). На стороне receiver'а нужно:

  1. Конкатенировать значения полей timestamp и token
  2. Посчитать HMAC-SHA256 от результата с ключом signing_key
  3. Сравнить с пришедшим signature (constant-time сравнение, чтобы не утечь по таймингам)
  4. Дополнительно проверить, что timestamp «свежий» (например, не старше 10 минут) — защита от replay-атак

PHP Пример верификации

<?php
$signing_key = 'your_route_signing_key_from_LK';
$timestamp = $_POST['timestamp'] ?? '';
$token     = $_POST['token'] ?? '';
$signature = $_POST['signature'] ?? '';

// 1. Recency check (защита от replay)
if (abs(time() - (int)$timestamp) > 600) {
    http_response_code(403);
    exit('stale timestamp');
}

// 2. HMAC-SHA256
$expected = hash_hmac('sha256', $timestamp . $token, $signing_key);

// 3. Constant-time сравнение
if (!hash_equals($expected, $signature)) {
    http_response_code(403);
    exit('signature mismatch');
}

// Подпись валидна — обрабатываем письмо
$from      = $_POST['from'];
$subject   = $_POST['subject'];
$body_text = $_POST['body-plain'];
// ... ваша бизнес-логика
http_response_code(200);
echo 'OK';

Python Пример (Flask)

import hmac, hashlib, time
from flask import Flask, request, abort

app = Flask(__name__)
SIGNING_KEY = b'your_route_signing_key_from_LK'

@app.route('/inbound', methods=['POST'])
def inbound():
    ts  = request.form.get('timestamp', '')
    tok = request.form.get('token', '')
    sig = request.form.get('signature', '')

    # 1. Recency
    if abs(time.time() - int(ts)) > 600:
        abort(403, 'stale timestamp')

    # 2. HMAC
    expected = hmac.new(SIGNING_KEY, (ts + tok).encode(), hashlib.sha256).hexdigest()

    # 3. Constant-time
    if not hmac.compare_digest(expected, sig):
        abort(403, 'signature mismatch')

    # OK — process
    from_ = request.form['from']
    subj  = request.form['subject']
    body  = request.form['body-plain']
    # ... your logic
    return 'OK', 200

Node.js Пример (Express)

const express = require('express');
const crypto  = require('crypto');

const app = express();
app.use(express.urlencoded({ extended: true, limit: '50mb' })); // 50mb для inline-вложений
const SIGNING_KEY = 'your_route_signing_key_from_LK';

app.post('/inbound', (req, res) => {
    const { timestamp, token, signature } = req.body;

    // 1. Recency
    if (Math.abs(Date.now() / 1000 - parseInt(timestamp, 10)) > 600) {
        return res.status(403).send('stale timestamp');
    }

    // 2. HMAC
    const expected = crypto
        .createHmac('sha256', SIGNING_KEY)
        .update(timestamp + token)
        .digest('hex');

    // 3. Constant-time
    const a = Buffer.from(expected, 'hex');
    const b = Buffer.from(signature || '', 'hex');
    if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
        return res.status(403).send('signature mismatch');
    }

    // OK — process
    const { from, subject } = req.body;
    const bodyText = req.body['body-plain'];
    // ... your logic
    res.status(200).send('OK');
});

app.listen(3000);

Вложения: три режима

Поле attachments в webhook-action принимает одно из трёх значений (по умолчанию — off):

РежимЧто в payloadКогда брать
offТолько метадата: filename, content_type, size, content_idСодержимое файлов не нужно — нужна только информация о наличии
url+ поле url со ссылкой на скачивание (presigned S3, TTL 24 часа)Lazy-fetch файлов по необходимости. Малые накладные на webhook payload
inline+ поле content_b64 с base64-кодированным содержимымReceiver не умеет HTTP-fetch / обработка должна быть синхронна с приёмом (антивирусный скан, конвертация). Тяжело для payload

Пример с inline-base64

attachments=[
  {
    "filename": "invoice.pdf",
    "content_type": "application/pdf",
    "size": 12345,
    "content_id": null,
    "content_b64": "JVBERi0xLjQKJ..."
  }
]

Ограничения для inline:

  • Суммарный размер вложений в письме — не более 25 MiB (после base64 — ~34 MB POST-body). Лишние вложения остаются в массиве с пометкой truncated: true
  • Receiver должен принимать большие POST-тела (для nginx — увеличить client_max_body_size)

Regex-захваты и подстановка в URL

В matches-фильтрах можно использовать PCRE capture-groups — numbered (...) и named (?P<name>...). Захваты:

  • Доступны в поле route-captures webhook payload как JSON-объект
  • Можно подставлять прямо в URL маршрута через \1, \2, ..., \g<name>

Пример

Маршрут: match_recipient("(?P<mailbox>[^@]+)@(?P<domain>.+)"), URL: https://app.your.ru/inbox/\g<mailbox>.

На письмо support@bold-gold-owl.route.dashamail.ru вебхук пойдёт на:

https://app.your.ru/inbox/support

и в payload будет:

route-captures={"mailbox":"support","domain":"bold-gold-owl.route.dashamail.ru"}

Хранилище (action store)

Если маршрут содержит действие store, письмо сохраняется в нашем хранилище на срок ttl_days дней (по умолчанию 3, можно задать от 1 до 30). Получить его можно через API:

МетодОписание
router.messagesListСписок сохранённых писем с фильтрами по маршруту, получателю, дате
router.messagesGetПолная карточка письма + presigned URL'ы на raw EML и вложения (TTL ссылок — 1 час, регенерируются при каждом вызове)
router.messagesAttachmentПрямая presigned-ссылка на конкретное вложение
router.messagesDeleteУдалить раньше TTL

По истечении TTL письмо автоматически удаляется (вложения + raw EML + БД-строка).

Доставка и ретраи

При сбое доставки webhook'а мы автоматически повторяем попытку. Логика по HTTP-коду ответа:

ОтветДействие
2xxdelivered — терминал, ретраи не нужны
4xxfailed — терминал, без ретраев (клиентский URL «битый», повторы бесполезны)
5xx / timeout / DNS / TLS / curl-errorretrying с экспоненциальным backoff

Расписание ретраев

ПопыткаЧерезКумулятивно
1 (исходная)00
2+60 сек~1 мин
3+5 мин~6 мин
4+30 мин~36 мин
5+2 часа~2.5 ч
финал+6 ч после 5-й попытки~9 ч до status=failed

HMAC-подпись регенерируется на каждой попытке со свежим timestamp и token — recency-проверка у receiver'а пройдёт даже через несколько часов после первой попытки.

Все попытки доставки видны в UI (Аккаунт → Интеграции → Обработка входящих → Логи доставки) и через метод router.deliveriesList.

Справочник методов API

Все методы вызываются по тому же протоколу, что и остальной DashaMail API — через https://api.dashamail.ru/?method=router.X&api_key=.... Поддерживаются HTTP GET и POST, кодировка UTF-8. Параметр format — JSON (по умолчанию), JSONP или XML.

Категории методов

router.domains* — Системный поддомен выдан автоматически, кастомные — добавляются с MX-проверкой
router.routes* — CRUD маршрутов с фильтрами и действиями. Mailgun-совместимая семантика
router.messages* — Retrieve писем, сохранённых action store. TTL по умолчанию 3 дня
router.deliveries* — Лог попыток доставки webhook'ов — статусы, ретраи, response_excerpt

Методы — Управление доменами

router.domainsList ()

Список всех доменов аккаунта: системный (default) и кастомные. Default-домен выдан автоматически и всегда verified.

router.domainsCreate (string domain)

Добавить кастомный поддомен. После создания verify_status=pending — нужно настроить MX-запись на mta.dashasender.ru и вызвать domainsVerify.

router.domainsVerify (int domain_id)

DNS-проверка MX-записи кастомного домена. При успехе verify_status переходит в verified и домен автоматически регистрируется в Даше.

router.domainsDelete (int domain_id)

Удалить кастомный поддомен. Default-домен удалить нельзя. Маршруты, привязанные к домену, не удаляются — но письма на этот домен перестают приниматься.

router.mxInstructions ()

Параметры MX-записи для настройки DNS своего поддомена. Используется UI и сторонними клиентами для генерации инструкции.

router.domainsList

router.domainsList ()

Список всех доменов аккаунта: системный (default) и кастомные. Default-домен выдан автоматически и всегда verified.

Параметры
Специфичных параметров нет — только обязательные method + api_key.
Возвращаемые значения (значения data)

Массив доменов аккаунта.

idидентификатор домена
domainполный поддомен
kindтип: default (системный) или custom (клиентский)
verify_statuspending / verified / failed
verified_atдата и время последней успешной проверки
created_atдата создания

router.domainsCreate

router.domainsCreate (string domain)

Добавить кастомный поддомен. После создания verify_status=pending — нужно настроить MX-запись на mta.dashasender.ru и вызвать domainsVerify.

Параметры
domain string клиентский поддомен (только ASCII, минимум один уровень, без trailing dot). Например, inbound.your-domain.com
Возвращаемые значения (значения data)
Объект созданного домена со структурой как в domainsList.

router.domainsVerify

router.domainsVerify (int domain_id)

DNS-проверка MX-записи кастомного домена. При успехе verify_status переходит в verified и домен автоматически регистрируется в Даше.

Параметры
domain_id int id домена из domainsList
Возвращаемые значения (значения data)
Объект домена с обновлённым verify_status.

router.domainsDelete

router.domainsDelete (int domain_id)

Удалить кастомный поддомен. Default-домен удалить нельзя. Маршруты, привязанные к домену, не удаляются — но письма на этот домен перестают приниматься.

Параметры
domain_id int id домена
Возвращаемые значения (значения data)
deletedtrue при успехе
idid удалённого домена

router.mxInstructions

router.mxInstructions ()

Параметры MX-записи для настройки DNS своего поддомена. Используется UI и сторонними клиентами для генерации инструкции.

Параметры
Специфичных параметров нет — только обязательные method + api_key.
Возвращаемые значения (значения data)
mx_targethostname MTA — куда настроить MX-запись
priorityрекомендуемый приоритет MX (10)
exampleобъект с примером DNS-записи: host, type=MX, priority, value, ttl
noteподсказка для клиента про пропагацию DNS

Методы — Маршруты

router.routesList ()

Все маршруты аккаунта, отсортированные по приоритету (по возрастанию).

router.routesGet (int route_id)

Получить один маршрут по id (включая signing_key).

router.routesCreate (string description, string expression, json filter, json actions, bool is_active, int priority)

Создать маршрут. Возвращает объект созданного маршрута с автоматически сгенерированным signing_key.

router.routesUpdate (int route_id, string description, string expression, json filter, json actions, bool is_active, int priority)

Partial-update маршрута. Обновляются только переданные поля.

router.routesDelete (int route_id)

Удалить маршрут. Логи доставки (InboundDeliveries) с этого маршрута остаются для аудита.

router.routesRegenerateKey (int route_id)

Сгенерировать новый signing_key (при компроментации). In-flight доставки, опубликованные ранее, остаются со снапшотом старого ключа — клиентский endpoint должен их пропустить через старый секрет.

router.routesReorder (json order)

Bulk-обновление приоритетов нескольких маршрутов (для drag-and-drop в UI). Маршрут на позиции i получает priority = i.

router.routesList

router.routesList ()

Все маршруты аккаунта, отсортированные по приоритету (по возрастанию).

Параметры
Специфичных параметров нет — только обязательные method + api_key.
Возвращаемые значения (значения data)
idid маршрута
priorityприоритет (целое; меньше = выше в очереди)
descriptionпользовательское описание
filtercanonical JSON фильтра ({combinator, conditions[]})
expressionMailgun-совместимая строка фильтра
actionsмассив действий (webhook/store/stop)
signing_keyHMAC-секрет (64 hex) для верификации подписи webhook
is_activetrue/false
match_countсчётчик матчей маршрута
last_matched_atвремя последнего матча
created_atдата создания
updated_atдата последнего обновления

router.routesGet

router.routesGet (int route_id)

Получить один маршрут по id (включая signing_key).

Параметры
route_id int id маршрута
Возвращаемые значения (значения data)
Объект маршрута со структурой как в routesList.

router.routesCreate

router.routesCreate (string description, string expression, json filter, json actions, bool is_active, int priority)

Создать маршрут. Возвращает объект созданного маршрута с автоматически сгенерированным signing_key.

Параметры
description string опционально – описание маршрута, до 255 символов
expression string опционально – Mailgun-совместимый фильтр одной строкой. Поддерживаемые функции: match_recipient(value), match_header(name,value), catch_all(). Объединение через and/or (один тип на выражение). Альтернатива — параметр filter
filter json опционально – фильтр в canonical-JSON формате: {"combinator":"and|or","conditions":[{field,op,value,name?}]}. Поля: recipient/from/sender/header. Ops: matches (PCRE)/equals/contains. Пустой conditions — catch_all
actions json массив действий, максимум 5. Типы: webhook (url + опц. attachments: off/url/inline), store (опц. ttl_days 1-30 и notify_url), stop
is_active bool опционально – 1 = маршрут активен (по умолчанию), 0 = выключен
priority int опционально – целое; маршруты обрабатываются по возрастанию. По умолчанию — следующее число после max существующего
Возвращаемые значения (значения data)
Объект созданного маршрута.

router.routesUpdate

router.routesUpdate (int route_id, string description, string expression, json filter, json actions, bool is_active, int priority)

Partial-update маршрута. Обновляются только переданные поля.

Параметры
route_id int id маршрута
description string опционально – новое описание
expression string опционально – новый фильтр (Mailgun-строка)
filter json опционально – новый фильтр (canonical JSON)
actions json опционально – новый массив действий
is_active bool опционально – новое состояние
priority int опционально – новый приоритет
Возвращаемые значения (значения data)
Объект обновлённого маршрута.

router.routesDelete

router.routesDelete (int route_id)

Удалить маршрут. Логи доставки (InboundDeliveries) с этого маршрута остаются для аудита.

Параметры
route_id int id маршрута
Возвращаемые значения (значения data)
deletedtrue
idid удалённого маршрута

router.routesRegenerateKey

router.routesRegenerateKey (int route_id)

Сгенерировать новый signing_key (при компроментации). In-flight доставки, опубликованные ранее, остаются со снапшотом старого ключа — клиентский endpoint должен их пропустить через старый секрет.

Параметры
route_id int id маршрута
Возвращаемые значения (значения data)
Объект маршрута с обновлённым signing_key.

router.routesReorder

router.routesReorder (json order)

Bulk-обновление приоритетов нескольких маршрутов (для drag-and-drop в UI). Маршрут на позиции i получает priority = i.

Параметры
order json JSON-массив id маршрутов в желаемом порядке. Например, [3,1,2]
Возвращаемые значения (значения data)
updatedчисло обновлённых маршрутов

Методы — Хранилище сообщений

router.messagesList (int route_id, string recipient, datetime since, datetime until, int limit, int offset)

Список сохранённых писем (от маршрутов с action store). Возвращает {items, total, limit, offset} для пагинации. Элементы — лёгкая мета (без body, без attachment-bytes); полная карточка — через messagesGet.

router.messagesGet (int message_id)

Полная карточка сообщения. Включает свежие presigned-ссылки (TTL 1 час) на raw EML и каждое вложение — регенерируются на каждый вызов, не храним. На первом обращении помечает retrieved_at.

router.messagesDelete (int message_id)

Удалить сохранённое сообщение раньше TTL. Снимает raw EML и вложения из S3, удаляет строки БД.

router.messagesAttachment (int message_id, int attachment_id)

Прямой presigned URL конкретного вложения. Удобен когда не нужна полная карточка письма — например, для скачивания файла по ссылке.

router.messagesList

router.messagesList (int route_id, string recipient, datetime since, datetime until, int limit, int offset)

Список сохранённых писем (от маршрутов с action store). Возвращает {items, total, limit, offset} для пагинации. Элементы — лёгкая мета (без body, без attachment-bytes); полная карточка — через messagesGet.

Параметры
route_id int опционально – фильтр по маршруту
recipient string опционально – LIKE-поиск по получателю
since datetime опционально – от даты, формат YYYY-MM-DD HH:MM:SS
until datetime опционально – до даты
limit int опционально – размер страницы (1-200, по умолчанию 50)
offset int опционально – смещение для пагинации (по умолчанию 0)
Возвращаемые значения (значения data)
items array массив сообщений
idid сообщения
route_idid маршрута, который сохранил
recipientSMTP RCPT TO
fromemail отправителя
subjectтема, декодированная из MIME
message_idзаголовок Message-Id
attachments_countчисло вложений
raw_sizeразмер сырого EML в байтах
expires_atвремя автоматического удаления
retrieved_atвремя первого retrieve через API (или null)
created_atвремя приёма письма
totalобщее количество с учётом фильтров
limitприменённый лимит
offsetприменённое смещение

router.messagesGet

router.messagesGet (int message_id)

Полная карточка сообщения. Включает свежие presigned-ссылки (TTL 1 час) на raw EML и каждое вложение — регенерируются на каждый вызов, не храним. На первом обращении помечает retrieved_at.

Параметры
message_id int id сообщения
Возвращаемые значения (значения data)
idid
route_idid маршрута
recipientполучатель
fromотправитель
subjectтема
message_idMessage-Id
body_textplain-текст письма
body_htmlHTML-версия (или null)
parsedparsed_json — снимок payload, как был бы отдан webhook
raw_eml_urlpresigned URL для скачивания сырого EML (TTL 1ч)
raw_sizeразмер EML в байтах
attachments array массив вложений
idid вложения
filenameимя файла
content_typeMIME-тип
sizeразмер в байтах
content_idContent-ID для inline-картинок (или null)
urlpresigned URL для скачивания (TTL 1ч)
expires_atвремя TTL-удаления
retrieved_atвремя первого retrieve
created_atвремя приёма

router.messagesDelete

router.messagesDelete (int message_id)

Удалить сохранённое сообщение раньше TTL. Снимает raw EML и вложения из S3, удаляет строки БД.

Параметры
message_id int id сообщения
Возвращаемые значения (значения data)
deletedtrue
idid удалённого сообщения

router.messagesAttachment

router.messagesAttachment (int message_id, int attachment_id)

Прямой presigned URL конкретного вложения. Удобен когда не нужна полная карточка письма — например, для скачивания файла по ссылке.

Параметры
message_id int id сообщения
attachment_id int id вложения (из массива attachments в messagesGet)
Возвращаемые значения (значения data)
filenameимя файла
content_typeMIME-тип
sizeразмер в байтах
urlpresigned URL (TTL 1ч)

Методы — Логи доставки

router.deliveriesList (int route_id, string status, string recipient, datetime since, datetime until, int limit, int offset)

История попыток доставки webhook'ов. Без чувствительных полей (signing_key, payload_json) — только метаданные для отладки. Возвращает {items, total, limit, offset}.

router.deliveriesGet (int delivery_id)

Детали одной попытки доставки. Используется для отладки 5xx-ответов клиентского endpoint.

router.deliveriesList

router.deliveriesList (int route_id, string status, string recipient, datetime since, datetime until, int limit, int offset)

История попыток доставки webhook'ов. Без чувствительных полей (signing_key, payload_json) — только метаданные для отладки. Возвращает {items, total, limit, offset}.

Параметры
route_id int опционально – фильтр по маршруту
status string опционально – фильтр: pending / delivered / failed / retrying
recipient string опционально – LIKE-поиск по получателю
since datetime опционально – от даты
until datetime опционально – до даты
limit int опционально – 1-200, default 50
offset int опционально – пагинация
Возвращаемые значения (значения data)
items array массив попыток доставки
idid попытки
route_idid маршрута, который триггерил доставку
target_urlURL клиентского endpoint
recipientполучатель письма
message_idMessage-Id входящего письма
attemptномер текущей попытки (1-based)
http_statusHTTP-код ответа (или null если transport-error)
response_excerptпервые ~1KB ответа клиента
statuspending / delivered / failed / retrying
next_retry_atвремя следующей попытки (или null)
created_atвремя первой попытки
updated_atвремя последней попытки
totalобщее количество с учётом фильтров
limitприменённый лимит
offsetприменённое смещение

router.deliveriesGet

router.deliveriesGet (int delivery_id)

Детали одной попытки доставки. Используется для отладки 5xx-ответов клиентского endpoint.

Параметры
delivery_id int id попытки доставки
Возвращаемые значения (значения data)
Объект попытки со структурой как в deliveriesList.items.

Коды ошибок

В дополнение к общим кодам:

  • 2 — Раздел недоступен / ошибка БД / недостаточно прав
  • 3 — Ошибка валидации (например, некорректный URL, regex или формат фильтра)
  • 4 — Маршрут / сообщение / доставка не найдены
  • 7 — Домен уже добавлен в этот аккаунт
  • 54 — Некорректный домен (только ASCII, минимум один уровень)
  • 55 — Домен зарезервирован системой (попытка задать *.route.dashamail.ru)
  • 56 — Домен занят другим аккаунтом

Проблемы? Вопросы?

Если возник вопрос по API или кажется, что метод не работает — пишите на support@dashamail.ru, вам помогут.