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

Сайты и виджеты

Сайты клиента, виджеты на них, заявки, посетители, статистика, A/B-тесты, товарные каталоги и веб-пуш.

Раздел описывает управляющее API: им пользуются интеграторы и наш MCP-сервер. Он не имеет отношения к коду, который стоит на сайте клиента, — про загрузчик, события и товары читайте «Руководство для разработчика».

СлойКто пользуетсяЧто делает
SDK на сайте разработчик сайта собирает события и показывает виджеты: один тег <script async src="https://w.dashamail.ru/s/<sk>.js">
Это API интеграторы, MCP читает и настраивает сайты, виджеты, заявки и статистику

Что такое сайт

Сайт — запись в общем реестре: к ней привязаны и виджеты, и трекер событий, и веб-пуш, и товарный каталог. Что из этого подключено, видно в modules:

МодульЧто значит
modules.widgetsна сайте есть виджеты: формы, поп-апы, полоски
modules.trackвключено отслеживание событий — просмотры, корзина, заказы
modules.pushподключён веб-пуш
modules.feedподключён товарный каталог YML

site_key — тот самый sk из тега на странице. Он считается от адреса один раз и при переименовании сайта не меняется: менять тег на сайте клиента после правки названия не нужно.

Права ключа

Обычный ключ из личного кабинета делает всё, что разрешено аккаунту. Ключ, выданный через OAuth, несёт список прав — для этого раздела их четыре:

ПравоЧто открывает
sites.readсайты, виджеты, статистика, тесты, каталоги, веб-пуш, события, вебхуки
sites.writeподключение сайтов и доменов, включение виджетов, каталоги, вебхуки
leads.readзаявки и посетители
leads.writeповтор доставки заявки

Заявки и посетители вынесены в отдельное право: в них персональные данные, и токен «посмотреть статистику» не должен заодно читать телефоны. leads.read не включает sites.read — ключу, который читает заявки и при этом ищет сайт по списку, нужны оба.

Права субаккаунта проверяются отдельно от прав ключа и раньше них: уровень «только чтение» закрывает изменяющие запросы (code: 65), полный запрет — весь раздел. События, веб-пуш и товарные каталоги спрашивают своё право — то же, что в кабинете отвечает за интеграции.

Лимиты тарифа

Количество сайтов, одновременно включённых виджетов и идущих A/B-тестов ограничено тарифом «Сайты и виджеты»; текущие потолки и расход отдаёт тариф и расход. Упёрлись в потолок — отказ code: 69 с цифрами в теле ответа:

{
  "error": {
    "code": 69,
    "message": "На вашем тарифе можно подключить 1 сайт. Чтобы добавить ещё — тариф «Сайты и виджеты» в разделе «Оплата»",
    "details": { "what": "sites", "limit": 1, "current": 1 }
  }
}

Лимит просмотров считается за расчётный период подписки. Исчерпали его — рантайм перестаёт отдавать сайт, и у сайта появляется status: "blocked"; виджеты и настройки при этом читаются как обычно.

Отказ по значению поля

Когда запрос не проходит проверку (422, code: 67), рядом с message приходит разбор по полям — в нём видно, что именно поправить:

{
  "error": {
    "code": 67,
    "message": "Это должен быть поддомен example.ru",
    "details": { "errors": [ { "path": "domain", "message": "Это должен быть поддомен example.ru, например m.example.ru" } ] }
  }
}

Страницы и выгрузки

Списки заявок, посетителей и виджетов постраничные: limit и offset, признак следующей страницы — в meta.has_more. Остальные списки раздела короткие и отдаются целиком.

Заявки и посетителей можно забрать таблицей: format=csv отдаёт text/csv вместо JSON. limit и offset при этом не действуют — выгружается вся выборка.

У заявок отбор тот же, что у списка. Посетители выгружаются целиком, без отбора: это тот же файл «Вся база в CSV», что отдаёт кабинет.

Разделитель у двух выгрузок разный — так сложилось, и мы это сохраняем, чтобы у клиентов не поменялись уже разобранные файлы. Пишите разбор по таблице ниже, а не по догадке.

ВыгрузкаРазделительБайтыПереносы
заявки ; UTF-8 с BOM — чтобы кириллица открывалась в Excel LF
посетители , UTF-8 без BOM CRLF

В обеих кавычки удваиваются, и в кавычки берётся значение, внутри которого есть разделитель или перенос строки.

Даты и время

Время — московское, формат ГГГГ-ММ-ДД ЧЧ:ММ:СС. Параметры отбора по датам (from, to) — ГГГГ-ММ-ДД включительно.

Статистика

Показы, заявки и просмотры страниц считаются в отдельном хранилище и обновляются раз в сутки, поэтому сегодняшний день в отчёте неполный. Хранилище недоступно — методы статистики отвечают 503 и code: 70, а остальные методы раздела продолжают работать.

Конверсия — заявки на 100 показов, не на посетителей.

Список сайтов #

GET /sites

Все сайты аккаунта — и с виджетами, и подключённые только под трекер, веб-пуш или товарный каталог.

Что возвращается

track — счётчики трекера: устройства, события и время последнего события. У сайта без трекера они нулевые. Сайты, которыми с аккаунтом поделились через совместный доступ, в список не попадают: это настройка кабинета.

curl -X GET 'https://api.dashamail.com/v2/sites' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "id": 100842,
        "name": "Магазин «Ромашка»",
        "url": "https://example.ru/",
        "host": "example.ru",
        "protocol": "https",
        "status": "enabled",
        "site_key": "9f2c4b7e51a8d3604ef1c29b7a5d8e03",
        "modules": {
          "widgets": true,
          "track": true,
          "push": false,
          "feed": true
        },
        "script_status": "installed",
        "script_seen_at": "2026-10-27 09:14:02",
        "loader_version": "v2",
        "isolation": "shadow",
        "widgets_total": 7,
        "widgets_enabled": 3,
        "tests_total": 1,
        "track": {
          "devices": 18420,
          "events": 264913,
          "last_event": "2026-10-27 11:48:31"
        },
        "created_at": "2026-03-14 11:02:41",
        "updated_at": "2026-10-20 16:31:05"
      }
    ]
  }
}

Один сайт #

GET /sites/{site_id}

Сайт целиком: поля списка, его домены и код установки.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Что возвращается

