К содержанию
API v3

Интеграции

Интеграции и письма

CRM и сопоставление полей, вебхуки, мессенджеры, таблицы, счётчики, письма опроса и своя почта

Markdown для нейросетей Актуально на 15.10.2026

Состояние интеграций и журнал отправок

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

Отказы:

Ответ Когда
403 + blocked_by_access: true у участника нет права integrations
403 + blocked_by_tariff: true тариф не включает эту интеграцию
400 + code: not_connected журнал запрошен у неподключённой интеграции

47. Состояние интеграций опроса

В API с 08.09.2026

Отвечает на «почему заявки не приходят»: по каждой интеграции сразу видно, подключена ли она, включена ли отправка и разрешает ли её тариф.

GET/quiz/{id}/integrations
Аутентификация: Обязательна

Пример ответа (200)

JSON
{
    "status": true,
    "quiz_id": 18547,
    "integrations": {
        "telegram": {"connected": true, "enabled": true, "allowed_by_tariff": true, "blocked": null},
        "max": {"connected": false, "enabled": false, "allowed_by_tariff": true, "blocked": "not_connected"},
        "amocrm": {"connected": true, "enabled": false, "allowed_by_tariff": true, "blocked": "disabled"},
        "bitrix24": {"connected": false, "enabled": false, "allowed_by_tariff": false, "blocked": "blocked_by_tariff"},
        "zapier": {"connected": false, "enabled": false, "allowed_by_tariff": true, "blocked": "not_connected"},
        "google_sheets": {"connected": false, "enabled": false, "allowed_by_tariff": true, "blocked": "not_connected"}
    }
}

blocked — готовая причина, по которой ответы не уходят: blocked_by_tariff, not_connected или disabled. Пусто — отправка работает.

Вебхуки в этот ответ не входят: у них своя настройка и свой журнал доставки.


48. Журнал отправок мессенджера

В API с 08.09.2026

Свой журнал отправок есть у Telegram и MAX. По нему видно причину, по которой сообщение не ушло: бота выгнали из группы, чат удалён, токен отозван.

GET/quiz/{id}/integrations/logs
Аутентификация: Обязательна

Query параметры

Параметр Тип Обязательное Описание
integration string Да telegram или max. Другие значения — 422.
page integer Нет Страница, по умолчанию 1.
per_page integer Нет Записей на странице, 1–100, по умолчанию 20.
status string Нет Только записи с этим статусом: sent, failed, queued. Без параметра — все. Другое значение — 422. С 2026-10-13.

Пример ответа (200)

JSON
{
    "status": true,
    "quiz_id": 18547,
    "integration": "telegram",
    "total": 143,
    "page": 1,
    "per_page": 20,
    "last_page": 8,
    "unsent_count": 3,
    "counts": { "all": 143, "failed": 3, "queued": 0 },
    "logs": [...]
}

unsent_count — сколько отправок сорвалось и ждёт повтора.

total и last_page считаются с учётом status. counts — по всему журналу, от status и страницы не зависит: all — все записи, failed — не дошли (то же, что unsent_count), queued — в очереди на отправку; дошедших — all − failed − queued. Поле counts — с 2026-10-13. У каждой записи есть created_at (ISO 8601, UTC) — время попытки: у недошедшей sent_at пустой. У недошедшей записи заполнен хотя бы error_message (у Telegram ещё error_type), при отказе мессенджера — и error_code; у таймаута и обрыва связи error_code — номер ошибки cURL, 28 — таймаут. Старые записи (Telegram — до июня 2026, MAX — до октября 2026) могут быть без причины.

error_type у Telegram: bot_blocked, user_deactivated, chat_not_found, thread_not_found (тема удалена), topic_closed (тема закрыта — её можно открыть снова; с 2026-10-13, раньше записывалось как thread_not_found), no_access, other.

Неподключённая интеграция отвечает 400 с кодом not_connected, а не пустым списком: журнала в этом случае не существует, и пустой список означал бы, что отправок не было.


49. Досылка неотправленного

В API с 08.09.2026

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

POST/quiz/{id}/integrations/logs/resend
Аутентификация: Обязательна

Тело запроса (JSON)

Поле Тип Обязательное Описание
integration string Да telegram или max.
log_id integer Нет Одна запись журнала.
date_from date Нет Начало периода для досылки всех неудачных.
date_to date Нет Конец периода, не раньше date_from.

Без log_id и без периода дошлются все неудачные отправки. log_id вместе с периодом — 422: это разные действия, и вместе они означали бы, что период молча проигнорирован.

Пример ответа (200)

JSON
{
    "status": true,
    "quiz_id": 18547,
    "integration": "telegram",
    "resent": 3
}

