Интеграции
Интеграции и письма
CRM и сопоставление полей, вебхуки, мессенджеры, таблицы, счётчики, письма опроса и своя почта
Состояние интеграций и журнал отправок
Права и тариф для всех методов этого раздела: тарифная опция самой интеграции
плюс право участника 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)
{
"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)
{
"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)
{
"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)
{
"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)
{"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)
{
"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)
{
"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)
{
"pipelines": [...],
"users": [...],
"task_types": [...],
"custom_fields": [...]
}AmoCRM: Списки
В API с 19.02.2026
Получает каталоги (списки) из AmoCRM.
GET/amocrm/lists
Аутентификация: Обязательна
Пример ответа (200)
{
"response": {
"items": [...]
}
}AmoCRM: Поля каталога
В API с 22.09.2026
Возвращает поля элементов одного каталога amoCRM. У элемента каталога свой набор полей — не такой, как у сделки, контакта или компании, поэтому для сопоставления нужен именно он.
GET/amocrm/catalogs/{id}/fields
Аутентификация: Обязательна
Отказы
Те же, что у GET /amocrm/account; прочие причины — 400
amocrm_catalogs_unavailable.
Пример ответа (200)
{
"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)
{
"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)
{
"status": true,
"linked": true
}AmoCRM: Опросы
В API с 19.02.2026
Возвращает список опросов пользователя с информацией об активности интеграции AmoCRM.
GET/amocrm/quiz
Аутентификация: Обязательна
Query параметры
Аналогичны GET /quiz (sort, order, limit, offset, folder_id).
Пример ответа (200)
[
{
"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
{
"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 — идентификатор человека. |
{
"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. |
{
"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 |
{"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 | Только Яндекс: запись действий посетителя. |
{"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. Письмо, ещё стоящее в очереди, не видно.
{
"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: по нему видно, чего именно нет. Это отсутствие
записи, а не сбой чтения.