Видеосервер API

REST API для интеграций: список объектов, последнее положение, история треков, команды регистраторам и сводка по видео (каналы, архив, неисправности).

Базовый адрес: https://videoapi.glonassservice.ru. Все пути начинаются с /api/v1. Формат — JSON, кодировка UTF-8, только HTTPS.

Быстрый старт

# 1. получить токен
curl -s -d 'grant_type=password&username=ЛОГИН&password=ПАРОЛЬ' \
  https://videoapi.glonassservice.ru/api/v1/auth/login
# → {"access_token":"...","refresh_token":"...","expires_in":1794067466,"token_type":"Bearer"}

# 2. список объектов с последним положением
curl -s -H "Authorization: Bearer $TOKEN" \
  'https://videoapi.glonassservice.ru/api/v1/units?incllsv=1&pl=50'

# 3. сводка по видео: объекты с неисправностями
curl -s -H "Authorization: Bearer $TOKEN" \
  'https://videoapi.glonassservice.ru/api/v1/video/units?hasErrors=true'

Логин и пароль — те же, что для входа в веб-интерфейс. Для постоянных интеграций удобнее API-ключ.

Авторизация

Все методы, кроме входа и служебных адресов, требуют заголовок Authorization: Bearer <значение>. Значение — токен входа или API-ключ.

Токены

POST/api/v1/auth/loginвход, application/x-www-form-urlencoded
grant_type=password&username=<логин>&password=<пароль>

→ 200 {"access_token":"...","refresh_token":"...","expires_in":1794067466,"token_type":"Bearer"}
POST/api/v1/auth/refreshновая пара токенов
{"refresh_token":"..."}
POST/api/v1/auth/logoutвыход (ответ всегда успешный)
GET/api/v1/authкто я
{"id":1,"login":"ivan","name":"Иван","role":"manager","companyId":2,
 "companyName":"Ромашка","companyInn":"7707083893","viaApiKey":false,"canWrite":false}

Токены — JWT (HS256), как у Gelios. expires_in — момент истечения access-токена в unix-секундах (так же, как у Gelios, а не число секунд). access_token действует 1 час, refresh_token — 30 суток. Смена пароля или удаление пользователя сразу отзывает все его токены. После 5 неудачных входов с одного адреса вход временно блокируется (429).

API-ключи

Постоянный ключ для интеграций, где неудобно хранить пароль и обновлять токены. Выпускается только по токену входа.

POST/api/v1/auth/keysвыпустить ключ
{"name":"CRM","write":false}
→ 201 {"id":3,"name":"CRM","key":"vsk_...","write":false}
GET/api/v1/auth/keysмои ключи (сам ключ не показывается)
DELETE/api/v1/auth/keys/{id}отозвать
Ключ показывается один раз при создании, на сервере хранится только его хеш — сохраните сразу. write:false (по умолчанию) — только чтение; write:true разрешает отправку команд. Ключ действует с правами владельца, не более 20 ключей на пользователя. Ключами нельзя выпускать другие ключи.

Права доступа

Те же, что в веб-интерфейсе:

РольЧто видит
Администраторвсе объекты и все компании
Управляющийобъекты дерева групп своей компании
Пользовательтолько назначенные ему группы (с подгруппами)

Чужой объект отвечает 404 — его существование не раскрывается. Команды доступны только администратору и только токену или ключу с правом записи (403 иначе).

Соглашения

Компании

GET/api/v1/companiesкомпании, видимые пользователю
{"items":[{"id":1,"name":"Ромашка","inn":"7707083893"}]}

ИНН — 10 цифр (организация) или 12 (ИП); может быть пустым.

Объекты