domains — домены сайта: main — основной, alt — дополнительные. В install_code.current лежит тег, который нужно поставить на сайт сейчас; v1 — старый загрузчик, он остаётся рабочим на уже установленных сайтах.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": 100842,
      "name": "Магазин «Ромашка»",
      "url": "https://example.ru/",
      "host": "example.ru",
      "protocol": "https",
      "status": "enabled",
      "site_key": "9f2c4b7e51a8d3604ef1c29b7a5d8e03",
      "script_status": "installed",
      "script_seen_at": "2026-10-27 09:14:02",
      "loader_version": "v2",
      "isolation": "shadow",
      "widgets_total": 7,
      "widgets_enabled": 3,
      "tests_total": 1,
      "created_at": "2026-03-14 11:02:41",
      "updated_at": "2026-10-20 16:31:05",
      "modules": {
        "widgets": true,
        "track": true,
        "push": false,
        "feed": true
      },
      "track": {
        "devices": 18420,
        "events": 264913,
        "last_event": "2026-10-27 11:48:31"
      },
      "domains": [
        {
          "domain": "example.ru",
          "kind": "main"
        },
        {
          "domain": "m.example.ru",
          "kind": "alt"
        }
      ],
      "install_code": {
        "current": "<script async src=\"https://w.dashamail.ru/s/9f2c4b7e51a8d3604ef1c29b7a5d8e03.js\"></script>",
        "v2": "<script async src=\"https://w.dashamail.ru/s/9f2c4b7e51a8d3604ef1c29b7a5d8e03.js\"></script>",
        "v1": "<script async defer src=\"https://w.dashamail.ru/loader.js?sk=9f2c4b7e51a8d3604ef1c29b7a5d8e03\"></script>"
      }
    }
  }
}

Подключить сайт #

POST /sites

Заводит сайт по адресу. Код установки возвращается сразу — ставить его на сайт можно до всякой настройки.

Свой сайт, подключённый ранее только под трекер, веб-пуш или каталог, не дублируется: к нему просто подключаются виджеты, и в ответ приходит та же запись. Удалённый сайт восстанавливается.

Параметры тела запроса

ПараметрТипОписание
url обязательныйstringАдрес сайта, например https://example.ru. Хост нормализуется: приводится к нижнему регистру, www отбрасывается, кириллица переводится в punycode.
namestringНазвание для кабинета, не длиннее 300 символов. Не задано — берётся хост.

Что возвращается

Тот же набор полей, что у сайта в списке, плюс install_code.

Возможные ошибки

HTTPcodeКогда возникает
422 3 Адрес не задан или не разбирается
409 68 Сайт уже подключён к этому аккаунту либо занят другим — в этом случае нужна поддержка
409 69 Исчерпан лимит сайтов на тарифе
403 65 Недостаточно прав
curl -X POST 'https://api.dashamail.com/v2/sites' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "url": "https://example.ru",
  "name": "Магазин «Ромашка»"
}'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode([
            'url' => 'https://example.ru',
            'name' => 'Магазин «Ромашка»',
        ], JSON_UNESCAPED_UNICODE),
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.post(
    'https://api.dashamail.com/v2/sites',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={
        'url': 'https://example.ru',
        'name': 'Магазин «Ромашка»',
    },
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "url": "https://example.ru",
  "name": "Магазин «Ромашка»"
}),
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 201
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": 100842,
      "name": "Магазин «Ромашка»",
      "url": "https://example.ru/",
      "host": "example.ru",
      "protocol": "https",
      "status": "enabled",
      "site_key": "9f2c4b7e51a8d3604ef1c29b7a5d8e03",
      "script_status": "unknown",
      "script_seen_at": null,
      "loader_version": "v2",
      "isolation": "none",
      "widgets_total": 0,
      "widgets_enabled": 0,
      "tests_total": 0,
      "created_at": "2026-10-28 16:40:11",
      "updated_at": "2026-10-28 16:40:11",
      "modules": {
        "widgets": true,
        "track": false,
        "push": false,
        "feed": false
      },
      "track": {
        "devices": 0,
        "events": 0,
        "last_event": ""
      },
      "install_code": {
        "current": "<script async src=\"https://w.dashamail.ru/s/9f2c4b7e51a8d3604ef1c29b7a5d8e03.js\"></script>"
      }
    }
  }
}

Изменить сайт #

PUT /sites/{site_id}

Меняет настройки сайта. Передавайте только то, что нужно изменить — незаданные поля сохраняют прежние значения.

Адрес сайта (url) не меняется: на нём стоит site_key, зашитый в тег на страницах клиента. Переехали на другой домен — добавьте его доменом сайта.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры тела запроса

ПараметрТипОписание
namestringНазвание сайта.
isolationstringИзоляция виджетов от CSS сайта. shadow — рисовать виджеты в Shadow DOM: вёрстка сайта на них не влияет.
Допустимые значения: none, shadow
cookie_domainstringДомен для куки посетителя. Нужен, когда посетитель должен опознаваться на поддоменах как один человек.
domainsarrayДополнительные домены сайта списком — заменяет прежний набор целиком. [] убирает все.

Что возвращается

Сайт целиком — тот же набор полей, что в списке.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
422 67 Недопустимое значение поля
409 68 Один из доменов уже занят другим сайтом
403 65 Недостаточно прав
curl -X PUT 'https://api.dashamail.com/v2/sites/100842' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Магазин «Ромашка»",
  "isolation": "shadow"
}'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode([
            'name' => 'Магазин «Ромашка»',
            'isolation' => 'shadow',
        ], JSON_UNESCAPED_UNICODE),
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.put(
    'https://api.dashamail.com/v2/sites/100842',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={
        'name': 'Магазин «Ромашка»',
        'isolation': 'shadow',
    },
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842', {
  method: 'PUT',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "name": "Магазин «Ромашка»",
  "isolation": "shadow"
}),
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": 100842,
      "name": "Магазин «Ромашка»",
      "host": "example.ru",
      "status": "enabled",
      "isolation": "shadow",
      "modules": {
        "widgets": true,
        "track": true,
        "push": false,
        "feed": true
      },
      "track": {
        "devices": 18420,
        "events": 264913,
        "last_event": "2026-10-27 11:48:31"
      }
    }
  }
}

Код установки и его состояние #

GET /sites/{site_id}/install

Тег для вставки на сайт и признак того, видели ли мы его на страницах.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Что возвращается

script_status: installed — код видели, unknown — ещё нет, missing — раньше видели, а теперь нет. script_seen_at — когда код отзывался последний раз. Признак ставит сам загрузчик, отдельной проверки запускать не нужно.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842/install' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/install');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/install',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/install', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "install_code": {
        "current": "<script async src=\"https://w.dashamail.ru/s/9f2c4b7e51a8d3604ef1c29b7a5d8e03.js\"></script>",
        "v2": "<script async src=\"https://w.dashamail.ru/s/9f2c4b7e51a8d3604ef1c29b7a5d8e03.js\"></script>",
        "v1": "<script async defer src=\"https://w.dashamail.ru/loader.js?sk=9f2c4b7e51a8d3604ef1c29b7a5d8e03\"></script>"
      },
      "script_status": "installed",
      "script_seen_at": "2026-10-27 09:14:02",
      "loader_version": "v2"
    }
  }
}

Домены сайта #

GET /sites/{site_id}/domains

Домены, на которых работает сайт: основной и дополнительные.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Что возвращается

