Перейти к основному содержимому

API — обзор

Актуально для: SimpleTwo 0.9.x · Проверено: 07.09.2026

У платформы не один API, а несколько — по службам, и это не разрозненность, а следствие разделения плоскостей: у плоскости связи и плоскости управления разные требования к доступности, поэтому у них разные адреса и разные сроки жизни токенов.

СлужбаБазаЧто там
Координаторhttps://s2.<домен>/v1вход и сессии, каталог, политики доступа, встречи, реестр узлов, консоль
Messaginghttps://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-командойдо отзыва хоста
приглашениеодноразовое, в пути URLPOST /admin/api/enrollодин обмен, затем 410

Три правила, о которые спотыкаются интеграции:

  1. Токен бота — не токен человека. Бот ограничен возможностями (capabilities) и списком разговоров: то, что видит сотрудник, боту может быть недоступно, и наоборот. Проверять свою интеграцию под сессией человека, а запускать под ботом — верный способ получить 403 в проде.
  2. 401 означает «продли», а не «повтори». На 401 нужно один раз сходить в POST /v1/auth/renew и повторить запрос; повтор с тем же токеном даст тот же 401.
  3. 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. Один сокет на устройство, а не по одному на разговор: порядок событий гарантирован только внутри соединения, а несколько соединений одного устройства — это гонка, которую нельзя починить на клиенте.

Формы кадров, порядок доставки и что делать при разрыве — в разделе «События» спецификации протокола; отдельная статья про сокет пишется следующей.

С чего начать интеграцию

  1. Получить токен бота в консоли (Settings → Bots) с нужными возможностями.
  2. Посмотреть, что уже умеют автоматизации: исходящие вебхуки и сценарии по событию закрывают большинство задач без опроса API, и их настраивает администратор в консоли без написания кода.
  3. Проверять X-SimpleTwo-Protocol-Min в ответах и отправлять свою версию: интеграция — такой же клиент, и порог Min касается её ровно так же, как мобильного приложения.