Импорт и добавление контактов через Sendsay API
Sendsay API позволяет управлять базой контактов: добавлять контакты по одному, массово импортировать списки, обновлять данные существующих контактов.
Ключи данных и анкеты
Sendsay поддерживает два формата хранения данных контактов:
- Ключи данных (КД) — современный формат, используется в
member.set/member.get. Данные — произвольные ключи с любым уровнем вложенности (объекты, массивы). - Анкета-Вопрос-Ответ (АВО) — устаревший формат с привязкой к анкетам.
Ключи данных — более современный и удобный формат, с которым проще работать. Он более гибкий и поддерживает вложенные структуры.
Добавление одного контакта — member.set
Вызов member.set создаёт новый контакт или обновляет данные существующего. Работает с форматом Ключи данных (КД).
Минимальный запрос
{
"apikey": "ваш-api-ключ",
"action": "member.set",
"addr_type": "email",
"email": "test@test.com",
"datakey": [
["base.firstName", "set", "Анна"],
["base.city", "set", "Москва"]
]
}
Параметры
| Параметр | Описание |
|---|---|
action | member.set |
addr_type | Тип идентификатора: email, msisdn, viber, csid, push, vk, tg, vknotify, pushapp, id и др. Указывать его не обязательно — система сама распознаёт email или msisdn |
email | Адрес контакта (для addr_type: email) |
datakey | Массив операций над ключами данных. Каждая операция — массив: ["ключ", "режим", "значение"] или ["ключ", "режим", "значение", "тип"] |
if_exists | Поведение при существующем контакте: overwrite (по умолчанию) — обновить данные; error — вернуть ошибку; must — обновить только существующий, не создавать новый |
newbie.confirm | 1 — требовать подтверждения внесения в базу (по умолчанию 0). Используется только для email-адресов, действует лимит внесения без подтверждения |
Режимы изменения данных
| Режим | Описание |
|---|---|
set | Заменить данные новым значением |
update | Заменить, только если ключ уже существует |
insert | Добавить, только если ключа ещё нет |
merge | Объединить объекты: для каждого ключа нового значения выполняется set в существующий объект |
merge_update | Объединить объекты: заменяются только существующие ключи, новые игнорируются |
merge_insert | Объединить объекты: добавляются только отсутствующие ключи, существующие не трогаются |
push | Добавить значение в конец массива |
unshift | Добавить значение в начало массива |
delete | Удалить данные по ключу (значение не указывается) |
Каждый из режимов (кроме delete) имеет вариант с суффиксом .copy (например: set.copy, update.copy) — в этом случае вместо значения указывается ключ данных, из которого копируется значение.
Пример: задать несколько полей
{
"apikey": "ваш-api-ключ",
"action": "member.set",
"addr_type": "email",
"email": "test@test.com",
"datakey": [
["base.firstName", "set", "Анна"],
["base.lastName", "set", "Ив анова"],
["base.city", "set", "Москва"],
["base.birthDate", "set", "1990-05-15", "dt:YD"]
]
}
Элемент "dt:YD" — необязательный тип данных. Для дат выполняется проверка и приведение к стандартному формату (например, "1990-5-4" станет "1990-05-04").
Добавление с указанием списка
Для управления списка ми используется псевдо-ключ -group.КОДГРУППЫ с режимом set и значением 1 (включить) или режимом delete (исключить):
{
"apikey": "ваш-api-ключ",
"action": "member.set",
"addr_type": "email",
"email": "test@test.com",
"datakey": [
["base.firstName", "set", "Анна"],
["-group.clients", "set", "1"],
["-group.newsletter", "set", "1"]
]
}
Обновление данных без автосоздания
Если нужно обновить данные только существующего контакта и не создавать новый, используйте if_exists: "must":
{
"apikey": "ваш-api-ключ",
"action": "member.set",
"addr_type": "email",
"email": "test@test.com",
"if_exists": "must",
"datakey": [
["member.cellphone", "set", "+79001234567"],
["loyalty_level", "set", "gold"]
]
}
Если контакта с таким адресом нет — вызов вернёт ошибку, а не создаст новый контакт.
Обновление только отсутствующих данных
Режим insert позволяет записать значение, только если ключ ещё не существует — удобно для первичного внесения данных без перезаписи:
{
"datakey": [
["base.firstName", "insert", "Неизвестный"],
["base.city", "insert", "Не указан"]
]
}
Удаление данных
{
"datakey": [
["loyalty_level", "delete"],
["-group.old_segment", "delete"]
]
}
Ответ
Успешный ответ:
{
"addr_type": "email",
"email": "test@test.com"
}
Все изменения в datakey применяются вместе — либо все операции выполняются, либо не одна (при любой ошибке).
Получение данных контакта — member.get
{
"apikey": "ваш-api-ключ",
"action": "member.get",
"addr_type": "email",
"email": "test@test.com",
"datakey": ["base.firstName", "base.city", "member.cellphone", "-group"]
}
В datakey перечисляются ключи, которые нужно получить.
Специальный ключ -group вернёт список групп контакта. Чтобы получить все данные, используйте "*":
{
"apikey": "ваш-api-кл юч",
"action": "member.get",
"addr_type": "email",
"email": "test@test.com",
"datakey": ["*"]
}
Проверка существования контакта — member.exists
{
"apikey": "ваш-api-ключ",
"action": "member.exists",
"email": "test@test.com"
}
Ответ:
{
"list": {
"test@test.com": 1
}
}
Значение 1 — контакт существует, 0 — не существует, null — ошибка в адресе (невалидный формат).
Поиск контакта по всем типам идентификаторов — member.find
Одна и та же строка может соответствовать разным типам идентификаторов (email, csid и др.). Вызов member.find возвращает все совпадения:
{
"apikey": "ваш-api-ключ",
"action": "member.find",
"email": "test@test.com"
}
Ответ:
{
"list": [
{
"id": 12345,
"addr_type": "email",
"email": "test@test.com"
}
]
}
Информация об адресе — email.get
Запрос возвращает информацию об адресе, не связанную с существованием контакта — включая данные об ошибках доставки, стоп-листе и отписках. Работает, даже если контакт уже удалён.
{
"apikey": "ваш-api-ключ",
"action": "email.get",
"email": "test@test.com",
"with_stoplist": 2
}
Параметр with_stoplist: 2 возвращает расширенный формат стоп-листа с записями и по глоб альному стоп-листу, и по отпискам от отдельных отправителей.
В ответе придёт блок member с информацией:
- номер адреса (
id), - наличие блокировки (
haslock), - ошибки доставки (
error), - статус отписки (
lockremove), - записи стоп-листа (
stoplist).
Удаление контакта — member.delete
{
"apikey": "ваш-api-ключ",
"action": "member.delete",
"addr_type": "email",
"email": "test@test.com"
}
Массовый импорт — member.import
Вызов member.import позволяет загрузить список контактов одним запросом. Адреса и данные передаются прямо в запросе через users.list или по ссылке через users.url. Параметр users.list поддерживает несколько форматов.
Формат определяется автоматически по типу значения:
- Если значение — объект → JSON-объект (АВО или КД, в зависимости от структуры
caption). - Если значение — строка ZIP с файлом workbook.xml → XLSX.
- Если значение — строка ZIP без workbook.xml → CSV (первый файл архива).
- Если значение — строка без ZIP → CSV.
При использовании users.url формат определяется по Content-Type ответа:
- если
application/json— данные должны быть объектом, - иначе — по правилам для строки.
JSON-массив доступен только для экспресс-выпуска. Для импорта контактов (member.import) этот формат не поддерживается.
Формат: CSV (строка)
Текстовые данные в формате CSV. Разделитель — запятая или точка с запятой. Первая строка — заголовок с описанием столбцов (в формате коданкеты.кодвопроса для модели АВО).
{
"apikey": "ваш-api-ключ",
"action": "member.import",
"addr_type": "email",
"users.list": "member.email,base.firstName,base.city\nclient1@example.com,Анна,Москва\nclient2@example.com,Иван,Санкт-Петербург\nclient3@example.com,Ольга,Казань"
}
Если в значении ячейки встречается разделитель или кавычки, значение берётся в кавычки, а кавычки внутри удваиваются:
member.email,base.lastName,member.cellphone
test@test.ru,"ЗАО ""Рога и копыта""",+70000000000
test2@test.ru,"Рога, копыта и хвосты",+70000000000
Формат: JSON-объект-АВО
Объект с массивом caption (описание соответствия столбцов анкетам и вопросам) и массивом rows (данные). Каждая ячейка содержит одно значение: не массив и не объект.
{
"apikey": "ваш-api-ключ",
"action": "member.import",
"addr_type": "email",
"users.list": {
"caption": [
{ "anketa": "member", "quest": "email" },
{ "anketa": "base", "quest": "firstName" },
{ "anketa": "base", "quest": "city" }
],
"rows": [
["client1@example.com", "Анна", "Москва"],
["client2@example.com", "Иван", "Санкт-Петербург"],
["client3@example.com", "Ольга", "Казань"]
]
}
}
Формат: JSON-объект-КД
Аналогичная структура с caption и rows, но caption описывает ключи данных (datakey) и режим изменения (mode). Данные в ячейках могут быть любой структуры — строки, числа, массивы, объекты.
Импорт в формате JSON-объект-КД — это массовый member.set с индивидуальными данными для каждого контакта.
{
"apikey": "ваш-api-ключ",
"action": "member.import",
"addr_type": "email",
"users.list": {
"caption": [
{ "datakey": "member.email" },
{ "datakey": "base.firstName" },
{ "datakey": "base.city" },
{ "datakey": "tags" }
],
"rows": [
["client1@example.com", "Анна", "Москва", ["vip", "active"]],
["client2@example.com", "Иван", "Санкт-Петербург", ["new"]],
["client3ga@example.com", "Ольга", "Казань", { "level": "gold", "score": 150 }]
]
}
}
В caption также можно использовать:
{ "ignore": 1 }для пропуска столбца,{ "dynamic": 1 }для динамического ключа (в ячейке — структура аналогичная записиmember.setсdatakeyилиnull).
Параметры
| Параметр | Описание |
|---|---|
action | member.import |
addr_type | Тип идентификатора: email, msisdn, viber, csid, push, vk, tg, vknotify, pushapp, id и др. Не обязательно — система сама распознаёт email или msisdn |
users.list | Данные контактов: строка (CSV/XLSX) или JSON-объект (АВО/КД). JSON-массив не поддерживается |
users.url | Альтернатива users.list — ссылка на внешний файл с данными |
users.list.encoding | Кодировка данных (для CSV) |
separator | Разделитель полей в CSV (,, ;, \t и др.) |
caption | Описание столбцов (альтернатива первой строке CSV или заголовку XLSX) |
if_exists | overwrite — обновить существующих; error — пропустить существующих; must — обно вить только существующих, не создавать новых |
newbie.confirm | 1 — требовать подтверждения внесения в базу (по умолчанию 0). Внесение email без подтверждения ограничено лимитом member.noconfirm.rest (можно проверить через sys.settings.get). Не влияет на номера телефонов — они всегда вносятся без подтверждения |
auto_group | Объект. Автоматически создать список для импортируемых адресов или дополнить существующую. Содержит id (код списка) и name (название). Если id не указан — создаётся список со стандартным кодом importYYYYMMDDhhmmss. Код созданного списка можно узнать через track.get |
clean_group | 1 — очистить список из auto_group перед импортом (полная замена участников). По умолчанию 0 |
member.group.add | Массив кодов списков, в которые нужно добавить импортируемые адреса |
member.group.remove | Массив кодов списков, из которых нужно удалить импортируемые адреса |
sequence.event | 1 — внесение/изменение данных будет вызывать срабатывание событийных действий. По умолчанию 0 |
sequence.start | Массив номеров триггеров, прохождение которых нужно запустить для всех участников импорта |
sequence.stop | Массив номеров триггеров, прохождение которых нужно остановить для всех участников импорта |
Порядок обработки списков:
- сначала удаление из
member.group.remove, - затем добавление в
member.group.add, - затем
auto_group.
Порядок обработки последовательностей:
- сначала остановка по
sequence.stop, - затем запуск по
sequence.start.
Действует на всех участников импорта, независимо от того, изменились ли их данные.
Импорт с автосозданием списка
{
"apikey": "ваш-api-ключ",
"action": "member.import",
"addr_type": "email",
"users.list": "member.email,base.firstName\nclient1@example.com,Анна\nclient2@example.com,Иван",
"auto_group": {
"id": "march_import",
"name": "Импорт март 2026"
}
}
Импорт с добавлением и удалением из списка (CSV)
{
"apikey": "ваш-api-ключ",
"action": "member.import",
"addr_type": "email",
"users.list": "member.email,base.firstName\nclient1@example.com,Анна\nclient2@example.com,Иван",
"member.group.add": ["newsletter", "clients"],
"member.group.remove": ["old_segment"]
}
Импорт с добавлением и удалением из списков (JSON-объект-КД)
{
"apikey": "ваш-api-ключ",
"action": "member.import",
"addr_type": "email",
"users.list": {
"caption": [{ "datakey": "member.email" }, { "datakey": "base.firstName" }],
"rows": [
["client1@example.com", "Анна"],
["client2@example.com", "Иван"]
]
},
"member.group.add": ["newsletter", "clients"],
"member.group.remove": ["old_segment"]
}
Импорт из файла
Если список контактов большой, данные можно загрузить как файл в хранилище CDP Sendsay (rfs.file.put) и указать путь:
{
"apikey": "ваш-api-ключ",
"action": "member.import",
"addr_type": "email",
"users.file": "путь/к/файлу.csv",
"separator": ";",
"auto_group": {
"id": "newsletter"
}
}
Ответ
Импорт — асинхронный вызов. В ответе возвращается трекер:
{
"track.id": 11111
}
Результат импорта проверяется вызовом track.get:
{
"apikey": "ваш-api-ключ",
"action": "track.get",
"id": 11111
}
В финальном ответе трекера будет информация о количестве обработанных, созданных, обновлённых, про пущенных контактов и ошибках.
Пробный импорт — member.import.probe
Перед массовым импортом вы можете проверить формат данных, без реального внесения:
{
"apikey": "ваш-api-ключ",
"action": "member.import.probe",
"addr_type": "email",
"users.list": "email;name\nclient1@example.com;Анна",
"separator": ";"
}
Запрос вернёт информацию о распознанных столбцах, типах данных и возможных ошибках.
Отправка письма-подтверждения — member.sendconfirm
Вызов позволяет отправить письма, в которых работают специальные команды шаблонизатора:
[% param.url_confirm %]для подтверждения внесения в базу,[% param.url_unsub_cancel %]и[% param.url_unsub_sender_cancel %]для удаления из стоп-листов.
Типы подтверждений
| Параметр | Описание |
|---|---|
confirm: 1 | Подтверждение внесения в базу |
unsubcancel: 1 | Удаление из глобального стоп-листа |
unsubsendercancel: 1 | Удаление из стоп-листа по отправителю (отправитель берётся из черновика letter) |
Пример: подтверждение для одного контакта
{
"apikey": "ваш-api-ключ",
"action": "member.sendconfirm",
"confirm": 1,
"letter": "confirm_letter",
"email": "client1@example.com"
}
Параметр letter — это код информационного письма, который обязательно нужно указать. Письмо должно иметь заполненный адрес отправителя и не находиться на модерации.
Способы указания получателей
| Способ | Описание | Синхронность по умолчанию |
|---|---|---|
email | Один контакт | Синхронно |
list | Массив идентификаторов | Синхронно |
group | Код спис ка | Асинхронно |
group.filter | Фильтр отбора | Асинхронно |
url | Ссылка на файл с данными | Асинхронно |
stat.uni | Выборка из универсальной статистики | Асинхронно |
Синхронность можно изменить параметром sync: 0|1.
Пример: подтверждение для списка контактов
{
"apikey": "ваш-api-ключ",
"action": "member.sendconfirm",
"confirm": 1,
"letter": "confirm_letter",
"list": ["client1@example.com", "client2@example.com"]
}
Пример: подтверждение для списка
{
"apikey": "ваш-api-ключ",
"action": "member.sendconfirm",
"confirm": 1,
"letter": "confirm_letter",
"group": "unconfirmed_users",
"issue_name": "Повторное приглашение"
}
При использовании group, group.filter, url или stat.uni создаётся выпуск, номер которого возвращается в issue.id. Асинхронные запросы также возвращают track.id для отслеживания.
Особенности добавления контактов через Sendsay API
- При импорте система проверяет адреса и может отклонить некорректные.
- Результаты импорта доступны в «Журнале заданий».
- Повторный импорт с
if_exists: "overwrite"обновит данные существующих контактов, а не создаст дубликаты. - Для работы с триггерными сценариями можно указать, на какие последовательности запустить участников, а на каких остановить.
- Максимальные лимиты на размер
users.listи количество записей зависят от тарифа. Для очень больших списков рекомендуется использовать загрузку через файл.