list_id — адресная база, в которую складывает подписчиков трекер этого домена; 0 — не задана.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
403 65 У субаккаунта нет права на модули сайта
curl -X GET 'https://api.dashamail.com/v2/sites/100842/domains' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/domains');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/domains',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/domains', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "domain": "example.ru",
        "kind": "main",
        "list_id": 128341
      },
      {
        "domain": "m.example.ru",
        "kind": "alt",
        "list_id": 0
      }
    ]
  }
}

Добавить домен сайта #

POST /sites/{site_id}/domains

Добавляет домен, на котором тоже стоит код сайта. Виджеты, заявки и статистика у доменов одного сайта общие.

Добавить можно только поддомен основного домена сайта: посетитель на m.example.ru и example.ru — один человек, а на чужом домене — другой сайт.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры тела запроса

ПараметрТипОписание
domain обязательныйstringДомен, например m.example.ru.

Что возвращается

В ответе — весь список доменов сайта после добавления, а не один добавленный.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
422 3 Не передан domain
422 67 Домен некорректен, не является поддоменом основного либо их уже 20
409 68 Домен у сайта уже есть
403 65 У субаккаунта нет права на модули сайта
curl -X POST 'https://api.dashamail.com/v2/sites/100842/domains' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "domain": "m.example.ru"
}'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/domains');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode([
            'domain' => 'm.example.ru',
        ], JSON_UNESCAPED_UNICODE),
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.post(
    'https://api.dashamail.com/v2/sites/100842/domains',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={
        'domain': 'm.example.ru',
    },
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/domains', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "domain": "m.example.ru"
}),
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 201
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "domain": "example.ru",
        "kind": "main",
        "list_id": 128341
      },
      {
        "domain": "m.example.ru",
        "kind": "alt",
        "list_id": 0
      }
    ]
  }
}

Удалить домен сайта #

DELETE /sites/{site_id}/domains/{domain}

Отвязывает дополнительный домен. Основной домен сайта удалить нельзя.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
domain обязательныйstringДомен, который нужно отвязать.

Возможные ошибки

HTTPcodeКогда возникает
404 4 У сайта нет такого домена
409 68 Это основной домен сайта: он задаёт ключ, по которому сайт находит рантайм
403 65 У субаккаунта нет права на модули сайта
curl -X DELETE 'https://api.dashamail.com/v2/sites/100842/domains/m.example.ru' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/domains/m.example.ru');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.delete(
    'https://api.dashamail.com/v2/sites/100842/domains/m.example.ru',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/domains/m.example.ru', {
  method: 'DELETE',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 204
(тело ответа пустое)

Поля посетителя #

GET /sites/{site_id}/fields

Поля, которые сайт собирает о посетителе. По ним заполняются fields в заявках и карточке посетителя.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Что возвращается

name — ключ поля в данных, title — подпись в кабинете.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842/fields' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/fields');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/fields',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/fields', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "id": 100233,
        "name": "email",
        "title": "E-mail",
        "weight": 0
      },
      {
        "id": 100234,
        "name": "name",
        "title": "Имя",
        "weight": 1
      },
      {
        "id": 100412,
        "name": "city",
        "title": "Город",
        "weight": 2
      }
    ]
  }
}

Тариф и расход #

GET /sites/plan

Тариф «Сайты и виджеты» аккаунта: лимиты, расход и срок.

Только чтение: тариф оплачивается в личном кабинете.

Что возвращается

0 в любом *_limit означает «без ограничений». can отвечает на вопрос «можно ли завести ещё» — по нему удобно гасить кнопки, не считая лимиты самому. period — расчётный период лимита просмотров, [from, to).

curl -X GET 'https://api.dashamail.com/v2/sites/plan' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/plan');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/plan',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/plan', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "plan_id": 14,
      "plan_code": "sites-pro",
      "plan_name": "Сайты и виджеты PRO",
      "is_pro": false,
      "unlimited": false,
      "sites_limit": 10,
      "widgets_limit": 50,
      "tests_limit": 10,
      "pageviews_limit": 500000,
      "views_included": false,
      "period_months": 1,
      "ends_at": "2026-11-18 00:00:00",
      "usage": {
        "sites": 4,
        "widgets": 11,
        "tests": 1
      },
      "can": {
        "sites": true,
        "widgets": true,
        "tests": true
      },
      "period": {
        "from": "2026-10-18",
        "to": "2026-11-18"
      }
    }
  }
}

Виджеты сайта #

GET /sites/{site_id}/widgets

Виджеты сайта, новые сверху: формы, поп-апы, полоски.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры строки запроса

ПараметрТипОписание
statusstringТолько включённые или только выключенные.
Допустимые значения: enabled, disabled
kindstringВид виджета.
Допустимые значения: popup, horizontal, vertical, inline, none
searchstringПодстрока в названии.
limitintegerпо умолчанию: 100Сколько виджетов вернуть, не больше 500.
offsetintegerпо умолчанию: 0Смещение от начала выборки.

Что возвращается

kind — как виджет показывается: popup — всплывающее окно, horizontal и vertical — полоски у края экрана, inline — форма внутри страницы. has_draft — есть несохранённые правки: сайт их ещё не видит. test_id — A/B-тест, в котором участвует виджет, 0 — ни в одном.

Вид и настройки виджета правятся только в редакторе кабинета: наружу его модель не отдаётся.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842/widgets?status=enabled' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/widgets?status=enabled');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/widgets?status=enabled',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/widgets?status=enabled', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "id": 100931,
        "site_id": 100842,
        "name": "Скидка 10% за подписку",
        "kind": "popup",
        "status": "enabled",
        "template_id": 42,
        "test_id": 0,
        "has_draft": false,
        "published_at": "2026-10-02 13:20:44",
        "created_at": "2026-09-30 10:11:09",
        "updated_at": "2026-10-02 13:20:44"
      }
    ]
  }
}

Один виджет #

GET /sites/{site_id}/widgets/{widget_id}

Один виджет — в том же наборе полей, что и в списке.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
widget_id обязательныйintegerИдентификатор виджета.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Виджета с таким идентификатором на сайте нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842/widgets/100931' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/widgets/100931');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/widgets/100931',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/widgets/100931', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": 100931,
      "site_id": 100842,
      "name": "Скидка 10% за подписку",
      "kind": "popup",
      "status": "enabled",
      "template_id": 42,
      "test_id": 0,
      "has_draft": false,
      "published_at": "2026-10-02 13:20:44",
      "created_at": "2026-09-30 10:11:09",
      "updated_at": "2026-10-02 13:20:44"
    }
  }
}

Включить виджет #

POST /sites/{site_id}/widgets/{widget_id}/enable

Включает виджет: он начинает показываться на сайте. Слепок сайта пересобирается сразу, ждать крона не нужно.

