API — обзор
Актуально для: SimpleTwo 0.9.x · Проверено: 07.09.2026
У платформы не один API, а несколько — по службам, и это не разрозненность, а следствие разделения плоскостей: у плоскости связи и плоскости управления разные требования к доступности, поэтому у них разные адреса и разные сроки жизни токенов.
| Служба | База | Что там |
|---|---|---|
| Координатор | https://s2.<домен>/v1 | вход и сессии, каталог, политики доступа, встречи, реестр узлов, консоль |
| Messaging | https://chat.s2.<домен>/v1 | разговоры и сообщения, звонки и сигналинг, присутствие, боты, вложения |
| Календарь | https://cal.s2.<домен>/v1 | календари, записи, приглашения, ICS и CalDAV |
Полная карта эндпоинтов каждой службы — в разделе Справочник: он собирается из кода, поэтому не отстаёт от релиза.
Аутентификация: пять разных вещей
Все пять ходят в одном заголовке Authorization: Bearer <токен> — и это единственное, что
у них общее. Права, срок жизни и способ получения различаются.
| Токен | Кому выдаётся | Как получить | Живёт |
|---|---|---|---|
| сессия | человеку в клиенте | POST /v1/auth/login или вход через SSO | коротко, продлевается POST /v1/auth/renew |
бот (bot_…) | боту или интеграции | администратором в консоли: Bots | до отзыва; каждый запрос в аудите, включая чтения |
| служебный | службе продукта (messaging → координатор) | из конфигурации при устано вке роли | до перевыпуска |
узел (X-Node-Token, не Bearer) | хосту с ролью | при подключении хоста join-командой | до отзыва хоста |
| приглашение | одноразовое, в пути URL | POST /admin/api/enroll | один обмен, затем 410 |
Три правила, о которые спотыкаются интеграции:
- Токен бота — не токен человека. Бот ограничен возможностями (capabilities) и списком разговоров: то, что видит сотрудник, боту может быть недоступно, и наоборот. Проверять свою интеграцию под сессией человека, а запускать под ботом — верный способ получить 403 в проде.
- 401 означает «продли», а не «повтори». На 401 нужно один раз сходить в
POST /v1/auth/renewи повторить запрос; повтор с тем же токеном даст тот же 401. - 403 намеренно накрывает и «нет такого», и «не ваше» — там, где различить их значило бы раскрыть каталог, который вызывающему не положено читать.
Версия протокола
Одно моното нное целое, PROTOCOL_VERSION, покрывает и HTTP-формы, и кадры сокета: это
один контракт, и день, когда они начнут версионироваться отдельно, — это день, когда клиент
сможет удовлетворить половину. Не semver: единственный вопрос, который кто-либо задаёт, —
«этот клиент старше того, что сервер требует», а это сравнение.
| Заголовок | Направление | Значение |
|---|---|---|
X-SimpleTwo-Protocol | сервер → клиент | что говорит эта служба |
X-SimpleTwo-Protocol-Min | сервер → клиент | самый старый клиент, который ещё обслуживается |
X-SimpleTwo-Client-Protocol | клиент → сервер | что говорит этот клиент |
Заголовки, а не поля в теле: клиент должен узнать, что он отстал, из вызова, который он и так делал — включая неудавшийся, а заголовок доживает до клиента даже с тем 4xx, чьё тело он не разберёт.
Три состояния, и все три существуют:
| Клиент относительно сервера | Сервер | Клиент |
|---|---|---|
| актуален | обслуживает | ничего |
отстал, но ≥ Min | обслуживает, считает по версиям | ненавязчивое «доступно обновление» |
ниже Min | отказ: client_too_old | блокирующий экран: эта сборка не говорит с этим сервером |
Средняя строка — самое важное. Без неё каждое изменение контракта — выбор между «сломать
молча» и «тащить алиас вечно», а алиас нельзя вывести из обращения: доказать, что последний
старый клиент исчез, невозможно. С ней у устаревания есть конец: поднять Min в назначенный
день, посмотрев на отчёт по популяции, после недель предупреждений в самом приложении.
Min сегодня равен 0 сознательно: все установленные сборки старше самого заголовка и
не сообщают ничего, что читается как версия 0. Планируя интеграцию, отправляйте
X-SimpleTwo-Client-Protocol — иначе вы попадёте в ту же нулевую группу и не получите
предупреждения, когда порог поднимут.
Ошибки
{ "code": "call_step_is_signalling",
"error": "This version of the app can no longer place calls — please update it." }
code— машиночитаемый, строчными через подчёркивание, никогда не переименовывается и не переиспользуется. Это идентификатор: переименование меняет то, что покажет более старый клиент.error— английское предложение, остаётся навсегда как запасной вариант для клиента, который кода не знает. Оно видно пользователю независимо от наших пожеланий: установленные клиенты показывают его дословно.
Полный перечень кодов — Коды ошибок, он генерируется из объявлений в службе.
Коды состояния несут смысл, и различать их обязательно:
| Код | Значит | Что делать |
|---|---|---|
| 400 | запрос неправильный или называет неизвестное | это баг: сообщить, не повторять |
| 401 | токена нет, истёк или отозван | продлить и повторить один раз |
| 403 | аутентифицирован и не имеет права | не повторять, это ответ |
| 404 | нет такого — или нет для этого вызывающего | считать отсутствующим |
| 409 | конфликт состояния (повторное вступление, занятое имя) | разрешить и повторить |
| 410 | форма ушла; сообщение называет замену | править клиент |
| 429 | ограничение частоты | отступить; на сокет не влияет |
События: один сокет
GET /v1/ws?token=…&device=… на хосте messaging. Один сокет на устройство, а не по одному
на разговор: порядок событий гарантирован только внутри соединения, а несколько соединений
одного устройства — это гонка, которую нельзя поч инить на клиенте.
Формы кадров, порядок доставки и что делать при разрыве — в разделе «События» спецификации протокола; отдельная статья про сокет пишется следующей.
С чего начать интеграцию
- Получить токен бота в консоли (Settings → Bots) с нужными возможностями.
- Посмотреть, что уже умеют автоматизации: исходящие вебхуки и сценарии по событию закрывают большинство задач без опроса API, и их настраивает администратор в консоли без написания кода.
- Проверять
X-SimpleTwo-Protocol-Minв ответах и отправлять свою версию: интеграция — такой же клиент, и порогMinкасается её ровно так же, как мобильного приложения.