Отправка ответов в CRM

Молчащая интеграция выглядит одинаково при трёх разных причинах: отправка выключена, тариф её не включает или на стороне CRM отозвали токен. Последнее со стороны опроса не видно вообще — поэтому проверка связи здесь отдельным методом.

{crm} в путях — amocrm или bitrix24. Другое значение — 422 с кодом unknown_crm. Опрос без подключённой CRM — 400 с кодом not_connected: это не пустое состояние, а отсутствие настройки.

Права и тариф — как во всём разделе: тарифная опция этой CRM плюс право участника integrations.


50. Состояние подключения CRM

В API с 08.09.2026

GET/quiz/{id}/integrations/crm/{crm}
Аутентификация: Обязательна

Пример ответа (200)

JSON
{
    "status": true,
    "quiz_id": 18547,
    "crm": "bitrix24",
    "connected": true,
    "is_active": false
}

51. Включить или выключить отправку в CRM

В API с 08.09.2026

POST/quiz/{id}/integrations/crm/{crm}/toggle
Аутентификация: Обязательна

Тело запроса (JSON)

Поле Тип Обязательное Описание
is_active boolean Да Включить отправку или выключить. Принимаются и строки "true" / "false".

Пример ответа (200)

JSON
{"status": true, "quiz_id": 18547, "crm": "bitrix24", "is_active": true}

Отказ записи — 400 с кодом toggle_failed.


52. Проверить, живо ли подключение

В API с 08.09.2026

Токен отзывают на стороне CRM, и со стороны опроса это выглядит как молчащая интеграция. Метод обращается к порталу и отвечает, отвечает ли он.

GET/quiz/{id}/integrations/crm/{crm}/check
Аутентификация: Обязательна

Пример ответа (200)

JSON
{
    "status": true,
    "quiz_id": 18547,
    "crm": "bitrix24",
    "is_active": true,
    "connection_ok": false
}

Мёртвая связь — это результат проверки, а не сбой вызова, поэтому ответ успешный: смотреть надо на connection_ok.


53. Справочники CRM и текущее сопоставление

В API с 08.09.2026

То же, что видит человек в форме настройки: поля лида, сделки, контакта и компании, воронки со стадиями, ответственные. Рядом — сопоставление, сохранённое у опроса сейчас.

GET/quiz/{id}/integrations/crm/{crm}/fields
Аутентификация: Обязательна

Query параметры

Параметр Тип Обязательное Описание
sections array Нет lead, deal, contact, company, users, pipelines, types. По умолчанию lead и contact: каждый справочник — отдельный запрос в CRM. Принимается и строкой через запятую.
deal_category_id integer Нет Воронка, чьи стадии нужны (только Bitrix24). Без неё портал отдаёт стадии воронки по умолчанию.

Пример ответа (200)

JSON
{
    "status": true,
    "quiz_id": 18547,
    "crm": "bitrix24",
    "is_active": true,
    "sections": ["lead", "pipelines"],
    "directories": {
        "lead": {...},
        "deal_categories": [...],
        "deal_stages": [...]
    },
    "current_mapping": {"lead": {"enabled": true, "fields": {...}}}
}

Различия CRM отдаются как есть, а не подгоняются друг под друга: у amoCRM сделка и есть лид, поэтому разделы deal и types приходят со значением null — это ответ, а не сбой. У Bitrix24 раздел pipelines возвращает два справочника: воронки (deal_categories) и стадии (deal_stages).

Отозванный доступ к порталу — 400 с кодом connection_lost, сбой обращения к справочникам — 400 с кодом directories_failed. Справочники читаются живыми запросами в CRM, поэтому вызов не мгновенный.


Сопоставление полей опроса с полями CRM

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

Две CRM устроены по-разному, поэтому и методы разные. За один вызов правится одна сущность или один блок: правка одного не сбрасывает остальное, а непереданные ключи остаются прежними.


121. Bitrix24: сопоставление по сущностям

В API с 08.09.2026

POST/quiz/{id}/integrations/bitrix24/mapping/{entity}

{entity} — lead, contact, company, deal; другое значение — 422 с кодом unknown_entity.

Поле Тип Описание
enabled boolean Создавать эту сущность при ответе.
fields object {"ПОЛЕ": {"widget_id": "..."}} или {"ПОЛЕ": {"static_value": "..."}}, до 200 полей.
title_type string Field — название из вопроса, Static — заданный текст.
title_value string Идентификатор вопроса или сам текст, смотря по title_type.
company_title_value string Название компании.
status string Стадия лида (только lead).
add_id_to_title boolean Добавлять номер к названию (только lead).
category_id integer Воронка (только deal).
default_stage string Стадия сделки (только deal).
link_to_lead boolean Привязать сделку к лиду (только deal).