Лимит тарифа считает именно включённые виджеты — создать можно сколько угодно, держать включёнными ограниченное число.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
widget_id обязательныйintegerИдентификатор виджета.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Виджета с таким идентификатором на сайте нет
409 68 Виджет нечего показывать: он ни разу не публиковался
409 68 На сайте не установлен код: выключенный виджет показывать негде
409 68 Сайт ещё переносится из кабинета Leadplan — правки пока делаются там
409 69 Исчерпан лимит включённых виджетов на тарифе
403 65 Недостаточно прав
curl -X POST 'https://api.dashamail.com/v2/sites/100842/widgets/100931/enable' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/widgets/100931/enable');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.post(
    'https://api.dashamail.com/v2/sites/100842/widgets/100931/enable',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/widgets/100931/enable', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": 100931,
      "status": "enabled"
    }
  }
}

Выключить виджет #

POST /sites/{site_id}/widgets/{widget_id}/disable

Выключает виджет: он перестаёт показываться. Настройки и собранные заявки остаются.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
widget_id обязательныйintegerИдентификатор виджета.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Виджета с таким идентификатором на сайте нет
403 65 Недостаточно прав
curl -X POST 'https://api.dashamail.com/v2/sites/100842/widgets/100931/disable' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/widgets/100931/disable');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.post(
    'https://api.dashamail.com/v2/sites/100842/widgets/100931/disable',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/widgets/100931/disable', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": 100931,
      "status": "disabled"
    }
  }
}

Статистика сайта #

GET /sites/{site_id}/stats

Просмотры страниц, показы виджетов и заявки по дням или месяцам, с итогами, разбивкой по виджетам и источниками заявок.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры строки запроса

ПараметрТипОписание
periodstringпо умолчанию: daysdays — последние 30 дней, months — последние 12 месяцев.
Допустимые значения: days, months
widget_idintegerСчитать показы, заявки и источники только по одному виджету. Просмотры страниц виджетом не фильтруются — они относятся к сайту.

Что возвращается

В series пропущенные дни идут нулями. Если период задевает время, за которое просмотры не собирались, pageviews в этих точках приходит null, а сам промежуток — в pageviews_gap: это «нет данных», а не «ноль посетителей». sources — источники заявок, не больше 15 строк.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
422 67 Недопустимый период
503 70 Хранилище статистики недоступно
curl -X GET 'https://api.dashamail.com/v2/sites/100842/stats?period=days' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/stats?period=days');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/stats?period=days',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/stats?period=days', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "period": "days",
      "from": "2026-09-28",
      "to": "2026-10-27",
      "pageviews_gap": null,
      "series": [
        {
          "date": "2026-10-26",
          "pageviews": 1841,
          "displays": 612,
          "leads": 14
        },
        {
          "date": "2026-10-27",
          "pageviews": 1902,
          "displays": 640,
          "leads": 19
        }
      ],
      "totals": {
        "pageviews": 54218,
        "displays": 18204,
        "leads": 431,
        "conversion": 2.37
      },
      "widgets": [
        {
          "widget_id": 100931,
          "name": "Скидка 10% за подписку",
          "archived": false,
          "displays": 12043,
          "leads": 318,
          "visitors": 9120,
          "conversion": 2.64
        }
      ],
      "sources": [
        {
          "type": "organic",
          "src": "yandex",
          "leads": 164
        },
        {
          "type": "direct",
          "src": "",
          "leads": 98
        }
      ]
    }
  }
}

Статистика по виджетам #

GET /sites/{site_id}/stats/widgets

Таблица виджетов за произвольный отрезок: показы, заявки и дата первого показа.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры строки запроса

ПараметрТипОписание
fromstringНачало отрезка, ГГГГ-ММ-ДД включительно. Не задано — всё время.
tostringКонец отрезка, ГГГГ-ММ-ДД включительно.
searchstringПодстрока в названии виджета.

Что возвращается

В таблицу попадают и архивные виджеты, если за отрезок у них были показы: archived: true. first_display — первый показ за всё время, а не за отрезок: это дата запуска виджета.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
503 70 Хранилище статистики недоступно
curl -X GET 'https://api.dashamail.com/v2/sites/100842/stats/widgets?from=2026-10-01&to=2026-10-27' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/stats/widgets?from=2026-10-01&to=2026-10-27');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/stats/widgets?from=2026-10-01&to=2026-10-27',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/stats/widgets?from=2026-10-01&to=2026-10-27', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "widget_id": 100931,
        "name": "Скидка 10% за подписку",
        "status": "enabled",
        "archived": false,
        "first_display": "2026-09-30",
        "displays": 12043,
        "leads": 318
      }
    ]
  }
}

Воронка сайта #

GET /sites/{site_id}/stats/funnel

Ступени за 30 дней: посетители, опознанные, показы, заявки и заказы — с долями от посетителей.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Что возвращается

Ступень, которую нечем считать, приходит null, а не нулём: посетителей и заказы считает трекер, заявки — виджеты. У сайта без трекера visitors и orders — null.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
503 70 Хранилище статистики недоступно
curl -X GET 'https://api.dashamail.com/v2/sites/100842/stats/funnel' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/stats/funnel');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/stats/funnel',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/stats/funnel', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "days": 30,
      "from": "2026-09-27",
      "visitors": 18420,
      "identified": 2140,
      "displays": 18204,
      "leads": 431,
      "orders": 96,
      "rates": {
        "identified": 11.62,
        "leads": 2.34,
        "orders": 0.52
      }
    }
  }
}

A/B-тесты сайта #

GET /sites/{site_id}/tests

Тесты сайта с их вариантами.

Тесты создаются и останавливаются в кабинете: запись наружу не отдаётся.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Что возвращается

Посетитель попадает в вариант по своему идентификатору — раз и навсегда, а не по счётчику показов. weight — доля варианта в сплите. reset_at — отчёт обнулили с этой даты, сами показы и заявки остались.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842/tests' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/tests');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/tests',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/tests', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "id": 100044,
        "site_id": 100842,
        "name": "Поп-ап: скидка или подарок",
        "status": "active",
        "started_at": "2026-10-10 12:00:00",
        "stopped_at": null,
        "reset_at": null,
        "created_at": "2026-10-10 11:58:21",
        "variants": [
          {
            "widget_id": 100931,
            "name": "Скидка 10%",
            "status": "enabled",
            "weight": 1
          },
          {
            "widget_id": 100932,
            "name": "Подарок к заказу",
            "status": "enabled",
            "weight": 1
          }
        ]
      }
    ]
  }
}

Итоги A/B-тестов #

GET /sites/{site_id}/tests/stats

Сравнение вариантов по всем тестам сайта.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Что возвращается

visitors — уникальные посетители, видевшие вариант, sessions — уникальные сессии показов. Победителя API не называет: решение за человеком. Строки есть и у виджетов, уже убранных из теста, — сравнивайте со списком текущих вариантов.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
503 70 Хранилище статистики недоступно
curl -X GET 'https://api.dashamail.com/v2/sites/100842/tests/stats' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/tests/stats');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/tests/stats',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/tests/stats', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "test_id": 100044,
        "variants": [
          {
            "widget_id": 100931,
            "displays": 6102,
            "leads": 171,
            "visitors": 4610,
            "sessions": 5204,
            "conversion": 2.8
          },
          {
            "widget_id": 100932,
            "displays": 5941,
            "leads": 147,
            "visitors": 4510,
            "sessions": 5102,
            "conversion": 2.47
          }
        ]
      }
    ]
  }
}