GET/api/v1/unitsсписок доступных объектов
ПараметрСмысл
funчасть названия
fimчасть номера терминала
fgiтолько объекты группы (id группы)
unit_idsномера через запятую (параметр можно повторять)
incllsv1 — приложить последнее сообщение lastMsg
pl, poстраница
GET/api/v1/units/{unit_id}один объект
{"id":"018270814098","name":"АЗС","plate":"C868YM97","manufacturer":"72302","model":"MR9708E-B1",
 "iconType":"car","groupId":3,"groupName":"Одигитрия","companyId":2,
 "channelsCount":8,"online":true,"lastSeen":1794055748,
 "imei":"018270814098","hwManufacturer":"72302","hwType":"MR9708E-B1",
 "creator":{"id":8,"login":"hodegetria","legalName":"ООО Одигитрия"},
 "isBlock":false,"removed":false,"phone":"","unitType":"vehicle","currentUserAccess":7,
 "lastMsg":{…}}

channelsCount — число видеоканалов, online — регистратор на связи, lastSeen — время последнего пакета.

Создатель (владелец) объекта — creator — это верхний управляющий компании, которой принадлежит объект (компания определяется по группе объекта, в том числе вложенной в группу первого уровня). Если в компании нет управляющих, создателем указывается её самый ранний сотрудник; у объектов вне компаний — главный администратор. В creator всегда объект с id, login, legalName; id совпадает с id пользователя в разделе «Пользователи».

Поля imei (номер терминала), hwManufacturer, hwType, isBlock, removed, phone, unitType и currentUserAccess отдаются для совместимости с моделью объекта Gelios; значения isBlock, removed и phone у нас фиксированные (false, false, пусто).

POST/api/v1/units/last-msgs/fullпоследние сообщения списка объектов
{"unitIds":["0120040","018270814098"]}      // пустой список — все доступные
GET/api/v1/units/{unit_id}/last-msg/pureпоследнее сообщение, нормализованное
GET/api/v1/units/{unit_id}/last-msg/rawкак хранит навигация

Последнее сообщение (lastMsg)

ПолеСмысл
timeвремя, зафиксированное устройством
receivedAtвремя получения сервером
latitude, longitudeкоординаты
speed, courseскорость км/ч, курс в градусах
mileageпробег, км
fuelтопливо (если передаётся)
ignitionзажигание
satellitesчисло спутников
validесть фикс GNSS
alarmsсписок активных тревог
addressадрес по координатам

Положение — последняя точка с корректным фиксом, поэтому time может быть старше lastSeen (регистратор на связи, но спутников нет).

История

GET/api/v1/storage/messagesточки объекта за период
ПараметрСмысл
unit_id *номер терминала
time_from *, time_to *период, unix-секунды, не более 93 суток
columnsкакие поля оставить, через запятую (time всегда)
return_typejson (по умолчанию) или csv
limitне более точек: по умолчанию 10 000, максимум 50 000
curl -s -H "Authorization: Bearer $TOKEN" \
  'https://videoapi.glonassservice.ru/api/v1/storage/messages?unit_id=0120040&time_from=1762400000&time_to=1762486400&columns=latitude,longitude,speed'

Точки с фиксом, по возрастанию времени. Поля: time, latitude, longitude, altitude, speed, course, valid, ignition, satellites, rssi, mileage, fuel, alarmBits. Если точек больше limit, в ответе truncated:true — сузьте период.

Команды

Только администратор, токен или ключ с правом записи. Команды уходят на реальное оборудование — проверяйте текст.
POST/api/v1/units/{unit_id}/commands/sendотправить текстовую команду
{"text":"...","type":"tcp"}
→ 201 {"taskId":12,"historyRowId":12,"status":"sent"}
GET/api/v1/units/{unit_id}/commands/historyистория команд (pl, po)

Пользователи

Раздел повторяет /api/v1/users Gelios. «Клиент» Gelios соответствует у нас компании с её пользователями; создавать и менять пользователей может только администратор токеном или ключом с правом записи. Администратор сервиса видит всех пользователей, управляющий — пользователей своей компании, обычный пользователь — себя.

Создатель — поле creator — у каждого пользователя это объект {id, login, legalName} (у главного администратора — он сам: 1С читает creator.id у каждого элемента). Для администратора, который читает список, верхние записи клиентов (управляющие компаний) показываются как его прямые подчинённые: у них creator.id равен id его сессии, как у Gelios. subordinatesCount — сколько пользователей создал этот пользователь.