Набор полей заменяется целиком, но только когда его передали: вызов без fields оставляет прежний набор. Каждое поле берёт значение откуда-то одного — поле с обоими источниками даёт 422 с кодом field_ambiguous (адаптер в этом случае взял бы вопрос и молча проигнорировал постоянное значение), поле без источников — field_empty.

Стадия принадлежит воронке. У воронки по умолчанию стадия не начинается с «C», у воронки N обязана начинаться с «CN:». Несовместимая — 422 с кодом stage_mismatch; стадия у сущности, кроме сделки — stage_deal_only. Воронка берётся из вызова, а если её не передали — из уже сохранённых настроек.

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


122. amoCRM: сопоставление по блокам

В API с 08.09.2026

POST/quiz/{id}/integrations/amocrm/mapping/{block}

{block} — deal (сделка), list (контакты, компании, каталоги), task (задача); другое значение — 422 с кодом unknown_block.

Поле Тип Описание
active array Что создавать: номера воронок у сделки, 0 — контакт и 1 — компания у списков, номера каталогов портала.
titles object Название по номеру воронки или списка: идентификатор вопроса либо текст.
statuses object Стадия по номеру воронки.
users object Ответственный по номеру воронки или списка. Словарь ответственных у amoCRM один на сделки, списки и задачи: присланные номера дописываются в него (и видны в task), остальные остаются как были.
use_price object Брать сумму сделки из набранных баллов.
bind object {"ID поля CRM": "UUID вопроса"}, до 200 полей.
subtype object Уточнение вида значения у сопоставленного поля.

Каждое значение сверяется с живыми справочниками портала. Отказы приходят кодом: pipeline_unknown (нет такой воронки), status_mismatch (стадия из другой воронки), field_unknown (нет такого поля), bind_not_widget (значение поля берётся из ответа, поэтому здесь нужен вопрос, а не текст), subtype_without_bind, user_unknown, title_empty, directories_unavailable.

Пустой список active означает «не создавать» — это значение, а не отсутствие значения, и оно сохраняется. Ключи, которых нет в этом методе (например значения полей-списков, их заводит кабинет), сохраняются как были.

Без живого подключения к порталу метод отвечает 400 с кодом connection_lost и ничего не записывает: справочников не прочитать, а проверять нечем.

Метод POST /amocrm/quiz/{id}/settings остаётся: им пользуется виджет внутри amoCRM, который сохраняет весь набор настроек целиком. Он тоже проверяет тело по форме и сверяет воронки со справочниками портала, но работает с полным объектом настроек, а не с одним блоком. Для новых интеграций удобнее этот метод — он правит по одному блоку за раз.


Интеграции

AmoCRM: Аккаунт

В API с 19.02.2026

Получает общую информацию об аккаунте AmoCRM: воронки, пользователи, типы задач и дополнительные поля.

GET/amocrm/account
Аутентификация: Обязательна

Отказы

Ответ Код Когда Что делать клиенту
402 amocrm_subscription_expired У аккаунта amoCRM не оплачена подписка: портал закрывает свой API целиком Сказать про оплату в amoCRM. Повторная авторизация не поможет и ссылку на неё показывать не надо
401 amocrm_token_revoked Доступ отозван в портале: интеграцию удалили либо токен убит Предложить подключиться заново
429 amocrm_rate_limited Портал ограничил частоту запросов Повторить позже
403 amocrm_forbidden У подключённого сотрудника не хватает прав в портале: часть справочников amoCRM отдаёт только администратору аккаунта Сказать, что права выдаёт администратор amoCRM. Повторная авторизация не поможет
400 amocrm_account_unavailable Прочие причины: портал недоступен, ответ не разобрался Показать общую ошибку

Те же коды и статусы отдаёт GET /amocrm/lists; его собственный код amocrm_catalogs_unavailable остаётся для прочих причин.

Пример ответа (200)

JSON
{
    "pipelines": [...],
    "users": [...],
    "task_types": [...],
    "custom_fields": [...]
}

AmoCRM: Списки

В API с 19.02.2026

Получает каталоги (списки) из AmoCRM.

GET/amocrm/lists
Аутентификация: Обязательна

Пример ответа (200)

JSON
{
    "response": {
        "items": [...]
    }
}

AmoCRM: Поля каталога

В API с 22.09.2026

Возвращает поля элементов одного каталога amoCRM. У элемента каталога свой набор полей — не такой, как у сделки, контакта или компании, поэтому для сопоставления нужен именно он.