Заявки сайта #

GET /sites/{site_id}/leads

Что люди отправили через виджеты сайта, новые сверху.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры строки запроса

ПараметрТипОписание
widget_idintegerТолько заявки одного виджета.
fromstringС этого дня, ГГГГ-ММ-ДД включительно.
tostringДо этого дня, ГГГГ-ММ-ДД включительно.
searchstringПоиск по почте, имени или телефону. По телефону — от трёх цифр.
limitintegerпо умолчанию: 50Сколько заявок вернуть, не больше 500.
offsetintegerпо умолчанию: 0Смещение от начала выборки.
formatstringОтдать выборку таблицей text/csv вместо JSON. Выгружается вся выборка, limit и offset не действуют.
Допустимые значения: csv

Что возвращается

fields — все значения формы в порядке отправки, с подписями полей. Почта, телефон и имя продублированы отдельными полями: по ним идёт поиск.

deliveries — сводка доставок в подключённые сервисы и вебхуки: сколько ушло, сколько не получилось, сколько ждёт очереди. Разбор по попыткам — в карточке заявки.

Телефон хранится цифрами, ведущая 8 заменена на 7. Почта, не прошедшая проверку, в email не попадает, но остаётся в fields как её ввёл человек.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842/leads?from=2026-10-20&limit=50' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/leads?from=2026-10-20&limit=50');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/leads?from=2026-10-20&limit=50',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/leads?from=2026-10-20&limit=50', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "id": 1024417,
        "site_id": 100842,
        "widget_id": 100931,
        "widget_name": "Скидка 10% за подписку",
        "email": "ivan@example.ru",
        "phone": "79160000000",
        "name": "Иван",
        "fields": [
          {
            "name": "email",
            "title": "E-mail",
            "value": "ivan@example.ru"
          },
          {
            "name": "name",
            "title": "Имя",
            "value": "Иван"
          },
          {
            "name": "city",
            "title": "Город",
            "value": "Москва"
          }
        ],
        "utm_source": "yandex",
        "traffic": {
          "type": "organic",
          "src": "yandex"
        },
        "created_at": "2026-10-27 10:12:40",
        "deliveries": {
          "sent": 2,
          "failed": 0,
          "queued": 0
        }
      }
    ]
  }
}

Одна заявка #

GET /sites/{site_id}/leads/{lead_id}

Заявка целиком: все значения формы, откуда человек пришёл, его карточка посетителя и журнал доставок.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
lead_id обязательныйintegerИдентификатор заявки.

Что возвращается

Заявка собирается ровно так же, как уходит в подключённые сервисы: что видно здесь, то и было отправлено.

delivery_log — строка на попытку: attempt — её номер, http_status и response — чем ответил сервис (первый килобайт), next_try_at — когда будет следующая попытка.

timezone_offset — часовой пояс браузера в минутах, как его прислал сам браузер.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Заявки с таким идентификатором на сайте нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842/leads/1024417' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/leads/1024417');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/leads/1024417',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/leads/1024417', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": 1024417,
      "site_id": 100842,
      "widget_id": 100931,
      "widget_name": "Скидка 10% за подписку",
      "test_id": 100044,
      "email": "ivan@example.ru",
      "phone": "79160000000",
      "name": "Иван",
      "fields": [
        {
          "name": "email",
          "title": "E-mail",
          "value": "ivan@example.ru"
        }
      ],
      "url": "https://example.ru/catalog/",
      "referrer": "https://yandex.ru/search/",
      "utm": {
        "source": "yandex",
        "medium": "organic",
        "campaign": "",
        "term": "",
        "content": ""
      },
      "traffic": {
        "type": "organic",
        "src": "yandex"
      },
      "timezone_offset": 180,
      "created_at": "2026-10-27 10:12:40",
      "visitor": {
        "id": "0f3a6c18-4b2d-4f1a-9e77-2c5b8d410e62",
        "country": "Россия",
        "region": "Москва",
        "city": "Москва",
        "browser": "Chrome",
        "os": "Windows",
        "device": "desktop"
      },
      "delivery_log": [
        {
          "id": 88104221,
          "binding_id": 100277,
          "attempt": 1,
          "status": "sent",
          "http_status": 200,
          "response": "{\"ok\":true}",
          "next_try_at": null,
          "created_at": "2026-10-27 10:12:41",
          "updated_at": "2026-10-27 10:12:41"
        }
      ]
    }
  }
}

Повторить доставку заявки #

POST /sites/{site_id}/leads/{lead_id}/retry

Ставит заявку в очередь на повторную доставку: неудачные попытки и сервисы, подключённые уже после заявки.

Доставленное и уже стоящее в очереди не трогается, дублей не будет. Сам запрос ничего не отправляет — он только возвращает заявку в очередь, отправкой займётся та же доставка, что и у обычных заявок, с теми же повторами.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
lead_id обязательныйintegerИдентификатор заявки.

Что возвращается

queued — сколько доставок поставлено в очередь. 0 — повторять нечего: всё либо уже доставлено, либо ждёт своей очереди.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Заявки с таким идентификатором на сайте нет
403 65 Недостаточно прав
curl -X POST 'https://api.dashamail.com/v2/sites/100842/leads/1024417/retry' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/leads/1024417/retry');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.post(
    'https://api.dashamail.com/v2/sites/100842/leads/1024417/retry',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/leads/1024417/retry', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "queued": 1,
      "delivery_log": [
        {
          "id": 88104998,
          "binding_id": 100277,
          "attempt": 1,
          "status": "queued",
          "http_status": null,
          "next_try_at": "2026-10-27 12:40:00"
        }
      ]
    }
  }
}

Посетители сайта #

GET /sites/{site_id}/visitors

Люди, которые оставляли заявки на сайте, с их полями и числом обращений.

В список попадают только посетители, о которых что-то известно: тот, кто просто ходил по сайту и ничего не отправлял, строки не заводит.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры строки запроса

ПараметрТипОписание
searchstringПодстрока в любом значении полей посетителя.
orderstringпо умолчанию: last_activityСортировка: по времени последней заявки, по имени, по числу заявок или по последнему виджету. Можно сортировать по значению поля — field:city.
Допустимые значения: last_activity, name, activities, last_tool
ascфлагСортировать по возрастанию. По умолчанию — по убыванию.
limitintegerпо умолчанию: 25Сколько посетителей вернуть.
offsetintegerпо умолчанию: 0Смещение от начала выборки.
formatstringОтдать выборку таблицей text/csv вместо JSON.
Допустимые значения: csv

Что возвращается

id посетителя — строка, а не число: это идентификатор из куки его браузера.

