CRM: команды и операторы
Управление CRM на стороне рекламодателя: per-bot включение CRM, команды операторов
с их правами, сами операторы, шаблоны ответов и наборы, кастомные события
(постбэки операторов), статистика и надзор за диалогами. Это API владельца аккаунта
(/api/crm/*). Рабочее место оператора живёт отдельно на crm.altercpa.top — его API
(/op/*) в этот справочник не входит.
Все ответы — HTTP 200 с application/json; успех или ошибка указаны в теле, а не в
HTTP-статусе. Время возвращается в unix-секундах (0 = не задано).
Авторизация и тарифные гейты
Все 23 эндпоинта используют авторизацию по API-ключу или сессии дашборда
(?id={uid}-{key}) и не требуют активной платной подписки — так владелец с
истёкшей подпиской всё ещё может управлять CRM и выключить её по ботам, чтобы
аккуратно свернуться.
Наличие функции CRM на тарифе проверяется на сервере при каждом изменяющем действии,
а также на «тяжёлых» GET — статистике и списке диалогов. Лёгкие списки (bot/list,
team/list, operator/list, template/list, event/list) функции не требуют —
только владения ресурсом. Включение CRM по боту (bot.json с crm=1) требует функции;
выключение разрешено всегда.
Лимит мест операторов («ваш лимит мест операторов») проверяется при создании оператора
и при его включении (status=0); лимит соблюдается атомарно, при нехватке —
error: limit.
Параметры принимаются как query-строка, urlencoded-тело или JSON-тело (JSON
приоритетнее); списки (bots, sets) — JSON-массив или строка через запятую.
Сквозные коды ошибок: key (нет/неверный токен — клиент разлогинивается),
ban (пользователь заблокирован), access (ресурс не ваш / не найден),
func (неверные аргументы), db (ошибка базы), limit (лимит мест).
Коды этой страницы: crm (функция CRM не на тарифе — фронт предлагает апгрейд),
inuse (в команде ещё есть операторы), media (неверный путь/тип медиа). Тарифы CRM
описаны в разделе тарифы и оплата.
Боты с CRM
GET /api/crm/bot/list.json
Список ваших не удалённых ботов с их состоянием CRM (per-bot включение CRM). Порядок — по ID бота убыванию. Удалённые боты исключены. Функции CRM не требует.
| Параметр | Описание |
|---|
{
"status": "ok",
"data": [
{ "id": 42, "username": "myshopbot", "name": "My Shop", "crm": true },
{ "id": 37, "username": "leadsbot", "name": "Leads", "crm": false }
]
}| Ошибка | Значение |
|---|---|
db | Ошибка базы данных |
Включить/выключить CRM по боту
POST /api/crm/bot.json
Переключает per-bot включение CRM для одного вашего бота. Включение (crm=1)
требует функции CRM; выключение (crm=0) разрешено всегда — это «аварийный выход»
для владельца с истёкшей подпиской. Изменение сразу обновляет настройки бота на нашем
бэкенде.
| Параметр | Обязательный | Описание |
|---|---|---|
bot | ✓ | ID бота; должен быть вашим и не удалён. 0/отсутствует → func |
crm | ✓ | Желаемое состояние; должен присутствовать. Истинно: 1/true/yes/on |
{ "status": "ok", "bot": 42, "crm": true }| Ошибка | Значение |
|---|---|
func | bot не задан или crm отсутствует |
access | Бот не ваш или удалён |
crm | Включение без функции CRM на тарифе |
db | Ошибка базы данных |
Список команд
GET /api/crm/team/list.json
Ваши команды с шестью флагами прав и списком разрешённых ботов (allowlist). Порядок — по ID команды. Функции CRM не требует.
Флаги прав: leads_view (видеть карточку лида), leads_edit (менять лид),
confirm (подтверждать заявку на вступление, approveChatJoinRequest),
events (запускать кастомные события), reply (отправлять сообщения),
sticky (закрепление диалога за оператором).
| Параметр | Описание |
|---|
{
"status": "ok",
"data": [
{
"id": 3,
"name": "Поддержка",
"leads_view": true,
"leads_edit": true,
"confirm": true,
"events": false,
"reply": true,
"sticky": false,
"bots": [42, 37],
"created": 1718900000
}
]
}| Ошибка | Значение |
|---|---|
db | Ошибка базы данных |
Создать или изменить команду
POST /api/crm/team.json
Создаёт команду (при id=0) или меняет её имя и шесть флагов прав. При правке
понижение прав применяется к операторам команды сразу.
| Параметр | Обязательный | Описание |
|---|---|---|
id | 0/отсутствует — создать; иначе — править (команда должна быть вашей) | |
name | Имя команды | |
leads_view | Право: видеть лид | |
leads_edit | Право: менять лид | |
confirm | Право: подтверждать заявку на вступление | |
events | Право: запускать кастомные события | |
reply | Право: отправлять сообщения | |
sticky | Право: закрепление диалога |
{ "status": "ok", "id": 3 }При создании id — новый идентификатор; при правке — переданный id.
| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Правка не вашей команды |
db | Ошибка базы данных |
Удалить команду
POST /api/crm/team/del.json
Удаляет команду вместе с её allowlist ботов и шарами наборов шаблонов. Откажет, если в команде ещё есть операторы — сначала переназначьте или удалите их.
| Параметр | Обязательный | Описание |
|---|---|---|
team | ✓ | ID команды; должна быть вашей |
{ "status": "ok" }| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Команда не ваша |
inuse | В команде ещё есть операторы — переназначьте/удалите их |
db | Ошибка базы данных |
Заменить ботов команды
POST /api/crm/team/bots.json
Полностью заменяет allowlist ботов команды переданным набором. Чужие и удалённые боты молча отбрасываются; в ответе — проверенный сохранённый подмножество (порядок сохраняется). Пустой/отсутствующий список очищает allowlist.
| Параметр | Обязательный | Описание |
|---|---|---|
team | ✓ | ID команды; должна быть вашей |
bots | JSON-массив или строка через запятую с ID ботов |
{ "status": "ok", "bots": [42, 37] }| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Команда не ваша |
db | Ошибка базы данных |
Заменить наборы команды
POST /api/crm/team/sets.json
Полностью заменяет наборы шаблонов, расшаренные команде. Чужие наборы молча отбрасываются; в ответе — проверенный сохранённый подмножество. Пустой/отсутствующий список снимает все шары.
| Параметр | Обязательный | Описание |
|---|---|---|
team | ✓ | ID команды; должна быть вашей |
sets | JSON-массив или строка через запятую с ID наборов |
{ "status": "ok", "sets": [5, 8] }| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Команда не ваша |
db | Ошибка базы данных |
Список операторов
GET /api/crm/operator/list.json
Полный список операторов аккаунта плюс использование мест. Секрет никогда не
возвращается — открытый токен показывается только один раз при создании или сбросе.
used считает активных операторов (status=0), cap — ваш лимит мест операторов.
Функции CRM не требует.
status: 0 активен, 1 отключён. lead — право работы с лидами,
manage — право управления (подразумевает lead).
| Параметр | Описание |
|---|
{
"status": "ok",
"operators": [
{
"id": 11,
"name": "Анна",
"login": "anna",
"team": 3,
"status": 0,
"lead": true,
"manage": false,
"seen": 1718950000,
"created": 1718900000
}
],
"seats": { "used": 1, "cap": 15 }
}| Ошибка | Значение |
|---|---|
db | Ошибка базы данных |
Создать или изменить оператора
POST /api/crm/operator.json
Создаёт оператора (при id=0) или меняет его имя, логин, команду и флаги ролей.
При создании возвращается одноразовый открытый token (64 символа) — он
показывается один раз и хранится только в виде хэша; лимит мест соблюдается атомарно.
При правке токен не возвращается. manage подразумевает lead.
| Параметр | Обязательный | Описание |
|---|---|---|
id | 0/отсутствует — создать; иначе — править (оператор должен быть вашим) | |
name | Отображаемое имя | |
login | Логин-метка | |
team | ID команды; если не 0, должна быть вашей. 0 — без команды | |
manage | Роль: управление (подразумевает lead) | |
lead | Роль: работа с лидами; принудительно true, если задан manage |
Создание:
{ "status": "ok", "id": 11, "token": "9f3c…64-символьный-секрет…b2a1" }Правка:
{ "status": "ok", "id": 11 }| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Команда не ваша или правка не вашего оператора |
limit | Лимит мест исчерпан (при создании) |
db | Ошибка базы данных |
Включить/отключить оператора
POST /api/crm/operator/status.json
Включает (status=0) или отключает (status=1) оператора. Отключение возвращает
его диалоги в общий пул и удаляет его сессии. Включение заново занимает место
(лимит соблюдается атомарно).
| Параметр | Обязательный | Описание |
|---|---|---|
operator | ✓ | ID оператора; должен быть вашим |
status | ✓ | 1 — отключить (вернуть диалоги в пул + удалить сессии); иначе (0) — включить |
{ "status": "ok" }| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Оператор не ваш |
limit | Нет свободного места (при включении) |
db | Ошибка базы данных |
Сбросить доступ оператора
POST /api/crm/operator/reset.json
Перевыпускает секрет оператора: возвращает новый одноразовый открытый token
(64 символа, показывается один раз), старый доступ-линк аннулируется, все сессии
оператора удаляются.
| Параметр | Обязательный | Описание |
|---|---|---|
operator | ✓ | ID оператора; должен быть вашим |
{ "status": "ok", "token": "1a7e…новый-64-символьный-секрет…c4d9" }| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Оператор не ваш |
db | Ошибка базы данных |
Удалить оператора
POST /api/crm/operator/del.json
Удаляет оператора, возвращая его диалоги в общий пул и удаляя его сессии.
| Параметр | Обязательный | Описание |
|---|---|---|
operator | ✓ | ID оператора; должен быть вашим |
{ "status": "ok" }| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Оператор не ваш |
db | Ошибка базы данных |
Список шаблонов и наборов
GET /api/crm/template/list.json
Возвращает и наборы (sets, с указанием команд, которым они расшарены), и плоский
массив всех шаблонов (templates, каждый несёт свой set). Наборы — по ID набора;
шаблоны — по набору, порядку и ID. Функции CRM не требует.
media_type: 0 нет, 1 фото, 2 видео, 3 документ.
| Параметр | Описание |
|---|
{
"status": "ok",
"sets": [
{ "id": 5, "name": "Приветствия", "teams": [3], "created": 1718900000 }
],
"templates": [
{
"id": 21,
"set": 5,
"name": "Привет",
"text": "Здравствуйте! Чем помочь?",
"media": "",
"media_type": 0,
"sort": 0
}
]
}| Ошибка | Значение |
|---|---|
db | Ошибка базы данных |
Создать или изменить шаблон
POST /api/crm/template.json
Создаёт (при id=0) или меняет один шаблон ответа: текст и опциональное медиа,
по желанию привязанный к набору. Медиа проверяется на принадлежность вам;
пустой media сбрасывает media_type в 0.
| Параметр | Обязательный | Описание |
|---|---|---|
id | 0/отсутствует — создать; иначе — править (шаблон должен быть вашим) | |
set | ID набора; если не 0, должен быть вашим. 0 — без набора | |
name | Метка шаблона | |
text | Текст ответа | |
media | Путь к вашему медиа из media/upload; "" если нет | |
media_type | 1 фото, 2 видео, 3 документ (при заданном media) | |
sort | Порядок внутри набора |
{ "status": "ok", "id": 21 }При создании id — новый идентификатор; при правке — переданный id.
| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Набор не ваш или правка не вашего шаблона |
media | Неверный путь медиа или media_type |
db | Ошибка базы данных |
Удалить шаблон
POST /api/crm/template/del.json
Удаляет один шаблон (удаляется только если принадлежит вам). Отдельной
проверки владения нет: чужой или несуществующий id — молчаливый no-op, ответ всё
равно ok.
| Параметр | Обязательный | Описание |
|---|---|---|
template | ✓ | ID шаблона (удалится только если принадлежит вам) |
{ "status": "ok" }| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
db | Ошибка базы данных |
Создать или переименовать набор
POST /api/crm/set.json
Создаёт набор шаблонов (при id=0) или переименовывает его.
| Параметр | Обязательный | Описание |
|---|---|---|
id | 0/отсутствует — создать; иначе — переименовать (набор должен быть вашим) | |
name | Имя набора |
{ "status": "ok", "id": 5 }При создании id — новый идентификатор; при переименовании — переданный id.
| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Переименование не вашего набора |
db | Ошибка базы данных |
Удалить набор
POST /api/crm/set/del.json
Удаляет набор и его шары командам, разгруппировывая его шаблоны: они вынимаются из набора, само содержимое сохраняется.
| Параметр | Обязательный | Описание |
|---|---|---|
set | ✓ | ID набора; должен быть вашим |
{ "status": "ok" }| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Набор не ваш |
db | Ошибка базы данных |
Список кастомных событий
GET /api/crm/event/list.json
Определения кастомных событий одного бота (постбэки, которые запускают операторы), активные и отключённые. Порядок — по порядку и ID события. Гейт — только владение ботом, функции CRM этот список не требует.
status: 0 активно, 1 отключено.
| Параметр | Обязательный | Описание |
|---|---|---|
bot | ✓ | ID бота; должен быть вашим. 0/отсутствует → func |
{
"status": "ok",
"data": [
{
"id": 7,
"bot": 42,
"name": "Оплата получена",
"desc": "Менеджер подтвердил оплату",
"url": "https://track.example.com/postback?click={click}&goal=paid",
"sort": 0,
"status": 0,
"created": 1718900000
}
]
}| Ошибка | Значение |
|---|---|
func | bot не задан (0) |
access | Бот не ваш |
db | Ошибка базы данных |
Создать или изменить событие
POST /api/crm/event.json
Создаёт (при id=0) или меняет определение кастомного события. Кастомное событие —
это постбэк, поэтому url обязателен (иначе func). При создании проверяется
владение ботом; bot неизменяем при правке. Отключить можно либо disabled,
либо status=1.
| Параметр | Обязательный | Описание |
|---|---|---|
id | 0/отсутствует — создать; иначе — править (событие должно быть вашим) | |
bot | ✓ | ID бота (используется/проверяется только при создании; неизменяем при правке) |
name | Метка события для операторов | |
desc | Описание | |
url | ✓ | Шаблон URL постбэка; пустой → func |
sort | Порядок | |
disabled | Если истинно → status=1 (отключено) | |
status | Альтернатива: status=1 тоже отключает |
{ "status": "ok", "id": 7 }При создании id — новый идентификатор; при правке — переданный id.
| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
func | Пустой url |
access | Бот не ваш (при создании) или правка не вашего события |
db | Ошибка базы данных |
Удалить событие
POST /api/crm/event/del.json
Удаляет определение события (удаляется только если принадлежит вам). История
сработавших событий сохраняется. Отдельной проверки владения нет:
чужой id — молчаливый no-op.
| Параметр | Обязательный | Описание |
|---|---|---|
event | ✓ | ID события (удалится только если принадлежит вам) |
{ "status": "ok" }| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
db | Ошибка базы данных |
Статистика CRM
GET /api/crm/stats.json
Статистика CRM по всему аккаунту за период: объём, здоровье очереди, присутствие операторов и нагрузка по каждому оператору (по всем ботам, командам и операторам владельца). По умолчанию — последние 7 дней.
В volume системные заметки исключены (учитывается только обычная переписка). В
queue: open — всего открытых диалогов; unclaimed — в пуле, без оператора;
pending — открытые диалоги, ждущие ответа оператора (взятые или нет): это рабочий
«хвост», на который интерфейс показывает предупреждение (а не unclaimed);
oldest_unanswered — время самого старого неотвеченного входящего (по той же логике
«ждёт ответа», а не по непрочитанным). presence.online — операторы, активные за
последние 5 минут.
| Параметр | Обязательный | Описание |
|---|---|---|
from | Начало периода (unix); по умолчанию сейчас − 7 дней | |
to | Конец периода (unix); по умолчанию сейчас |
{
"status": "ok",
"from": 1718300000,
"to": 1718900000,
"volume": { "dialogs": 120, "messages_in": 540, "messages_out": 610 },
"queue": { "open": 8, "unclaimed": 3, "pending": 5, "oldest_unanswered": 1718890000 },
"presence": { "online": 2 },
"operators": [
{
"id": 11,
"name": "Анна",
"messages_sent": 210,
"dialogs_handled": 64,
"confirms": 18,
"leads_edited": 12,
"events_fired": 9
}
]
}| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
db | Ошибка базы данных |
Надзор за диалогами
GET /api/crm/dialog/list.json
Только для чтения: список открытых диалогов аккаунта, самые свежие сверху, постранично
по курсору before (курсор диалога). Тела сообщений не возвращаются (надзор,
не чат). Размер страницы — 50; more=true, когда страница заполнена.
operator: 0 — диалог в пуле (тогда operator_name пустой). pending: 1 — диалог
ждёт ответа оператора. last_in/last_out — время последнего входящего (от подписчика)
и последнего ответа оператора (0 — ещё ни разу не отвечали); created — время начала
диалога.
| Параметр | Обязательный | Описание |
|---|---|---|
before | Курсор диалога: вернёт диалоги с last_id меньше указанного. 0/отсутствует — первая страница | |
filter | Фильтр по статусу (применяется на стороне сервера ко всему аккаунту): pending — ждут ответа; unclaimed — в пуле, без оператора; assigned — взяты оператором | |
bot | Ограничить одним ботом (его ID) |
{
"status": "ok",
"dialogs": [
{
"id": 301,
"bot": 42,
"subscriber": 123456789,
"lead": 5001,
"name": "Иван",
"username": "ivan",
"operator": 11,
"operator_name": "Анна",
"unread": 2,
"pending": 1,
"last_id": 9870,
"last_in": 1718895000,
"last_out": 1718896000,
"created": 1718800000
}
],
"more": false
}| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
db | Ошибка базы данных |
Переназначить диалог
POST /api/crm/dialog/assign.json
Переназначает диалог на одного из ваших операторов или принудительно возвращает его
в общий пул (operator=0). Пишет системную заметку, и инбоксы операторов сразу
обновляются.
| Параметр | Обязательный | Описание |
|---|---|---|
dialog | ✓ | ID диалога; должен принадлежать вам |
operator | Целевой оператор (должен быть вашим); 0 или отсутствует — вернуть в пул |
{ "status": "ok", "operator": 11 }| Ошибка | Значение |
|---|---|
crm | Нет функции CRM на тарифе |
access | Диалог не ваш / не найден, либо целевой оператор не ваш |
db | Ошибка базы данных |