GET/amocrm/catalogs/{id}/fields
Аутентификация: Обязательна

Отказы

Те же, что у GET /amocrm/account; прочие причины — 400 amocrm_catalogs_unavailable.

Пример ответа (200)

JSON
{
    "response": {
        "items": [
            {
                "id": 2001,
                "name": "Артикул",
                "type": "text",
                "code": null,
                "sort": 10,
                "is_required": false,
                "enums": []
            }
        ]
    }
}

Поля, значение которых считает сам портал (is_computed) или которые служебные (is_api_only), в ответ не попадают: запись в них amoCRM отклоняет. У полей-списков приходят варианты (enums) — именно их номера портал ждёт при отправке значения.


AmoCRM: Ссылка на повторную авторизацию

В API с 22.09.2026

Возвращает ссылку, по которой пользователь заново подключает amoCRM к своему аккаунту WebAsk. Нужна, когда портал отозвал доступ (401 amocrm_token_revoked у методов выше): переподключиться можно прямо из виджета, не заходя в конструктор. В ссылке уже зашифрована метка пользователя, поэтому новые токены после авторизации сохранятся именно ему.

GET/amocrm/auth-url
Аутентификация: Обязательна

К amoCRM метод не обращается, поэтому отказов портала у него нет. Без авторизации — 401 с кодом user_not_authenticated.

Пример ответа (200)

JSON
{
    "status": true,
    "auth_url": "https://www.amocrm.ru/oauth?client_id=...&state=...&mode=post_message"
}

AmoCRM: Привязка доступа из установки виджета

В API с 24.09.2026

Когда виджет ставят в самом amoCRM, портал присылает нам код доступа и адрес аккаунта, но не говорит, чей это пользователь WebAsk. Сервер сразу меняет код на токены:

  • если этот аккаунт amoCRM уже подключён у кого-то в WebAsk (переустановка виджета) — токены обновляются у всех таких пользователей, ничего вызывать не нужно;
  • если аккаунт новый — токены ждут привязки 30 дней.

Этот метод привязывает ожидающие токены к текущему пользователю. Виджет вызывает его через $authorizedAjax amoCRM: тот добавляет заголовок X-Auth-Token — одноразовый JWT, подписанный секретом нашей интеграции. Адрес аккаунта сервер берёт только из этого токена (поле iss), поэтому забрать доступ чужого аккаунта нельзя.

POST/amocrm/link
Аутентификация: Обязательна (ключ WebAsk) и заголовок X-Auth-Token от amoCRM

Вызывать можно сколько угодно раз. Если ждущих токенов нет, метод ничего не меняет и отвечает, подключён ли этот аккаунт amoCRM у пользователя сейчас.

Статус code Когда
200 — linked: true — аккаунт подключён (только что или раньше), false — нет
401 user_not_authenticated Нет ключа WebAsk
403 amocrm_link_token_invalid Нет X-Auth-Token, неверная подпись, токен истёк или выписан другой интеграции

Пример ответа (200)

JSON
{
    "status": true,
    "linked": true
}

AmoCRM: Опросы

В API с 19.02.2026

Возвращает список опросов пользователя с информацией об активности интеграции AmoCRM.

GET/amocrm/quiz
Аутентификация: Обязательна

Query параметры

Аналогичны GET /quiz (sort, order, limit, offset, folder_id).

Пример ответа (200)

JSON
[
    {
        "id": 123,
        "name": "Опрос с Amo",
        "amocrm_is_active": true,
        "folder": { ... }
    }
]

AmoCRM: Настройки опроса

В API с 19.02.2026

Получение или сохранение настроек AmoCRM для конкретного опроса.

Получение: GET /amocrm/quiz/{id}/settings
Сохранение: POST /amocrm/quiz/{id}/settings

Тело запроса для сохранения (JSON)

Поле Тип Обязательное Описание
settings object Да Настройки сопоставления: ключи deal, list, task, check, extra_fields
settings.deal.active array<int> Нет Идентификаторы воронок, в которые создавать сделки
settings.deal.status object Нет Стадия по каждой воронке: ключ — идентификатор воронки
settings.deal.title, .bind, .subtype, .use_price object Нет Название сделки, привязка полей, подтипы, отправка суммы в бюджет
settings.list.active, .title, .bind, .subtype, .enum, .compId array / object Нет То же для контактов, компаний и каталогов
settings.task.active, .title, .type, .user array / object Нет То же для задач
settings.check boolean Нет Общий признак включённости
is_active boolean Нет Флаг активности интеграции