activities — сколько заявок он оставил, last_tool — название виджета, через который обратился в последний раз. params — все значения его полей объектом.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842/visitors?order=activities&limit=25' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/visitors?order=activities&limit=25');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/visitors?order=activities&limit=25',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/visitors?order=activities&limit=25', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "id": "0f3a6c18-4b2d-4f1a-9e77-2c5b8d410e62",
        "name": "Иван Петров",
        "email": "ivan@example.ru",
        "phone": "79160000000",
        "params": {
          "email": "ivan@example.ru",
          "name": "Иван",
          "surname": "Петров",
          "city": "Москва"
        },
        "last_activity": "2026-10-27 10:12:40",
        "activities": 3,
        "last_tool": "Скидка 10% за подписку"
      }
    ]
  }
}

Карточка посетителя #

GET /sites/{site_id}/visitors/{visitor_id}

Посетитель со всеми полями сайта, устройством и источником первого визита.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
visitor_id обязательныйstringИдентификатор посетителя.

Что возвращается

fields перечисляет все поля сайта, в том числе незаполненные: у них value пустая. created_at — первый визит, submitted_at — последняя заявка.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Посетителя с таким идентификатором на сайте нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842/visitors/0f3a6c18-4b2d-4f1a-9e77-2c5b8d410e62' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/visitors/0f3a6c18-4b2d-4f1a-9e77-2c5b8d410e62');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/visitors/0f3a6c18-4b2d-4f1a-9e77-2c5b8d410e62',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/visitors/0f3a6c18-4b2d-4f1a-9e77-2c5b8d410e62', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": "0f3a6c18-4b2d-4f1a-9e77-2c5b8d410e62",
      "name": "Иван",
      "surname": "Петров",
      "email": "ivan@example.ru",
      "fields": [
        {
          "name": "email",
          "title": "E-mail",
          "value": "ivan@example.ru"
        },
        {
          "name": "city",
          "title": "Город",
          "value": "Москва"
        }
      ],
      "created_at": "2026-09-14 18:22:10",
      "last_activity": "2026-10-27 10:12:40",
      "submitted_at": "2026-10-27 10:12:40",
      "ip": "81.200.0.0",
      "country": "Россия",
      "region": "Москва",
      "city": "Москва",
      "browser": "Chrome",
      "os": "Windows",
      "device": "desktop",
      "referrer": "https://yandex.ru/search/",
      "utm_source": "yandex",
      "utm_medium": "organic",
      "utm_campaign": "",
      "utm_term": "",
      "utm_content": ""
    }
  }
}

Заявки посетителя #

GET /sites/{site_id}/visitors/{visitor_id}/leads

История обращений одного человека, новые сверху.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
visitor_id обязательныйstringИдентификатор посетителя.

Параметры строки запроса

ПараметрТипОписание
limitintegerпо умолчанию: 25Сколько заявок вернуть.
offsetintegerпо умолчанию: 0Смещение от начала выборки.

Что возвращается

В fields у значений только подпись поля и само значение: историю посетителя показывают таблицей, и системные имена полей в ней не нужны. Адрес страницы — отдельным полем url.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Посетителя с таким идентификатором на сайте нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842/visitors/0f3a6c18-4b2d-4f1a-9e77-2c5b8d410e62/leads' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/visitors/0f3a6c18-4b2d-4f1a-9e77-2c5b8d410e62/leads');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/visitors/0f3a6c18-4b2d-4f1a-9e77-2c5b8d410e62/leads',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/visitors/0f3a6c18-4b2d-4f1a-9e77-2c5b8d410e62/leads', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "id": 1024417,
        "widget_id": 100931,
        "widget_name": "Скидка 10% за подписку",
        "created_at": "2026-10-27 10:12:40",
        "url": "https://example.ru/catalog/",
        "fields": [
          {
            "title": "E-mail",
            "value": "ivan@example.ru"
          },
          {
            "title": "Имя",
            "value": "Иван"
          }
        ]
      }
    ]
  }
}

Вебхуки на заявку #

GET /sites/{site_id}/webhooks

Куда уходят заявки виджетов сайта: адрес, виджет и состояние.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Что возвращается

Вебхук ставится на виджет, а не на сайт: у разных виджетов могут быть разные адреса. Кроме вебхуков у сайта бывают подключённые сервисы рассылок — они настраиваются в кабинете и здесь не показываются.

status — состояние приёмника: active — работает, error — последние доставки не прошли, disabled — выключен в кабинете.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
curl -X GET 'https://api.dashamail.com/v2/sites/100842/webhooks' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/webhooks');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/webhooks',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/webhooks', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "id": 100277,
        "widget_id": 100931,
        "widget_name": "Скидка 10% за подписку",
        "url": "https://example.ru/hooks/dashamail",
        "status": "active",
        "updated_at": "2026-10-02 13:21:00"
      }
    ]
  }
}

Поставить вебхук на заявку #

POST /sites/{site_id}/webhooks

Заявки виджета начинают уходить POST-запросом на ваш адрес.

Вебхук ставится на один виджет. Повторный вызов на тот же виджет второй привязки не создаёт — меняет у неё адрес, поэтому метод можно звать повторно без опаски. Нужны все виджеты сайта — пройдите их список и позовите метод на каждый: виджеты, которые появятся позже, вебхука сами не получат.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры тела запроса

ПараметрТипОписание
url обязательныйstringАдрес приёмника. Должен начинаться с http:// или https:// и быть не длиннее 500 символов.
widget_id обязательныйintegerВиджет, чьи заявки отправлять.

Что возвращается

Неудачные доставки повторяются с растущей задержкой; сколько попыток было и чем они кончились, видно в карточке заявки.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта или виджета с таким идентификатором нет
422 3 Не передан url или widget_id
422 67 Адрес не начинается с http:// либо https://
403 65 Недостаточно прав
curl -X POST 'https://api.dashamail.com/v2/sites/100842/webhooks' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "url": "https://example.ru/hooks/dashamail",
  "widget_id": 100931
}'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/webhooks');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode([
            'url' => 'https://example.ru/hooks/dashamail',
            'widget_id' => 100931,
        ], JSON_UNESCAPED_UNICODE),
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.post(
    'https://api.dashamail.com/v2/sites/100842/webhooks',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={
        'url': 'https://example.ru/hooks/dashamail',
        'widget_id': 100931,
    },
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/webhooks', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "url": "https://example.ru/hooks/dashamail",
  "widget_id": 100931
}),
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": 100277,
      "widget_id": 100931,
      "url": "https://example.ru/hooks/dashamail",
      "status": "active"
    }
  }
}

Снять вебхук #

DELETE /sites/{site_id}/webhooks/{webhook_id}

Заявки перестают уходить на этот адрес. Уже собранные заявки остаются.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
webhook_id обязательныйintegerИдентификатор вебхука из списка.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Вебхука с таким идентификатором на сайте нет
403 65 Недостаточно прав
curl -X DELETE 'https://api.dashamail.com/v2/sites/100842/webhooks/100277' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/webhooks/100277');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.delete(
    'https://api.dashamail.com/v2/sites/100842/webhooks/100277',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/webhooks/100277', {
  method: 'DELETE',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 204
