Перейти к основному содержимому
Опубликовано: 

Sendsay API — Руководство по работе

Полная документация Sendsay API

Общие сведения

Sendsay API — это HTTP-интерфейс для управления рассылками, подписчиками, статистикой и другими объектами системы. Взаимодействие с API происходит через JSON-запросы, которые отправляются методом POST.

Параметры подключения

  • Транспорт: HTTPS (HTTP 1.0/1.1)
  • Шифрование: TLS 1.2 или TLS 1.3
  • Адрес API: https://api.sendsay.ru

Рекомендуется использовать расширение SNI.

Имя api.sendsay.ru имеет несколько IP-адресов. Если соединение с одним из них не устанавливается, рекомендуется повторить запрос с использованием другого.

Важно

Для работы с API в CDP поддерживается ГОСТ-шифрование. Это дополнительная услуга. Чтобы подключить её, .

Формат запроса

Endpoint

POST https://api.sendsay.ru/general/api/v100/json/account

Где account — код вашего аккаунта (совпадает с основным логином).

Для вызовов, не требующих привязки к аккаунту (например, ping), используйте символ -:

POST https://api.sendsay.ru/general/api/v100/json/-

Тело запроса

Основные требования к телу запроса:

  • Content-Type: application/json.
  • Кодировка: UTF-8.
  • Максимальный размер: 400 Мбайт.

Запрос — это JSON-объект с обязательным полем action:

{
"action": "название_действия",
"session": "идентификатор_сессии",
"параметр1": "значение1",
"параметр2": "значение2"
}
Важно

Используйте готовые функции вашего языка программирования для сериализации JSON. «Красивое» форматирование пробелами необязательно — его отсутствие уменьшает размер запроса и ускоряет обработку.

Аутентификация

Важно

Для автоматической работы по API создавайте отдельный саблогин с максимально ограниченными правами и используйте для него API-ключ или JWT-токен.

Как создать саблогин

Sendsay API поддерживает несколько способов аутентификации. Ниже подробно описан рекомендуемый для автоматизации способ — API-ключ. Остальные способы смотрите в документации API.

API-ключ (рекомендуется для автоматизации)

Создайте API-ключ заранее вызовом sys.user.apikey.create.

Аутентификация действует на один вызов и не требует logout. Процессы, запущенные асинхронными вызовами, продолжат работу до завершения.

В теле запроса:

{
"action": "нужное_действие",
"apikey": "ваш_ключ_api",
"...": "..."
}

В HTTP-заголовке:

Authorization: sendsay apikey=ключ-api-url-кодированный

Как получить API-ключ

Другие способы аутентификации

СпособОписаниеДокументация
Логин и пароль (сессия)Классическая аутентификация через login / logout. Сессия живёт несколько часовПодробнее
JWT-токенАутентификация по подписанному токену (RFC 7519). Подходит для серверного взаимодействияПодробнее
Двухфакторная аутентификация (SMS)Логин + пароль с подтверждением кодом из SMSПодробнее
OpenIDАутентификация через внешний OpenID-провайдер. Для настройки Подробнее

Формат ответа

Ответ — JSON в кодировке UTF-8 (Content-Type: application/json).

HTTP-статусы

СтатусЗначение
200Нормальный ответ
3xxПеренаправления (необходимо обрабатывать)
503Превышение лимита запросов (rate_limit)
ПрочиеНеизвестная ошибка — повторите запрос

Общие поля ответа

Каждый ответ может содержать следующие служебные поля:

{
"request.id": "значение из запроса",
"duration": "время обработки в секундах",
"_ehid": "служебная строка для отладки"
}

Успешный ответ

{
"request.id": "...",
"поле_результата_1": "значение",
"поле_результата_2": "значение"
}

Ответ с ошибкой

При ошибке в ответе появляется массив errors:

{
"errors": [
{
"id": "код_ошибки",
"explain": "описание ошибки"
}
]
}
Важно

Поле explain может быть строкой, массивом или объектом — в зависимости от вызова и ошибки.

Некоторые вызовы также возвращают массив warnings — это события, которые помешали выполнить вызов частично, но не делают его ошибочным.

Специальный случай: требуется смена пароля

Если вы получили ошибку error/auth/failed с уточнением force_change_password, для продолжения работы необходимо:

  1. Сменить пароль через вызов sys.user.set с разовой аутентификацией.
  2. Повторить исходный запрос (он не был выполнен). Может потребоваться новая сессия.

Синхронные и асинхронные запросы

Синхронные запросы