GET/api/v1/usersсписок (fusid, fusl, fuse, flnl, fusph, fcrid, fisa, fisbl, pl, po)
GET/api/v1/users/{user_id}пользователь
POST/api/v1/usersсоздать
{"login":"client1","password":"secret1","creatorId":1,"isAdmin":true,
 "legalName":"ООО Ромашка","email":"a@b.ru","phone":"+79001234567","isBlock":false,"inn":"7707083893"}
→ 201 {"id":12,"login":"client1","legalName":"ООО Ромашка","isAdmin":true,"role":"manager",
       "companyId":5,"companyName":"ООО Ромашка","inn":"7707083893","creator":{"id":1,"login":"admin"},…}
PATCH/api/v1/users/{user_id}legalName, email, phone, login, password, isBlock, isAdmin
DELETE/api/v1/users/{user_id}удалить (нельзя себя и администраторов)

Заблокированный пользователь не может войти ни в API, ни в веб-интерфейс, его токены перестают действовать.

Доступ пользователя к объектам

GET/api/v1/users/{user_id}/accesses/unitsдоступные объекты
GET/api/v1/users/{user_id}/accesses/units/groupsгруппы компании и уровень доступа (0 — нет)
PUT/api/v1/users/{user_id}/accesses/units/groups/{group_id}{"newAccess":1} — дать, 0 — забрать

Доступ выдаётся по группам объектов (и только пользователям с role=user: управляющие видят всю компанию). PUT …/accesses/units/{unit_id} по одному объекту не поддерживается и отвечает 422.

Видео

Сводка о состоянии видео на объектах: сколько каналов, идёт ли поток, какова глубина архива, какие неисправности. Данные берутся из кэша сервера, регистраторы при запросе не опрашиваются.

GET/api/v1/video/unitsсводка по всем доступным объектам
ПараметрСмысл
hasErrorstrue — только объекты с ошибками, false — только без ошибок
videoPresentфильтр по полю videoPresent
minArchiveDepthглубина архива не меньше N суток
pl, poстраница
GET/api/v1/video/units/{unit_id}/statusсводка по объекту
GET/api/v1/video/units/{unit_id}/channelsто же + список каналов
{"unitId":"022000130712","name":"Кран","online":false,"channelsCount":6,"channelsActive":0,
 "videoPresent":false,
 "archive":{"known":false,"depthDays":null,"depthFrom":null,"checkedAt":null},
 "errors":[{"code":"device_offline","message":"регистратор не на связи","channel":null}]}

Живое видео

Номер канала — от 1 до channelsCount объекта. Параметр stream: sub — дополнительный поток (по умолчанию, меньше трафика), main — основной. Регистратор должен быть на связи (409 иначе). Видео идёт кодеком H.264.

POST/api/v1/video/units/{unit_id}/channels/{channel}/liveзапросить видеопоток
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  'https://videoapi.glonassservice.ru/api/v1/video/units/018270814098/channels/1/live?stream=sub'

{"unitId":"018270814098","channel":1,"stream":"sub","expiresAt":1794057611,"ttl":300,
 "wsUrl":"wss://videoapi.glonassservice.ru/api/v1/video/live/1~0182…~sub~…",
 "httpUrl":"https://videoapi.glonassservice.ru/api/v1/video/live/1~0182…~sub~…",
 "snapshotUrl":"https://videoapi.glonassservice.ru/api/v1/video/snapshot/1~0182…~sub~…"}

Ссылки содержат короткоживущий билет: 5 минут на начало просмотра, после чего подключиться по ним нельзя (уже идущий поток не прерывается). Их можно отдавать плееру или браузеру, не раскрывая токен или ключ. Билет привязан к объекту, каналу и потоку, перестаёт действовать при смене пароля пользователя.

СсылкаЧто отдаёт
httpUrlнепрерывный «сырой» поток H.264 (Annex B), Content-Type: video/h264. Начинается с ключевого кадра. Открывается в VLC и ffplay -f h264 <ссылка>, пишется в файл через ffmpeg -f h264 -i <ссылка> -c copy out.mp4
wsUrlтот же поток по WebSocket (для веб-плееров). Каждое двоичное сообщение: 2 байта длительности кадра в миллисекундах (big-endian) + кадр H.264 Annex B. Текстовые сообщения — служебные JSON ({"info":…}, {"error":…})
snapshotUrlснимок канала в JPEG, см. ниже

