API
Диалоги, сообщения, контакты, каналы, подключение номеров и рассылки Lalexi из вашей CRM, сайта или учётной системы: адрес, личный токен, пространство, ошибки, страницы, лимиты и повторы без дублей.
API Lalexi даёт вашим системам — CRM, сайту, учётной системе — те же диалоги, сообщения, контакты и каналы, с которыми ваша команда работает в Lalexi. Через API можно подключать и отключать номера мессенджеров, загружать их историю, читать переписку и писать в неё, первым написать на новый номер, делать рассылки, вести контакты, менять статус, ответственного и метки диалога, смотреть расход сообщений и получать события вебхуками.
Каждый запрос выполняется от имени одного человека — владельца токена — и ровно с теми правами, которые у него есть в пространстве. Всё, что отправлено или изменено через API, записывается на него, как если бы он нажал кнопку в Lalexi сам.
Адрес
https://app.lalexi.com/v1Все пути ниже — относительно этого адреса: GET /me — это
GET https://app.lalexi.com/v1/me. Тела запросов и ответов — JSON
(Content-Type: application/json); файлы отправляются как
multipart/form-data.
Токен
API принимает личный токен доступа. Он есть у каждого участника
пространства: Настройки профиля → Токен доступа. Передавайте его в
заголовке Authorization:
curl https://app.lalexi.com/v1/me \
-H "Authorization: Bearer <ваш токен>"- Права токена — это ваши права. Токен администратора видит всё пространство, токен оператора — только его каналы и диалоги. Отдельных «ключей для интеграции» с другими правами нет: заведите для интеграции отдельного участника с нужной ролью, если не хотите, чтобы действия шли от вашего имени.
- Сброс токена в настройках профиля сразу отключает старый.
- Нет токена, неизвестный токен или не личный — ответ
401 invalid_api_key. - Храните токен как пароль: только на сервере, никогда в коде страницы или мобильного приложения. API рассчитано на запросы сервер–сервер и не отвечает браузерным запросам с чужих сайтов (CORS). Единственное исключение — сам этот сайт документации, чтобы в Справочнике работала кнопка Send.
Попробовать в браузере
Каждая страница Справочника — это ещё и рабочая форма.
Вставьте личный токен в поле Authorization, заполните параметры и нажмите Send: запрос
уйдёт прямо из браузера, ответ появится на той же странице. Это быстрее, чем собирать curl
руками, и сразу показывает настоящие поля настоящего ответа, а не только схему.
Два предупреждения, оба важные.
Запросы настоящие. Тестового режима у API нет: POST /dialogs правда напишет человеку в
мессенджер, POST /channels/{id}/disconnect правда отключит номер, DELETE /webhooks/{id} правда
удалит подписку. Щупать без последствий можно всё, что GET.
Токен остаётся в браузере. Страница запоминает его в хранилище браузера, чтобы не вставлять
каждый раз, и отправляет только на app.lalexi.com — ни на сервер документации, ни куда-то ещё.
На чужом или общем компьютере токен туда лучше не вставлять, а если вставили — очистите данные
сайта в браузере.
Пространство
Если вы состоите в нескольких пространствах, укажите нужное в заголовке
X-Workspace-Id каждого запроса. Номера ваших пространств и ваша роль в
каждом — в ответе GET /me (этому запросу заголовок не нужен):
curl https://app.lalexi.com/v1/channels \
-H "Authorization: Bearer <ваш токен>" \
-H "X-Workspace-Id: 7"С одним пространством заголовок можно не передавать.
| Ситуация | Ответ |
|---|---|
| Несколько пространств, заголовка нет | 400 workspace_required |
| Пространство не ваше | 404 workspace_not_found |
| Пространство приостановлено | 403 workspace_suspended |
| В пространстве выключен доступ по API | 403 api_disabled |
Номера и время
id диалога — это номер из его адреса в Lalexi, по нему удобно ссылаться на
диалог. У остальных объектов id — их собственный номер. Время — ISO 8601 в
UTC: 2026-10-27T09:30:00Z.
Ошибки
Любая ошибка приходит в одном виде:
{
"error": {
"code": "validation_failed",
"message": "The request is invalid.",
"details": { "text": ["is required"] }
}
}Решения в коде принимайте по code — это закрытый список. message — пояснение
для человека (на английском), его текст может меняться. details есть, только
когда есть что добавить: какие поля не прошли проверку, id уже существующего
контакта, цифры исчерпанного лимита.
code | HTTP | Что случилось |
|---|---|---|
invalid_json | 400 | Тело запроса — не JSON. |
workspace_required | 400 | Несколько пространств и нет X-Workspace-Id. |
invalid_api_key | 401 | Токена нет, он неизвестен или не личный. |
forbidden | 403 | Ваша роль этого не позволяет. |
workspace_suspended | 403 | Пространство приостановлено. |
api_disabled | 403 | Доступ по API в пространстве выключен. |
not_found | 404 | Объекта нет или он вам не виден (ответ одинаковый); так же отвечает неизвестный путь. |
workspace_not_found | 404 | Пространство не ваше. |
contact_exists | 409 | Контакт с таким телефоном, e-mail или идентификатором уже есть — его id в details.id. |
idempotency_in_progress | 409 | Запрос с этим Idempotency-Key ещё выполняется. |
duplicate | 409 | Такой же новый диалог (канал, получатель, текст) уже начат меньше минуты назад. |
message_limit_reached | 409 | Лимит сообщений пространства исчерпан — details.limit, details.used. |
channel_disconnected | 409 | Канал сейчас не подключён. |
validation_failed | 422 | Запрос неверен; details называет поля. |
invalid_cursor | 422 | Курсор повреждён. |
idempotency_key_reused | 422 | Этот Idempotency-Key уже использован с другим запросом. |
identifier_read_only | 422 | Идентификатор контакта из мессенджера менять нельзя. |
invalid_assignee | 422 | Этот человек не работает в канале диалога. |
invalid_team | 422 | Такой команды в пространстве нет. |
attachment_invalid | 422 | Файл слишком большой или его нельзя сохранить. |
channel_reply_only | 422 | Канал может только отвечать тем, кто написал первым. |
channel_cannot_start | 422 | Канал не умеет начинать диалог через API. |
probe_not_supported | 422 | Проверка номера работает только в каналах мессенджеров. |
template_not_found | 422 | Это не одобренный шаблон WhatsApp Business этого канала. |
invalid_recipient | 422 | Получатель не подходит для канала. |
recipient_rejected | 422 | Мессенджер отказал этому получателю. |
send_rejected | 422 | Мессенджер отказался принять сообщение. |
rate_limited | 429 | Превышен лимит запросов — подождите Retry-After секунд. |
internal_error | 500 | Сбой на нашей стороне. |
upstream_unavailable | 503 | Служба доставки сообщений не ответила; ничего не отправлено, можно повторить. |
Постраничная выдача
Списки отвечают так: {"data": [...], "next_cursor": "..."}. Параметр limit
— сколько элементов вернуть (от 1 до 100, по умолчанию 25). Чтобы получить
следующую страницу, передайте next_cursor из ответа в параметре cursor; на
последней странице next_cursor равен null. Курсор — непрозрачная строка:
не собирайте и не меняйте его.
Короткие списки — каналы, операторы, команды, метки, поля, вебхуки —
приходят целиком, с next_cursor: null.
Для синхронизации диалогов используйте GET /conversations?updated_since=…:
с этим параметром диалоги идут от самого раннего изменения к позднему, и
диалог, изменившийся во время обхода, не теряется, а уходит в конец.
Запомните updated_at последнего полученного диалога и передайте его в
updated_since в следующий раз.
Повтор без дублей
POST /conversations/{conversation_id}/messages и POST /dialogs принимают
заголовок Idempotency-Key — любую строку до 255 символов, например UUID или
номер записи в вашей системе:
curl https://app.lalexi.com/v1/conversations/1042/messages \
-H "Authorization: Bearer <ваш токен>" \
-H "Idempotency-Key: crm-order-1042-confirmation" \
-H "Content-Type: application/json" \
-d '{"text": "Ваш заказ отправлен."}'- Повтор с тем же ключом в течение 24 часов ничего не отправляет заново и возвращает первый ответ.
- Пока первый запрос выполняется, повтор получает
409 idempotency_in_progress. - Тот же ключ с другим телом —
422 idempotency_key_reused. - Ключи свои у каждого человека, пространства и адреса.
- Если первая попытка упала на нашей стороне (ответ 5xx), ключ освобождается и следующая попытка выполняется по-настоящему.
Так безопасно повторять запрос после обрыва связи или тайм-аута: сообщение не уйдёт дважды.
Лимиты запросов
| Что считается | Лимит |
|---|---|
| Запросы с одного токена | 300 в минуту |
POST /dialogs с одного токена | 20 в минуту |
GET /dialogs/probe с одного токена | 30 в минуту |
POST /webhooks/{id}/test с одного токена | 5 в минуту |
POST /channels и POST /channels/{id}/reconnect с одного токена, вместе | 10 в минуту |
Фоновая работа в мессенджере с одного токена, вместе: POST …/history-import, PUT …/chat-filter, POST …/chat-filter/allow, POST /broadcasts, POST /broadcasts/{id}/rephrase | 10 в минуту |
| Запросы с одного IP-адреса | 600 в минуту |
Сверх лимита — ответ 429 rate_limited с заголовком Retry-After: через
сколько секунд закончится текущая минута. Лимиты сообщений пространства —
отдельная история: они те же, что в Lalexi, и видны в GET /usage (только администраторам,
как страницы «Использование» и «Лимиты»).
Новый диалог
POST /dialogs пишет первым — то же, что кнопка «Новое сообщение». Он
работает в каналах, у которых capabilities.can_start_dialog равно true:
мессенджеры (по номеру телефона), e-mail (по адресу, с темой письма) и
WhatsApp Business (по номеру, с одобренным шаблоном). Боты и площадки
объявлений могут только отвечать — 422 channel_reply_only.
- Правило 60 секунд. В каналах мессенджеров тот же текст на тот же номер
из того же канала второй раз в течение минуты не уйдёт — ответ
409 duplicate. Это защита от двойного нажатия; для безопасных повторов используйтеIdempotency-Key. - Ответ
202со"status": "unknown"значит, что исход не успел вернуться: сообщение могло уйти. Не отправляйте его снова вслепую — сначала найдите диалог (GET /conversations?phone=…). Повтор с тем жеIdempotency-Keyвернёт тот жеunknownи второй раз не отправит. 503 upstream_unavailable— ничего не отправлено, повторять безопасно.GET /dialogs/probeзаранее проверяет, есть ли у номера аккаунт в мессенджере канала, ничего не отправляя.
Подключение номера
POST /channels с {"type": "whatsapp"} начинает подключение — то же, что
плитка канала в Настройки → Каналы → Добавить. В ответе connect_url:
страница Lalexi, где владелец номера сканирует QR-код, вводит код из
мессенджера или вставляет токен бота. Откройте её в браузере — в новой вкладке
или всплывающем окне. Ссылка живёт недолго: на каждую попытку берите новую.
Когда подключение закончено, канал появляется в GET /channels с
connected_by — это вы — и приходит вебхук channel.created. Подключать
номера может любой участник пространства, как и в Lalexi. Какие типы можно
подключить сейчас и что каждый умеет — GET /channel-types.
- Переподключение. Если у номера
statusсталreconnect_requiredилиdisconnected,POST /channels/{id}/reconnectдаёт такую же страницу для того же аккаунта. Канал, его id и диалоги остаются; по завершении статус станетconnected, придётchannel.status_changed. - Отключение.
POST /channels/{id}/disconnectотвязывает аккаунт. Канал и переписка остаются со статусомdisconnected. Отключённый номер можно спрятать вместе с его диалогами —PATCH /channels/{id}с{"hidden": true}; в списке его видно сinclude_hidden=true. - Подпись.
PATCH /channels/{id}с{"note": "Отдел продаж"}— подпись номера для команды. - Лимит подключений. Когда все подключения тарифа заняты, ответ
409 connection_limit_reachedсdetails.limitиdetails.used.
Администратор управляет любым номером, оператор — своими (теми, в которых работает).
История и фильтр чатов
Новый номер принимает все свои чаты с момента подключения. Чтобы получить и
прошлую переписку, запустите POST /channels/{channel_id}/history-import;
GET по тому же адресу показывает, сколько уже загружено. Повторный запуск
добавляет только недостающее.
Какие чаты номера попадают в пространство, решает фильтр:
PUT /channels/{channel_id}/chat-filter с mode — all (все), include
(только chat_ids) или exclude (все, кроме chat_ids). Id чатов берите из
GET /channels/{channel_id}/chats: список загружается в фоне, пока status
равен loading, повторите запрос через секунду-две. После сохранения фильтра
история разрешённых чатов загружается сама. POST /channels/{channel_id}/chat-filter/allow пропускает ещё один чат — по номеру
или id — не трогая остальные.
У ботов нет списка чатов и истории: там эти адреса отвечают
422 not_supported (смотрите capabilities.chat_list канала).
Рассылки
POST /broadcasts создаёт рассылку — черновик: ничего не уходит, пока вы не
вызовете POST /broadcasts/{id}/schedule. Каждая строка items уходит со
своего номера (channel_id) по очереди, с паузой delay_seconds (30–300
секунд) и не раньше scheduled_at. Номер должен быть вашим и уметь писать
первым (capabilities.broadcasts).
Строки, которые отправить нельзя — чужой номер, номер бота, неверный телефон,
пустой текст, — в рассылку не попадают и перечислены в errors с их
позицией (index). Если не годится ни одна, рассылка не создаётся —
422 invalid_items.
Дальше: GET /broadcasts/{broadcast_id}/items — получатели и их статусы,
PATCH /broadcasts/{broadcast_id}/items/{id} — другой текст или время для
одного получателя, POST /broadcasts/{id}/rephrase — варианты текста от ИИ по
промпту пространства (/broadcasts/rephrase-prompt), POST /broadcasts/{id}/cancel и DELETE /broadcasts/{id}. Рассылки пространства
видны всем его участникам, как в Lalexi. Менять рассылку — запускать, отменять,
удалять, править получателей — может администратор, а остальные только когда
затронутые строки уходят с их собственных номеров (иначе 403 forbidden).
Свои сообщения
Всё, что написано через API — POST /conversations/{conversation_id}/messages
и POST /dialogs, — помечено "via": "api" в ответах и в вебхуках. Передайте
свой external_id (до 255 символов), и он вернётся на том же сообщении. Так
интеграция отличает свои сообщения от написанных в Lalexi, с телефона или
контактом и не заносит их к себе второй раз.
Совместимость
Внутри v1 изменения только добавляются: новые адреса, новые необязательные
поля запросов, новые поля ответов, новые события вебхуков, новые коды ошибок,
новые значения открытых списков (типы каналов, типы вложений). Удаление и
переименование полей или смена их типа — только в новой версии, /v2.
Поэтому ваша интеграция должна пропускать незнакомые поля и значения, а неизвестный код ошибки обрабатывать по HTTP-статусу.
Спецификация
Весь API описан одним файлом OpenAPI 3.1 — его можно скачать:
https://docs.lalexi.com/openapi/public-api.yamlЭто тот же документ, из которого собран Справочник, так что они не могут разойтись. Файл подходит, чтобы сгенерировать клиент на своём языке, загрузить схему в Postman или Insomnia, или отдать её ИИ-агенту — тогда он будет собирать запросы по описанию, а не по догадкам.
Тот же файл открыт в Swagger UI — одна страница со всеми адресами сразу, привычная всем, кто работал с другими API. Там же можно отправить запрос: нажмите «Authorize», вставьте токен, раскройте адрес и «Try it out».
Генерация клиента, например:
npx @openapitools/openapi-generator-cli generate \
-i https://docs.lalexi.com/openapi/public-api.yaml \
-g typescript-fetch -o ./lalexi-clientДальше
Вебхуки
События, формат доставки, проверка подписи, повторы.
Swagger UI
Все адреса одной страницей: схемы, примеры и форма, чтобы отправить запрос.
Справочник
Каждый адрес API: параметры, тела запросов и ответов, ошибки — и форма, чтобы отправить запрос.
Битрикс24
Если ваша CRM — Битрикс24, переписку можно привести в неё готовой интеграцией, не собирая её на API.