(тело ответа пустое)

Товарные каталоги #

GET /sites/{site_id}/feeds

Каталоги сайта: ссылка на YML-фид, его настройки и что из него загрузилось.

Каталог нужен письмам о товарах — брошенной корзине, просмотренным товарам, снижению цены: из него берутся название, цена и картинка товара, который смотрел посетитель.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры строки запроса

ПараметрТипОписание
orderstringпо умолчанию: descПорядок: по времени правки или по названию магазина.
Допустимые значения: desc, asc, name_asc, name_desc

Что возвращается

last_update — когда фид читался последний раз, next_load — когда прочитается снова. Товары в ответ не попадают: их список отдаёт ассортимент.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
403 65 У субаккаунта нет права на модули сайта
curl -X GET 'https://api.dashamail.com/v2/sites/100842/feeds' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/feeds');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/feeds',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/feeds', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "id": 612,
        "site_id": 100842,
        "shop_name": "Магазин «Ромашка»",
        "yml_file_url": "https://example.ru/feed.yml",
        "originDomain": "example.ru",
        "currency_code": "rub",
        "total_products": 4182,
        "categories_num": 36,
        "yml_load_period": 24,
        "last_update": "2026-10-27 04:12:08",
        "next_load": "2026-10-28 04:12:08",
        "lastedit_time": "2026-10-20 16:40:11"
      }
    ]
  }
}

Один каталог #

GET /sites/{site_id}/feeds/{feed_id}

Каталог со всеми настройками и доменами, из которых можно выбрать его originDomain.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
feed_id обязательныйintegerИдентификатор каталога.

Что возвращается

sales_rate_period — за сколько дней считается рейтинг продаж, abandoned_period — через сколько часов корзина считается брошенной (0 — не считать).

Возможные ошибки

HTTPcodeКогда возникает
404 4 Каталога с таким идентификатором на сайте нет
403 65 У субаккаунта нет права на модули сайта
curl -X GET 'https://api.dashamail.com/v2/sites/100842/feeds/612' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/feeds/612');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/feeds/612',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/feeds/612', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": 612,
      "shop_name": "Магазин «Ромашка»",
      "yml_file_url": "https://example.ru/feed.yml",
      "shop_url": "https://example.ru",
      "originDomain": "example.ru",
      "shop_category_id": 1,
      "currency_code": "rub",
      "price_number_format": 0,
      "sales_rate_period": 30,
      "abandoned_period": 24,
      "yml_load_period": 24,
      "total_products": 4182,
      "categories_num": 36,
      "last_update": "2026-10-27 04:12:08",
      "next_load": "2026-10-28 04:12:08",
      "domains": [
        "example.ru",
        "m.example.ru"
      ]
    }
  }
}

Ассортимент каталога #

GET /sites/{site_id}/feeds/{feed_id}/items

Категории каталога со счётчиками и начало списка товаров — проверить, что фид читается правильно.

Товары не хранятся у нас: они читаются с самого фида при каждом запросе, с начала файла. Поэтому страница ограничена 200 товарами, а offset тут не поддерживается — выгружать весь ассортимент этим методом не нужно, он у вас уже есть.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
feed_id обязательныйintegerИдентификатор каталога.

Параметры строки запроса

ПараметрТипОписание
limitintegerпо умолчанию: 50Сколько товаров вернуть: от 10 до 200.

Что возвращается

pending: true — фид ещё ни разу не загружался: категорий нет, и это не ошибка. columns — какие поля нашлись у товаров этого фида, products у категории — с учётом вложенных.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Каталога с таким идентификатором на сайте нет
403 65 У субаккаунта нет права на модули сайта
503 70 Фид не читается: адрес не отвечает или отдаёт не YML
curl -X GET 'https://api.dashamail.com/v2/sites/100842/feeds/612/items' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/feeds/612/items');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/feeds/612/items',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/feeds/612/items', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "pending": false,
      "last_update": "2026-10-27 04:12:08",
      "total_products": 4182,
      "categories_num": 36,
      "categories": [
        {
          "id": 14,
          "name": "Посуда",
          "level": 0,
          "products": 1204
        },
        {
          "id": 18,
          "name": "Кастрюли",
          "level": 1,
          "products": 316
        }
      ],
      "columns": [
        "id",
        "name",
        "price",
        "oldprice",
        "url",
        "picture",
        "available"
      ],
      "limit": 50,
      "offers": [
        {
          "id": "4412",
          "name": "Кастрюля 3 л",
          "price": "2490",
          "url": "https://example.ru/catalog/4412",
          "available": "true"
        }
      ]
    }
  }
}

Подключить каталог #

POST /sites/{site_id}/feeds

Подключает YML-фид к сайту.

Фид читается сразу, в этом же запросе: у большого каталога ответ придёт не мгновенно. Ставьте таймаут с запасом — минуту и больше.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры тела запроса

ПараметрТипОписание
url обязательныйstringАдрес YML-фида, например https://example.ru/feed.yml.

Что возвращается

Название магазина, валюта и домен берутся из самого фида; остальные настройки получают значения по умолчанию и правятся отдельно.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
422 67 Адрес не задан или по нему не YML-фид
409 68 Этот фид уже подключён к сайту
403 65 Недостаточно прав; каталоги недоступны на текущем тарифе — о причине говорит текст
curl -X POST 'https://api.dashamail.com/v2/sites/100842/feeds' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "url": "https://example.ru/feed.yml"
}'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/feeds');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'POST',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode([
            'url' => 'https://example.ru/feed.yml',
        ], JSON_UNESCAPED_UNICODE),
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.post(
    'https://api.dashamail.com/v2/sites/100842/feeds',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={
        'url': 'https://example.ru/feed.yml',
    },
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/feeds', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "url": "https://example.ru/feed.yml"
}),
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 201
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": 612,
      "shop_name": "Магазин «Ромашка»",
      "yml_file_url": "https://example.ru/feed.yml",
      "originDomain": "example.ru",
      "currency_code": "rub",
      "total_products": 4182
    }
  }
}

Изменить каталог #

PUT /sites/{site_id}/feeds/{feed_id}

Меняет настройки каталога. Передавайте только то, что нужно изменить.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
feed_id обязательныйintegerИдентификатор каталога.

Параметры тела запроса

ПараметрТипОписание
originDomainstringДомен, к которому относится каталог. Выбирается из доменов сайта.
shop_category_idintegerОтрасль магазина.
currency_codestringВалюта цен.
Допустимые значения: rub, uah, usd, eur, kzt, byr
price_number_formatintegerФормат цены в письме: 0 — как в фиде, 1 — с разделителем разрядов.
Допустимые значения: 0, 1
sales_rate_periodintegerЗа сколько дней считать рейтинг продаж.
Допустимые значения: 1, 3, 7, 14, 30, 60, 90
abandoned_periodintegerЧерез сколько часов корзина считается брошенной; 0 — не считать.
Допустимые значения: 0, 12, 24, 72, 168, 336, 720, 1440, 2160
yml_load_periodintegerКак часто перечитывать фид, в часах.
Допустимые значения: 12, 24, 72