Можно обойтись без билета: GET /api/v1/video/units/{unit_id}/channels/{channel}/live с заголовком Authorization отдаёт тот же поток (WebSocket при запросе с Upgrade, иначе HTTP).

Ограничения. До 8 одновременных потоков на пользователя (429 иначе). Если устройство не прислало видео за 15 секунд, поток закрывается с ошибкой 502. Нагрузка на регистратор и канал связи такая же, как при просмотре в веб-интерфейсе: один и тот же канал смотрят все зрители одним потоком от устройства.

Снимки

GET/api/v1/video/units/{unit_id}/channels/{channel}/snapshotJPEG-снимок канала
curl -s -H "Authorization: Bearer $TOKEN" -o cam1.jpg \
  'https://videoapi.glonassservice.ru/api/v1/video/units/018270814098/channels/1/snapshot'

Снимок делается из живого потока: сервер дожидается ключевого кадра и отдаёт его как image/jpeg (разрешение — как у выбранного потока, sub или main). Обычно 1–3 секунды; если видео на канале не открыто, до 15–25 секунд на запуск. Ссылка snapshotUrl из запроса видеопотока работает без заголовка авторизации, её можно подставить в <img src>. Ошибки: 409 — регистратор не на связи, 502 — устройство не прислало видео.

Поля сводки

ПолеСмысл
channelsCountколичество видеоканалов объекта
channelsActiveсколько каналов отдают поток сейчас
videoPresenttrue — поток идёт; false — регистратор не на связи или сообщил о неисправности камеры; null — на связи, но поток не открыт (неизвестно)
archiveknown; depthDays — глубина архива в сутках (0 — на регистраторе нет записей или, если регистратор на связи, он больше суток не отдаёт данные архива; тогда в errors код archive_empty); depthFrom — самые ранние сутки с записью (ГГГГ-ММ-ДД); checkedAt — когда определено
errorsактивные ошибки: code, message, channel (null — на весь объект)
channels[]только в /channels: channel, streaming, videoPresent, archiveDepthDays, archiveDepthFrom, errors

Коды ошибок

КодСмысл
device_offlineрегистратор не на связи
camera_faultрегистратор сообщил о неисправности камеры (тревога JT808, бит 11)
archive_emptyна регистраторе нет записей
archive_unknownглубина архива ещё не определена
Ограничения текущей версии. Глубина архива определяется на объект (в channels[] повторяется значение объекта). Тревоги видео по каналам (потеря сигнала, ошибка накопителя) пока не принимаются, поэтому соответствующих кодов нет. Записи архива через API — в следующих версиях.

Ошибки и лимиты

Тело ошибки — {"detail":"текст"}.

КодКогда
400, 422неверные параметры или тело запроса
401нет или недействителен токен/ключ, неверный логин или пароль
403нет права (команды без права записи, не администратор)
404объект не найден или недоступен
409объект не на связи (команды, видео, снимки)
429слишком много неудачных входов — подождите; слишком много одновременных потоков
502регистратор не принял команду или не прислал видео

Совместимость с Gelios

Формы запросов и ответов повторяют Gelios API (/api/v1/…, items + paginationMetadata, вход OAuth2 password): интеграции, написанные под Gelios, достаточно перенацелить на другой хост. Различия:

ЧтоGeliosЗдесь
Идентификатор объектачислострока — номер терминала, может начинаться с нуля
Времяпо-разномуunix-секунды (UTC)
Ошибки{"detail":…}так же
Тип команды (type)tcp / sms / …принимается; команда отправляется текстовым сообщением на регистратор
Геозоны, отчёты, уведомления, датчикиестьпока нет

Служебные адреса

Без авторизации: GET / (имя и версия), /healthcheck, /heartbeat. Описание API (openapi.json) и Swagger — на портале документации.