Тело проверяется по форме: значение не того типа даёт 422 с кодом validation_failed и разбором по полям в errors. Разделы, которых нет в наборе check, deal, list, task, extra_fields, отказом не считаются — они молча отбрасываются и в настройки не попадают.

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

Ответ Код Когда
422 validation_failed Тело не соответствует форме
400 pipeline_unknown Выбранной воронки нет в портале. В id — её идентификатор
400 status_mismatch Стадия не принадлежит своей воронке. В id — воронка, в status_id — стадия

Если справочники портала не прочитались (подписка не оплачена, amoCRM недоступна), сохранение не блокируется: иначе клиент не смог бы донастроить интеграцию, пока у него проблемы на стороне amoCRM.


Вебхуки опроса

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

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


54. Список вебхуков

В API с 08.09.2026

GET/quiz/{id}/webhooks

JSON
{
    "status": true,
    "quiz_id": 18547,
    "is_active": true,
    "items": [{"id": 50, "title": "Наша CRM", "url": "https://example.com/hook",
               "method": "post", "is_active": true, "incomplete": false, "hours": 0,
               "headers": [{"name": "Authorization", "value": "***"}]}]
}

55. Создать вебхук

В API с 08.09.2026

POST/quiz/{id}/webhooks

Поле Тип Обязательное Описание
title string Да Название, до 255 символов.
url string Да Адрес. Только публичный http(s): адрес закрытой сети отклоняется.
method string Да get, post, put, patch.
body array Нет Состав отправляемых данных.
body_naming array Нет Свои имена полей.
headers array Нет [{"name": "...", "value": "..."}]. Имя — только латиница, цифры и спецсимволы token из RFC 7230 (без пробела, двоеточия, не-ASCII), иначе 422: такой заголовок в запрос не ушёл бы.
incomplete boolean Нет Отправлять незавершённые ответы.
hours integer Нет Через сколько часов считать ответ незавершённым: 0, 1, 6, 12, 24.
is_active boolean Нет Сразу включить отправку. По умолчанию вебхук создаётся выключенным.

В ответе — webhook_id нового вебхука и полный список items.

Повторный вызов с тем же url и method вебхук не задваивает: приходит 400 с кодом webhook_exists и webhook_id уже существующего. Иначе приёмник начал бы получать по два запроса на каждый ответ.


56. Изменить вебхук

В API с 08.09.2026

POST/quiz/{id}/webhooks/{webhookId}

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

Неизвестный вебхук — 400 с кодом webhook_not_found.


57. Удалить вебхук

В API с 08.09.2026

DELETE/quiz/{id}/webhooks/{webhookId}


58. Включить или выключить вебхук

В API с 08.09.2026

POST/quiz/{id}/webhooks/{webhookId}/toggle

Поле Тип Обязательное
is_active boolean Да

59. Журнал доставки вебхука

В API с 08.09.2026

GET/quiz/{id}/webhooks/{webhookId}/logs

Параметр Тип Описание
page integer Страница, по умолчанию 1.
per_page integer 1–30, по умолчанию 20. В журнале лежат тела запросов и ответов, поэтому предел ниже обычного.
status string Только записи с этим статусом: sent, failed, queued. Без параметра — все. Другое значение — 422. С 2026-10-13.

В ответе total, page, per_page, last_page (с учётом status), counts и logs. counts — { "all": 200, "failed": 71, "queued": 0 } по всему журналу эндпоинта, от status и страницы не зависит. У каждой записи logs на верхнем уровне answer_id — какой ответ ушёл, null у тестового запроса. Поля counts и answer_id — с 2026-10-13. Причина отказа — detail.error_code (timeout, dns_failed, ssl_error, connection_failed, too_many_redirects, unsafe_url, http_error, unknown) и/или detail.http_code с response_body.

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


60. Досылка вебхука

В API с 08.09.2026

POST/quiz/{id}/webhooks/{webhookId}/logs/resend

Поле Тип Описание
log_id integer Одна запись журнала.
date_from date Y-m-d. Начало периода.
date_to date Y-m-d. Конец периода.

log_id вместе с периодом — 422.

Повтор уходит с текущими заголовками вебхука и телом, собранным заново по текущему набору полей и их именам (данные ответа — из снимка исходной отправки). Если ответ удалён, тело — сохранённое в журнале, заголовки всё равно текущие. В журнал записывается то, что ушло при повторе. Тело запроса вебхука, включая поля answer_id и is_complete, описано в разделе Webhooks.


Уведомления в Telegram и MAX

Тарифная опция мессенджера (telegram, max) плюс право integrations.


101. Мессенджер опроса

В API с 08.09.2026

