Диалоги
Ответы подписчиков на рассылки: переписка тредами, ответ от имени отправителя рассылки, вложения.
Когда подписчик отвечает на письмо, ответ попадает не в почтовый ящик отправителя, а в диалог — тред, привязанный к рассылке и к подписчику. Дальше в нём можно переписываться: ответ уходит подписчику письмом от того же отправителя, которым была отправлена рассылка.
Что такое диалог
Диалог заводится сам на первый входящий ответ. У него есть ящик и статус, и в фильтре списка они сведены в один параметр:
open | Обычный входящий, работа не закончена. Так отдаётся по умолчанию |
closed | Обычный входящий, помеченный как закрытый |
all | Обычные входящие целиком, открытые и закрытые |
autoreply | Автоответы вроде «в отпуске» — отдельный ящик, статуса у него нет |
spam | Отфильтрованное как спам — тоже отдельный ящик |
Права субаккаунта
Основной аккаунт видит все диалоги. Субаккаунт — только свои, по тем же
правилам, что и рассылки с базами. Доступ к разделу задаётся отдельно:
без него запросы отвечают кодом 2, с доступом только на
чтение отказываются ответ, закрытие и открытие.
- GET Список диалогов
- GET Один диалог
- GET Переписка диалога
- POST Ответить подписчику
- POST Пометить прочитанным
- POST Пометить непрочитанным
- POST Закрыть диалог
- POST Открыть диалог
- GET Сколько непрочитанного
- GET Ссылка на вложение
Список диалогов #
GET
/dialogs
Треды от новых к старым: по времени последнего сообщения. В каждом — начало последнего сообщения, число непрочитанных и признак вложений, чтобы список можно было показать не запрашивая переписку.
Параметры строки запроса
| Параметр | Тип | Описание |
|---|---|---|
status | stringпо умолчанию: open | Ящик и статус диалога. Допустимые значения: open, closed, all, autoreply, spam |
unread_only | флаг | Только треды с непрочитанными сообщениями. |
campaign_id | integer | Только ответы на эту рассылку. |
list_id | integer | Только ответы подписчиков этой базы. |
q | string | Поиск по теме письма, адресу подписчика и названию рассылки. Не длиннее 100 символов. |
limit | integerпо умолчанию: 50 | Размер страницы, не больше 200. |
offset | integerпо умолчанию: 0 | Смещение. |
Возможные ошибки
| HTTP | code | Когда возникает |
|---|---|---|
403 |
65 |
У субаккаунта нет доступа к разделу |
curl -X GET 'https://api.dashamail.com/v2/dialogs?status=open&unread_only=1&limit=2' \
-H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/dialogs?status=open&unread_only=1&limit=2');
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/dialogs?status=open&unread_only=1&limit=2',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/dialogs?status=open&unread_only=1&limit=2', {
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);
{
"response": {
"msg": {
"err_code": 0,
"text": "OK",
"type": "message"
},
"data": [
{
"id": 8123,
"campaign_id": 501233,
"list_id": 128341,
"member_id": 90421,
"subscriber_email": "client@example.com",
"subject": "Re: Скидки до 40%",
"status": "open",
"unread_count": 1,
"last_message_at": "2026-04-05 12:41:08",
"last_inbound_at": "2026-04-05 12:41:08",
"created_at": "2026-04-05 12:41:08",
"campaign_name": "Весенняя распродажа",
"last_message_preview": "А до какого числа действует скидка?",
"has_attachments": false
}
]
}
}
Один диалог #
GET
/dialogs/{dialog_id}
Тред с контекстом: рассылка, на которую пришёл ответ, и карточка подписчика со всеми дополнительными полями базы. Сама переписка — отдельным запросом.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
dialog_id обязательный | integer | Идентификатор диалога. |
Возможные ошибки
| HTTP | code | Когда возникает |
|---|---|---|
404 |
9 |
Диалога с таким идентификатором нет либо он не ваш |
curl -X GET 'https://api.dashamail.com/v2/dialogs/8123' \
-H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/dialogs/8123');
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/dialogs/8123',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/dialogs/8123', {
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);
{
"response": {
"msg": {
"err_code": 0,
"text": "OK",
"type": "message"
},
"data": {
"id": 8123,
"campaign_id": 501233,
"subscriber_email": "client@example.com",
"subject": "Re: Скидки до 40%",
"status": "open",
"unread_count": 1,
"campaign": {
"id": 501233,
"name": "Весенняя распродажа",
"subject": "Скидки до 40%",
"from_name": "Ромашка",
"from_email": "news@example.ru",
"delivery_time": "2026-04-05 10:00:00",
"status": "SENT",
"report_url": "https://lk.dashamail.ru/?page=campaigns&id=501233"
},
"member": {
"id": 90421,
"email": "client@example.com",
"state": "active",
"merge_1": "Иван"
}
}
}
}
Переписка диалога #
GET
/dialogs/{dialog_id}/messages
Сообщения треда по возрастанию времени, вперемешку с
системными событиями вроде закрытия и открытия: у первых
kind: message, у вторых — event.
У сообщения есть и исходное тело, и очищенное:
body_text_clean и body_html_clean — без
цитат и подписей, их и стоит показывать человеку. Длинные письма
и большие вложения обрезаются, на это указывают
body_truncated и
attachments_truncated.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
dialog_id обязательный | integer | Идентификатор диалога. |
Параметры строки запроса
| Параметр | Тип | Описание |
|---|---|---|
limit | integerпо умолчанию: 100 | Сколько сообщений вернуть, не больше 500. |
offset | integerпо умолчанию: 0 | Смещение. |
Что возвращается
direction — in от подписчика,
out ваш ответ. Вложения перечислены в
attachments, ссылку на файл даёт
отдельный запрос.
Возможные ошибки
| HTTP | code | Когда возникает |
|---|---|---|
404 |
9 |
Диалога с таким идентификатором нет либо он не ваш |
curl -X GET 'https://api.dashamail.com/v2/dialogs/8123/messages' \
-H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/dialogs/8123/messages');
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/dialogs/8123/messages',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/dialogs/8123/messages', {
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);
{
"response": {
"msg": {
"err_code": 0,
"text": "OK",
"type": "message"
},
"data": [
{
"id": 41201,
"dialog_id": 8123,
"kind": "message",
"direction": "in",
"from_email": "client@example.com",
"subject": "Re: Скидки до 40%",
"body_text_clean": "А до какого числа действует скидка?",
"is_read": false,
"is_autoreply": false,
"is_spam": false,
"attachments": [],
"created_at": "2026-04-05 12:41:08"
}
]
}
}
Ответить подписчику #
POST
/dialogs/{dialog_id}/reply
Отправляет ответ подписчику письмом — от того же отправителя, которым была отправлена рассылка. Письмо уходит сразу и не отзывается.
Ответ не уйдёт подписчику, который отписался, пожаловался на
спам или числится возвратом: такой запрос получит код
31 с его текущим состоянием.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
dialog_id обязательный | integer | Идентификатор диалога. |
Параметры тела запроса
| Параметр | Тип | Описание |
|---|---|---|
body_text обязательный | string | Текст ответа. |
body_html | string | HTML-версия ответа. Без неё письмо уйдёт текстом. |
quote_original | stringпо умолчанию: 1 | Цитировать исходное письмо под ответом. 0 — не цитировать. |
Что возвращается
Идентификатор созданного сообщения в треде.
Возможные ошибки
| HTTP | code | Когда возникает |
|---|---|---|
403 |
65 |
У субаккаунта доступ к разделу только на чтение |
500 |
66 |
Письмо не удалось поставить в очередь отправки; сам ответ при этом сохранён в треде |
404 |
9 |
Диалога нет; подписчик удалён |
404 |
5 |
Пустое тело ответа |
422 |
31 |
Подписчик отписался, пожаловался или числится возвратом |
curl -X POST 'https://api.dashamail.com/v2/dialogs/8123/reply' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"body_text": "Скидка действует до 30 апреля включительно."
}'
<?php
$ch = curl_init('https://api.dashamail.com/v2/dialogs/8123/reply');
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([
'body_text' => 'Скидка действует до 30 апреля включительно.',
], 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/dialogs/8123/reply',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
json={
'body_text': 'Скидка действует до 30 апреля включительно.',
},
)
response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/dialogs/8123/reply', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"body_text": "Скидка действует до 30 апреля включительно."
}),
});
const payload = await response.json();
if (!response.ok) throw new Error(payload.error.message);
console.log(payload.response.data);
{
"response": {
"msg": {
"err_code": 0,
"text": "OK",
"type": "message"
},
"data": {
"message_id": 41202,
"dialog_id": 8123
}
}
}
Пометить прочитанным #
POST
/dialogs/{dialog_id}/read
Помечает прочитанным весь тред, а с message_id —
одно сообщение.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
dialog_id обязательный | integer | Идентификатор диалога. |
Параметры тела запроса
| Параметр | Тип | Описание |
|---|---|---|
message_id | integer | Пометить только это сообщение. |
Возможные ошибки
| HTTP | code | Когда возникает |
|---|---|---|
404 |
9 |
Диалога с таким идентификатором нет либо он не ваш |
curl -X POST 'https://api.dashamail.com/v2/dialogs/8123/read' \
-H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/dialogs/8123/read');
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/dialogs/8123/read',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/dialogs/8123/read', {
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);
{
"response": {
"msg": {
"err_code": 0,
"text": "OK",
"type": "message"
},
"data": {
"ok": 1
}
}
}
Пометить непрочитанным #
POST
/dialogs/{dialog_id}/unread
Возвращает треду признак непрочитанного — чтобы он снова попал в список дел.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
dialog_id обязательный | integer | Идентификатор диалога. |
Возможные ошибки
| HTTP | code | Когда возникает |
|---|---|---|
404 |
9 |
Диалога с таким идентификатором нет либо он не ваш |
curl -X POST 'https://api.dashamail.com/v2/dialogs/8123/unread' \
-H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/dialogs/8123/unread');
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/dialogs/8123/unread',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/dialogs/8123/unread', {
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);
{
"response": {
"msg": {
"err_code": 0,
"text": "OK",
"type": "message"
},
"data": {
"ok": 1,
"unread_count": 1
}
}
}
Закрыть диалог #
POST
/dialogs/{dialog_id}/close
Помечает тред закрытым: работа по нему закончена. Переписка сохраняется, новый ответ подписчика откроет тред снова.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
dialog_id обязательный | integer | Идентификатор диалога. |
Возможные ошибки
| HTTP | code | Когда возникает |
|---|---|---|
403 |
65 |
Доступ к разделу только на чтение |
404 |
9 |
Диалога с таким идентификатором нет либо он не ваш |
curl -X POST 'https://api.dashamail.com/v2/dialogs/8123/close' \
-H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/dialogs/8123/close');
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/dialogs/8123/close',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/dialogs/8123/close', {
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);
{
"response": {
"msg": {
"err_code": 0,
"text": "OK",
"type": "message"
},
"data": {
"ok": 1
}
}
}
Открыть диалог #
POST
/dialogs/{dialog_id}/open
Возвращает закрытый тред в работу.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
dialog_id обязательный | integer | Идентификатор диалога. |
Возможные ошибки
| HTTP | code | Когда возникает |
|---|---|---|
403 |
65 |
Доступ к разделу только на чтение |
404 |
9 |
Диалога с таким идентификатором нет либо он не ваш |
curl -X POST 'https://api.dashamail.com/v2/dialogs/8123/open' \
-H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/dialogs/8123/open');
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/dialogs/8123/open',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/dialogs/8123/open', {
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);
{
"response": {
"msg": {
"err_code": 0,
"text": "OK",
"type": "message"
},
"data": {
"ok": 1
}
}
}
Сколько непрочитанного #
GET
/dialogs/unread-count
Счётчики непрочитанного одним запросом. total —
только обычный входящий: автоответы и спам общий счётчик не
раздувают, их числа лежат отдельно в by_box.
Возможные ошибки
| HTTP | code | Когда возникает |
|---|---|---|
403 |
65 |
У субаккаунта нет доступа к разделу |
curl -X GET 'https://api.dashamail.com/v2/dialogs/unread-count' \
-H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/dialogs/unread-count');
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/dialogs/unread-count',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/dialogs/unread-count', {
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);
{
"response": {
"msg": {
"err_code": 0,
"text": "OK",
"type": "message"
},
"data": {
"total": 4,
"by_status": {
"open": 3,
"closed": 1
},
"by_box": {
"normal": 4,
"autoreply": 12,
"spam": 0
}
}
}
}
Ссылка на вложение #
GET
/dialogs/attachments/{attachment_id}
Временная ссылка на файл из переписки. Живёт 15 минут, после чего запросите её заново — постоянной ссылки у вложения нет.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
attachment_id обязательный | integer | Идентификатор вложения из attachments сообщения. |
Возможные ошибки
| HTTP | code | Когда возникает |
|---|---|---|
404 |
9 |
Вложения с таким идентификатором нет либо оно не ваше |
curl -X GET 'https://api.dashamail.com/v2/dialogs/attachments/3391' \
-H 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.dashamail.com/v2/dialogs/attachments/3391');
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/dialogs/attachments/3391',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
response.raise_for_status()
print(response.json()['response']['data'])
const response = await fetch('https://api.dashamail.com/v2/dialogs/attachments/3391', {
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);
{
"response": {
"msg": {
"err_code": 0,
"text": "OK",
"type": "message"
},
"data": {
"url": "https://s3.dashamail.ru/dialogs/3391?X-Amz-Expires=900&…",
"filename": "счёт.pdf",
"content_type": "application/pdf",
"size_bytes": 48211,
"expires_at": "2026-04-05 13:10:00"
}
}
}