Возможные ошибки

HTTPcodeКогда возникает
404 4 Каталога с таким идентификатором на сайте нет
422 67 Недопустимое значение поля
403 65 Недостаточно прав
curl -X PUT 'https://api.dashamail.com/v2/sites/100842/feeds/612' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "abandoned_period": 24,
  "yml_load_period": 12
}'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/feeds/612');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode([
            'abandoned_period' => 24,
            'yml_load_period' => 12,
        ], JSON_UNESCAPED_UNICODE),
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.put(
    'https://api.dashamail.com/v2/sites/100842/feeds/612',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={
        'abandoned_period': 24,
        'yml_load_period': 12,
    },
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/feeds/612', {
  method: 'PUT',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "abandoned_period": 24,
  "yml_load_period": 12
}),
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "id": 612,
      "abandoned_period": 24,
      "yml_load_period": 12
    }
  }
}

Отключить каталог #

DELETE /sites/{site_id}/feeds/{feed_id}

Отключает каталог от сайта. Письма о товарах по нему перестают собираться.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.
feed_id обязательныйintegerИдентификатор каталога.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Каталога с таким идентификатором на сайте нет
403 65 Недостаточно прав
curl -X DELETE 'https://api.dashamail.com/v2/sites/100842/feeds/612' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/feeds/612');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.delete(
    'https://api.dashamail.com/v2/sites/100842/feeds/612',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/feeds/612', {
  method: 'DELETE',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 204
(тело ответа пустое)

События сайта #

GET /sites/{site_id}/events

Какие события сайт передаёт в DashaMail и в какую адресную базу они складываются.

Только чтение: соответствие полей события настраивается в кабинете. Неверное соответствие тихо ломает сбор данных, и менять его вслепую через API опаснее, чем руками.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Что возвращается

События сгруппированы по точкам интеграции: у сайта с несколькими доменами их может быть больше одной. builtin: true — встроенное событие (просмотр, корзина, заказ), false — своё. last_event — когда событие приходило последний раз; пусто — не приходило ни разу, и это первое, что стоит проверить при отладке.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
403 65 У субаккаунта нет права на модули сайта
curl -X GET 'https://api.dashamail.com/v2/sites/100842/events' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/events');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/events',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/events', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "point": {
          "id": 54218,
          "endpointId": "a1b2c3d4e5f6",
          "name": "example.ru",
          "list_id": 128341,
          "domains": [
            "example.ru",
            "m.example.ru"
          ]
        },
        "events": [
          {
            "id": 0,
            "event": "Просмотр товара",
            "rel": "viewed",
            "builtin": true,
            "list_id": 128341,
            "list_name": "Клиенты интернет-магазина",
            "last_event": "2026-10-27 11:48:31"
          },
          {
            "id": 9214,
            "event": "Подписка в подвале",
            "rel": "subscribe",
            "builtin": false,
            "list_id": 128341,
            "list_name": "Клиенты интернет-магазина",
            "originDomain": "",
            "last_event": "2026-10-26 20:04:12"
          }
        ]
      }
    ]
  }
}

Журнал событий #

GET /sites/{site_id}/events/log

Последние события сайта как они пришли — чтобы убедиться, что код на сайте передаёт то, что нужно.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры строки запроса

ПараметрТипОписание
limitintegerпо умолчанию: 100Сколько событий вернуть: от 10 до 200.
daysintegerпо умолчанию: 7За сколько последних дней смотреть.
Допустимые значения: 7, 30
operationstringТолько события одного вида.
endpointIdstringТолько события одной точки интеграции.

Что возвращается

Если за выбранные дни событий не было, журнал ищет глубже и показывает последнее, что есть: window говорит, за какой срок ответ на самом деле собран.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
403 65 У субаккаунта нет права на модули сайта
503 70 Хранилище событий недоступно
curl -X GET 'https://api.dashamail.com/v2/sites/100842/events/log?limit=100&days=7' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/events/log?limit=100&days=7');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/events/log?limit=100&days=7',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/events/log?limit=100&days=7', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": {
      "limit": 100,
      "days": 7,
      "window": 7,
      "events": [
        {
          "time": "2026-10-27 11:48:31",
          "operation": "viewed",
          "originDomain": "example.ru",
          "email": "ivan@example.ru",
          "data": {
            "id": "4412",
            "price": "2490"
          }
        }
      ]
    }
  }
}

Веб-пуш сайта #

GET /sites/{site_id}/push

Подписки на веб-пуш по доменам сайта: сколько их и сколько живых.

Только чтение: подключение веб-пуша и тексты запроса подписки настраиваются в кабинете.

Параметры пути

ПараметрТипОписание
site_id обязательныйintegerИдентификатор сайта.

Параметры строки запроса

ПараметрТипОписание
periodstringпо умолчанию: weekПериод графика подписок и отписок.
Допустимые значения: week, month, year

Что возвращается

Строка на каждый домен сайта: подписка заводится на домен, поэтому у сайта с двумя доменами и приложений два. push: null — на этом домене веб-пуш не подключён.

devices — все подписки, active — неотозванные, engaged — заходившие за последние 30 дней. Отозванная подписка — это браузер, который отписался или больше не существует.

Возможные ошибки

HTTPcodeКогда возникает
404 4 Сайта с таким идентификатором у аккаунта нет
403 65 У субаккаунта нет права на модули сайта
curl -X GET 'https://api.dashamail.com/v2/sites/100842/push' \
  -H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/sites/100842/push');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'GET',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer YOUR_API_KEY',
    ],
]);

$response = json_decode(curl_exec($ch), true);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException($response['error']['message']);
}
print_r($response['response']['data']);
import requests

response = requests.get(
    'https://api.dashamail.com/v2/sites/100842/push',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
)

response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/sites/100842/push', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  },
});

const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
Ответ HTTP 200
{
  "response": {
    "msg": {
      "err_code": 0,
      "text": "OK",
      "type": "message"
    },
    "data": [
      {
        "domain": "example.ru",
        "push": {
          "id": 1182,
          "sdk_version": 2,
          "autoprompt": true
        },
        "devices": 24180,
        "active": 19420,
        "engaged": 8104,
        "audience": {
          "period": "week",
          "title": "7 дней",
          "subscribed": 412,
          "unsubscribed": 96,
          "growth": 316,
          "browsers": {
            "Chrome": 14204,
            "Safari": 3180,
            "Firefox": 1204,
            "Edge": 832
          }
        }
      },
      {
        "domain": "m.example.ru",
        "push": null,
        "devices": 0,
        "active": 0,
        "engaged": 0
      }
    ]
  }
}

DashaMail хранит и защищает ваши данные на территории Российской Федерации

Подробнее...