Действие HTTP
Состояние GET /quiz/{id}/integrations/messenger/{messenger}
Действия POST /quiz/{id}/integrations/messenger/{messenger}

{messenger} — telegram или max; другое значение даёт 422 с кодом unknown_messenger.

Поле Тип Описание
action string activate, deactivate, delete, toggle_buttons, save_widgets, remove_recipient, test.
buttons_enabled boolean Для toggle_buttons. Кнопки под сообщением.
subject string Тема сообщения, до 70 символов.
hidden_widget_ids array UUID вопросов, которые не попадают в сообщение, до 500.
recipient_id string Для remove_recipient. У Telegram это номер чата, у MAX — идентификатор человека.
JSON
{
    "status": true, "quiz_id": 18547, "messenger": "telegram", "is_active": true,
    "subject": "Новая заявка", "buttons_enabled": true,
    "bot_url": "https://t.me/webask_bot?start=1f0c...",
    "recipients": [{"id": 123456789, "title": "Отдел продаж"}],
    "hidden_widget_ids": ["b3f1c2d4-..."]
}

Подключение делает человек. activate заводит интеграцию и выдаёт bot_url — по этой ссылке бота добавляют в чат или группу; пока этого не сделали, отправлять некуда. Получатели появляются сами, когда бота добавили.

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

test отправляет пробное сообщение всем подключённым получателям. Выключенная интеграция — 400 с кодом inactive, интеграция без получателей — 400 с кодом no_recipients, сбой отправки — 400 с кодом test_failed.

Опрос без подключённого мессенджера — 400 с кодом not_connected для всего, кроме activate.


Google Таблицы

Подключение остаётся в кабинете: там вход в аккаунт Google и выбор файла на Диске. Тарифная опция googleSheets плюс право integrations.


102. Выгрузка ответов в таблицу

В API с 08.09.2026

Действие HTTP
Состояние GET /quiz/{id}/integrations/google-sheets
Действия POST /quiz/{id}/integrations/google-sheets
Поле Тип Описание
action string activate, deactivate, delete, save_widgets, save_switchers, set_sync_mode, sync_now, export_all.
hidden_widget_ids array Обязателен для save_widgets, до 500. Вопросы, которые в таблицу не попадают.
enable_timestamp boolean Столбец со временем ответа.
enable_personal_data boolean Персональные данные респондента.
sync_mode string Для set_sync_mode: realtime, scheduled, manual.
schedule_hour, schedule_minute integer Обязательны при scheduled: 0–23 и 0–59.
export_mode string Для export_all: new_file, new_sheet, replace.
JSON
{
    "status": true, "quiz_id": 18547, "is_active": true,
    "table_title": "Ответы опроса", "table_url": "https://docs.google.com/...",
    "access": "ok", "requires_reconnect": false,
    "enable_timestamp": true, "enable_personal_data": false,
    "sync_mode": "scheduled", "schedule_hour": 9, "schedule_minute": 30,
    "last_synced_at": "2026-09-09 09:30:12", "hidden_widget_ids": []
}

access — состояние доступа к таблице. Чаще всего выгрузка замолкает именно из-за отозванного на стороне Google доступа, и тогда приходит requires_reconnect: true: переподключение делают в кабинете.

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

sync_now досылает всё, что ещё не уехало в таблицу; export_all выгружает накопившиеся ответы заново — новым файлом, новым листом или заменой прежнего.

Опрос без подключённой интеграции — 400 с кодом not_connected.


Zapier

Связки собираются на стороне Zapier — здесь только то, слушает ли он этот опрос. Права и тариф как во всём разделе: опция zapier плюс право integrations.


99. Zapier у опроса

В API с 08.09.2026

Действие HTTP
Состояние GET /quiz/{id}/integrations/zapier
Включить, выключить, отключить POST /quiz/{id}/integrations/zapier с полем action: activate, deactivate, delete
JSON
{"status": true, "quiz_id": 18547, "connected": true, "is_active": true, "hooks": 2}

hooks — сколько связок на стороне Zapier слушает опрос.

delete сносит и подписки: связка на стороне Zapier перестанет получать ответы, и собирать её придётся заново там же. В ответе — removed_hooks. Опрос без подключения — 400 с кодом not_connected.


Счётчики и пиксели

Google Аналитика, Яндекс.Метрика, пиксель VK и пиксель Meta. У каждого своя тарифная опция (googleStats, yaMetrika, vkPixel, fbPixel) плюс общее для раздела право integrations.


100. Счётчик опроса

В API с 08.09.2026

Действие HTTP
Состояние GET /quiz/{id}/integrations/counters/{service}
Запись, включение, выключение, отключение POST /quiz/{id}/integrations/counters/{service}