По умолчанию запросы синхронны — запрошенное действие выполняется (или не выполняется при ошибке) к моменту ответа. Результат содержится непосредственно в ответе.

Асинхронные запросы

Асинхронный запросы означает, что действие принято в очередь, и будет выполнено позже. В ответе возвращается track.id — номер трекера для отслеживания статуса запроса через track.get.

Примеры асинхронных запросов: issue.send, member.import, stat.uni, member.list и другие.

Отслеживание асинхронных запросов

Получение состояния запроса

{
"action": "track.get",
"id": 12345
}

Ответ содержит поле obj с подробной информацией: статус, дата создания, параметры запроса, прогресс выполнения (ETA) и результаты.

Основные статусы трекера

КодЗначение
-7Приостановлен
-6Не прошёл модерацию
-5На премодерации
-4Отложенное действие
-3Отменён
-2Завершился с ошибкой
-1Завершился успешно
0Принят
1Запущен
2Начата обработка
3–6Промежуточные этапы (сортировка, форматирование, генерация отчёта, антиспам)

Список всех трекеров

{
"action": "track.list",
"filter": [],
"order": [],
"skip": 0,
"first": 50
}

Информация о запросах старше двух месяцев удаляется автоматически. Для issue.send/personal — через два дня.

Отмена и пауза

Для трекеров в состояниях 0, 1 или 2 можно установить статус «отменён» (-3) или «пауза» (-7, только для member.import):

{
"action": "track.set",
"id": 12345,
"status": -3
}
Важно

Уже совершённые действия останутся в силе. Отмена прекращает обработку только оставшейся части списка действий.

Лимиты и ограничения

ПараметрЗначение
Одновременных запросов на изменение данных5
Одновременных запросов всего10
Запросов в секунду80
Максимальный размер запроса400 Мбайт

При превышении лимитов вы получите ошибку rate_limit с HTTP-кодом 503.

Идентификация запросов (request.id)

Необязательный параметр request.id помогает при отладке и обращениях в службу поддержки. Он возвращается в ответе без изменений.

Способы передачи

В URL:

https://api.sendsay.ru/general/api/v100/json/account?request.id=мой-запрос-123

В теле запроса:

{
"action": "...",
"request.id": "мой-запрос-123"
}

В HTTP-заголовке:

X-Request-ID: мой-запрос-123
Важно

Нельзя указывать request.id несколькими способами одновременно — это вызовет ошибку double_request.id.

Защита от дублирования

Для некоторых вызовов повторный запрос с тем же request.id в течение 15 минут вернёт ошибку repeated_request.id. Это правило действует для следующих вызовов:

  • issue.send
  • issue.send.multi
  • member.import
  • member.import.probe
  • member.sendconfirm

Время защиты можно увеличить (до 2 часов) через параметр repeated_request_ttl (в секундах).

Пакетные запросы — batch

Пакетные запросы позволяют отправить несколько запросов за один вызов:

{
"action": "batch",
"stop_on_error": 0,
"do": [
{ "action": "первый_запрос", "...": "..." },
{ "action": "второй_запрос", "...": "..." }
]
}

Ответ:

{
"result": [
{"ответ на первый запрос"},
{"ответ на второй запрос"}
]
}

Особенности пакетных запросов:

  • Запросы выполняются последовательно.
  • Запросы изолированы друг от друга (результат одного недоступен в другом).
  • Порядок ответов совпадает с порядком запросов.
  • stop_on_error: 1 — прекращает выполнение после первой ошибки.
  • Аутентификация (session, one_time_auth) работает только в основном запросе.
  • login и logout во вложенных запросах вызовут ошибку.
  • Несколько статистических запросов в одном batch могут привести к ошибке нехватки памяти.

Кэширование ответов

Кэширование ответов поддерживается для вызовов stat.uni и member.list.count и применяется только к успешным ответам.

Параметры кэша

{
"action": "stat.uni",
"cache": {
"mode": "use",
"key": "мой-ключ-кэша",
"ttl": 3600
},
"...": "..."
}

Режимы кэширования

РежимПоведение
ignoreНе использовать кэш
useВернуть из кэша, если есть; иначе вычислить и сохранить
refreshВычислить заново и сохранить в кэш
fetchВернуть из кэша, если есть; иначе — пустой ответ (без вычисления)

Правила для ключа кэша: до 64 печатных символов ASCII (без пробела). Ключи не пересекаются между разными вызовами, но видны всем саблогинам одного аккаунта.

Ответ с кэшем содержит поле cache:

{
"cache": {
"hit": 1,
"created": "2025-01-15 12:30:00",
"expired": "2025-01-15 13:30:00"
}
}
  • hit: 1 — данные из кэша,
  • hit: 0 — вычислены заново или кэш пуст.
Важно

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

Возвращаемое значение и способы получения результата

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

Вернуть в ответе (по умолчанию)

Результат возвращается синхронно. Подходит для интерактивных интерфейсов (для автоматизации лучше использовать асинхронную схему).

{ "type": "response" }

Сохранить в Отчёты

Файл хранится 90 дней. Формат: CSV, XLSX, HTML или JSON.

{ "type": "save", "to": "имя_файла", "format": "csv" }

Отправить на электронную почту

Файл с результатом будет отправлен на указанную электронную почту.

{ "type": "email_file", "to": ["test@test.com"], "format": "xlsx", "filename": "отчёт.xlsx" }

Загрузить на внешний сервер (HTTP/HTTPS)

Файл с результатом будет загружен на внешний сервер с указанным адресом.

{
"type": "url_file",
"to": "https://test.com/upload",
"name": "file",
"filename": "data.csv",
"format": "csv"
}

Загрузить по FTP/FTPS

{
"type": "url_file",
"to": "ftp://ftp.test.com/reports/",
"filename": "data.csv",
"format": "csv"
}

Уведомление на почту (без самого результата)

На указанную электронную почту поступит уведомление о готовности результата.

{ "type": "email_notify", "to": ["test@test.com"] }

Уведомление по SMS

Уведомление о готовности результата придёт в виде SMS.

{ "type": "sms", "to": ["+79001234567"] }

Уведомление по внешней ссылке (GET)

{ "type": "url_notify", "to": "https://test.com/callback" }

Не возвращать результат

{ "type": "none" }

Параметры формата

Для всех вариантов с format доступны дополнительные настройки:

  • compresszip, bzip2, gzip или пусто (без сжатия).
  • separator — разделитель полей для CSV (по умолчанию запятая).
  • always_quote0 или 1 — всегда обрамлять значения кавычками в CSV.
  • utf80 или 1 — использовать UTF-8 для CSV (рекомендуется 1).
  • append0 или 1 — дописать в существующий файл (только без сжатия).
Важно

Кодировка по умолчанию для CSV зависит от даты создания аккаунта: до 28 февраля 2018 — windows-1251, после — UTF-8.

Представление данных

Числа

Числовые значения могут передаваться и возвращаться как JSON-число или как JSON-строка:

{"count": 123}
{"count": "123"}

Допустимо использовать оба варианта.

Даты

В полях с датами указывается московское время. Формат поля:

YYYY-MM-DD hh:mm:ss

Можно указывать дату и время без лидирующих нулей, например: 2025-5-3 9:7:4.

Точность указывается метками: Ys (от года до секунды), Yh (до часа), YD (до дня).

Необязательные параметры

  • Параметры логики работы: если отсутствуют или пусты — считаются как 0 (нет).
  • Текстовые параметры: если отсутствуют — считаются пустой строкой.

Порядок обработки вызовов

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

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

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

Защищённые сущности

Большинство сущностей поддерживают защиту от изменения и удаления через свойство protected:

ЗначениеОписание
0Не защищено (по умолчанию)
1Защищено пользователем
-1Защищено системой

Для изменения или удаления объекта с protected = 1 передайте параметр ignore_protection со значением, равным id объекта.

Какие сущности можно защитить: списки и сегменты, черновики, форматы, анкеты, формы, логины, роли, действия по расписанию, триггеры, DKIM-ключи, адреса email-отправителей, названия SMS-отправителей.

Логины и пароли в ссылках

Некоторые вызовы обращаются к внешним серверам по HTTP(S) или FTP(S). Учётные данные можно указать прямо в URL:

http://login:password@host.tld/path

Однако рекомендуется использовать объект «Внешняя аутентификация», созданный через authext.create, и указывать его номер:

http://authext:777@host.tld/path

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

Проверка доступности

Пинг без аутентификации

{ "action": "ping" }

Ответ:

{ "pong": "случайное_значение" }

Пинг с аутентификацией

{ "action": "pong" }

Ответ:

{
"ping": "случайное_значение",
"account": "код_аккаунта",
"sublogin": "код_саблогина",
"via": "способ_аутентификации"
}

Готовые библиотеки

Готовые библиотеки для работы с Sendsay API доступны на GitHub.

Читайте также:
Отправка массовых рассылок через Sendsay API
Отправка транзакционных рассылок через Sendsay API
Импорт и добавление контактов через Sendsay API
Получение статистики через Sendsay API