{service} — google, yandex, vk, fb. Другое значение — 422 с кодом unknown_service.

Поле Тип Описание
action string save, activate, deactivate, delete.
counter string Номер счётчика или пикселя, до 20 символов.
version string Только Google: ga4 или прежняя ua.
is_webvisor boolean Только Яндекс: запись действий посетителя.
JSON
{"status": true, "quiz_id": 18547, "service": "yandex", "counter": "87654321", "is_active": true}

Номер и признак включённости пишутся и в запись интеграции, и в версию опроса — рендер читает версию. Поэтому включённый счётчик действительно появляется на странице, а после delete копия в версии снимается и счётчик перестаёт вставляться.

Отключение ненастроенного счётчика — 400 с кодом not_connected.


Письма опроса

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


79. Настройки писем опроса

В API с 08.09.2026

GET/quiz/{id}/emails

Возвращает настройки, получателей копий (без кода подтверждения) и списки вопросов, исключённых из письма автору и из письма респонденту. Поле notifications — правила, сводка, события, напоминание и баллы (§124).


80. Шаблон письма

В API с 08.09.2026

POST/quiz/{id}/emails/template

Поля с приставкой owner_ — письмо автору, client_ — письмо респонденту: subject (до 500), letter (до 5000), use_default_tmpl, reply_to_address, send_promo_code, formatted_letter (HTML из редактора, до 50 000), raw_html + raw_enabled (полностью свой HTML, работает только со своим SMTP). Отдельно client_source — имя скрытой переменной, из которой берётся адрес респондента.


81. Какие вопросы не попадают в письмо

В API с 08.09.2026

POST/quiz/{id}/emails/questions

Поле Тип Описание
owner_excluded_questions array UUID вопросов, исключённых из письма автору.
client_excluded_questions array То же для письма респонденту.

Непереданный список не трогается — у двух писем исключения независимы. Переданный пустым означает «в письмо идут все вопросы».

UUID сверяется с виджетами черновика опроса: выдуманный или чужой идентификатор даёт 400 с кодом unknown_questions и списком в поле unknown. Раньше такой uuid записывался молча и ни на что не влиял.

Настроек писем у опроса ещё нет — 400 с кодом emails_not_initialized.


82. Включить или выключить письмо

В API с 08.09.2026

POST/quiz/{id}/emails/toggle

Поле Тип Обязательное Описание
type string Да owner или client.
enabled boolean Да

Письмо уже в этом состоянии — ответ 200 с unchanged: true: внутри сервис переключает состояние, а не выставляет его, и повторный вызов иначе вернул бы всё как было.


83. Получатели копий ответов

В API с 08.09.2026

Действие HTTP
Добавить POST /quiz/{id}/emails/recipients с полем email
Удалить DELETE /quiz/{id}/emails/recipients/{emailId}
Включить/выключить POST /quiz/{id}/emails/recipients/{emailId}/toggle
Подтвердить или переслать код POST /quiz/{id}/emails/recipients/{emailId}/confirm

Заведённый адрес начинает получать копии только после подтверждения: код уходит на сам адрес, а не выдаётся вызывающему. Подтверждение — action: "confirm" с полем confirmation_code; повторная отправка кода — action: "resend_code".


84. Своя почтовая служба аккаунта

В API с 08.09.2026

Требует отдельное право участника account_smtp: в настройках своей почты лежит пароль от почтового ящика аккаунта.

POST/workspace/{workspace_id}/smtp

Поле Тип Описание
action string show, logs, enable, disable, test.
limit, offset integer Для logs, до 100 записей.

Журнал приходит полем logs, рядом — total, limit, offset: имя то же, что у журналов интеграций и вебхуков.

test обращается к почтовому серверу и отвечает 200 с полем connection_ok: неудачная проверка — это её результат, а не сбой вызова.

Тариф: enable и test требуют тарифной опции smtp, без неё — 403 с кодом blocked_by_tariff и blocked_by_tariff: true. show, logs и disable работают на любом тарифе. На тарифе без smtp письма опросов уходят через сервис, даже если свой SMTP включён: настройка сохраняется и снова действует после перехода на тариф с опцией.

Заведение и правка настроек своей почты остаются в кабинете — API их не принимает.


124. Правила, сводка, события, напоминание, баллы

В API с 13.10.2026

POST/quiz/{id}/emails/notifications

Те же настройки, что раздел «Уведомления» в кабинете. Текущие значения — поле notifications в GET /quiz/{id}/emails (всегда полностью, с подставленными значениями по умолчанию).

Передаются только меняемые поля: чего нет в запросе, то не меняется. Объекты digest, events, client_reminder накладываются поверх текущих, null значит «не трогать». rules заменяется списком целиком.

Поле Значения По умолчанию
rules до 20 правил: id (строка до 32, уникальна, обязательна), name (до 100), is_active, match (all | any), conditions (до 10), email_ids, subject (до 255) []
rules[].conditions[] widget_id — question_uuid вопроса; option_id — код оператора логики; value — с чем сравнивать, до 1000 —
digest is_active, period (day | week), weekday (1–7), hour (0–23, пояс владельца аккаунта), email_ids выключено, week, 1, 9
events email_ids; milestone (is_active, every 2–100 000); closed (is_active); limit (is_active, percent 1–99); silence (is_active, days 1–90) всё выключено, 100, 90, 3
client_reminder is_active, delay_hours (1–168), subject (до 255) выключено, 1, ""
client_send_score boolean — «N из M» в стандартном письме респонденту false
client_send_correct_answers boolean — верно/неверно по вопросам там же false

email_ids — email_id из recipients; при отправке учитываются только подтверждённые адреса аккаунта, неизвестные id не ошибка. Значения value по типам вопросов, операторы и что делает сервер по каждому событию — как в кабинете.

Ответ 200: { "status": true, "quiz_id": 1, "notifications": { … } }. Значение вне границ, больше 20 правил или 10 условий — 422.


125. Журнал писем опроса

В API с 13.10.2026

GET/quiz/{id}/emails/logs?limit=20&offset=0

Письма опроса за последние 30 дней, новые сверху: owner, client, booking, rule, digest, event, reminder. Письмо, ещё стоящее в очереди, не видно.

JSON
{
  "status": true,
  "quiz_id": 1,
  "total": 42,
  "items": [
    { "id": 931, "kind": "client", "to": "ivan@mail.ru", "subject": "Спасибо за ответ",
      "status": "failed", "error": "Ящик получателя переполнен", "created_at": "2026-10-08T17:58:00+03:00" }
  ]
}

limit — 1–100 (по умолчанию 20), offset ≥ 0; иначе 422 с кодом validation_error. error — понятная причина для failed, null для sent и для неизвестной причины.

Отправить ещё раз: POST /quiz/{id}/emails/logs/{logId}/resend — только для failed, в журнале появится новая запись. 404 с кодом not_found — записи нет в журнале опроса за 30 дней; 422 с кодом not_failed, already_resent (запись уже отправляли повторно — повторяйте новую) или cannot_resend.


126. Пример письма

В API с 13.10.2026

POST/quiz/{id}/emails/{type}/test, type — owner | client.

Письмо в нынешнем виде (тема, шаблон, логотип, отправитель) с выдуманными ответами — на почту пользователя ключа, тема «Пример: …». Ответ 200 с sent_to. Опрос не опубликован — 422 с кодом not_published. Не чаще раза в минуту на пользователя — иначе 429 с кодом too_often; счётчик общий с кабинетом и MCP, отказ 422 его не тратит.


127. Участник аккаунта в получатели

В API с 13.10.2026

POST/quiz/{id}/emails/recipients/member с полем user_id

Добавляет адрес участника аккаунта в получатели копий ответов — сразу подтверждённым, без кода. Ответ 200: email_id, email, checked: true, is_active: true, is_active_booking: true.

Код Когда
404 not_member пользователь не участник аккаунта опроса
422 invite_pending участник не принял приглашение
422 already_added адрес уже в получателях опроса
403 blocked_by_tariff достигнут лимит адресов тарифа

Состояние e-mail рассылок

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


114. Раздел состояния рассылок

В API с 08.09.2026

GET/workspace/{workspace_id}/mailings

Параметр Тип Обязательное Описание
section string Да Что смотрим, список ниже.
campaign_id integer Для campaign и recipients
list_id integer Для contacts
search string Нет Отбор по названию или адресу.
statuses array Нет Статусы доставки для recipients; пустой список — все.
days integer Нет Окно для reputation, 1–365, по умолчанию 30.
limit, offset integer Нет До 200 записей.

Разделы: campaigns — список кампаний, campaign — одна кампания, recipients — получатели с результатом доставки, contact_lists — списки контактов со сводкой, contacts — контакты одного списка, templates — шаблоны писем, reputation — доля отказов и жалоб (по ней почтовые службы решают, пускать ли письма аккаунта дальше), balance — остаток писем на счету, settings — настройки рассылок, smtp_logs — журнал отправок.

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

Кампании или списка с таким идентификатором в аккаунте нет — 400 с кодом not_found и полем section: по нему видно, чего именно нет. Это отсутствие записи, а не сбой чтения.