Видеосервер 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-ключ.
Токены
/api/v1/auth/loginвход, application/x-www-form-urlencodedgrant_type=password&username=<логин>&password=<пароль>
→ 200 {"access_token":"...","refresh_token":"...","expires_in":1794067466,"token_type":"Bearer"}
/api/v1/auth/refreshновая пара токенов{"refresh_token":"..."}
/api/v1/auth/logoutвыход (ответ всегда успешный)/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-ключи
Постоянный ключ для интеграций, где неудобно хранить пароль и обновлять токены. Выпускается только по токену входа.
/api/v1/auth/keysвыпустить ключ{"name":"CRM","write":false}
→ 201 {"id":3,"name":"CRM","key":"vsk_...","write":false}
/api/v1/auth/keysмои ключи (сам ключ не показывается)/api/v1/auth/keys/{id}отозватьwrite:false (по умолчанию) — только чтение; write:true разрешает отправку команд. Ключ действует с правами владельца, не более 20 ключей на пользователя. Ключами нельзя выпускать другие ключи.Права доступа
Те же, что в веб-интерфейсе:
| Роль | Что видит |
|---|---|
| Администратор | все объекты и все компании |
| Управляющий | объекты дерева групп своей компании |
| Пользователь | только назначенные ему группы (с подгруппами) |
Чужой объект отвечает 404 — его существование не раскрывается. Команды доступны только администратору и только токену или ключу с правом записи (403 иначе).
Соглашения
- Идентификатор объекта (
id,unit_id) — строка: номер терминала, может начинаться с нуля ("0120040"). Не приводите к числу. - Время — unix-секунды, UTC.
- Постраничность:
pl— размер страницы (1–1000, по умолчанию 100),po— смещение. Ответ:{"items":[…],"paginationMetadata":{"totalCount":73,"startRow":0,"endRow":50}}. - Единицы: скорость — км/ч, пробег — км, координаты — градусы WGS-84.
Компании
/api/v1/companiesкомпании, видимые пользователю{"items":[{"id":1,"name":"Ромашка","inn":"7707083893"}]}
ИНН — 10 цифр (организация) или 12 (ИП); может быть пустым.
Объекты
/api/v1/unitsсписок доступных объектов| Параметр | Смысл |
|---|---|
fun | часть названия |
fim | часть номера терминала |
fgi | только объекты группы (id группы) |
unit_ids | номера через запятую (параметр можно повторять) |
incllsv | 1 — приложить последнее сообщение lastMsg |
pl, po | страница |
/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, пусто).
/api/v1/units/last-msgs/fullпоследние сообщения списка объектов{"unitIds":["0120040","018270814098"]} // пустой список — все доступные
/api/v1/units/{unit_id}/last-msg/pureпоследнее сообщение, нормализованное/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 (регистратор на связи, но спутников нет).
История
/api/v1/storage/messagesточки объекта за период| Параметр | Смысл |
|---|---|
unit_id * | номер терминала |
time_from *, time_to * | период, unix-секунды, не более 93 суток |
columns | какие поля оставить, через запятую (time всегда) |
return_type | json (по умолчанию) или 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 — сузьте период.
Команды
/api/v1/units/{unit_id}/commands/sendотправить текстовую команду{"text":"...","type":"tcp"}
→ 201 {"taskId":12,"historyRowId":12,"status":"sent"}
/api/v1/units/{unit_id}/commands/historyистория команд (pl, po)- Текст — до 1000 байт; объект должен быть на связи (
409иначе);502— регистратор не принял. - Статус
sentозначает «отправлено регистратору»; подтверждения исполнения нет. - История хранит только команды, отправленные через этот API.
Пользователи
Раздел повторяет /api/v1/users Gelios. «Клиент» Gelios соответствует у нас компании с её пользователями; создавать и менять пользователей может только администратор токеном или ключом с правом записи. Администратор сервиса видит всех пользователей, управляющий — пользователей своей компании, обычный пользователь — себя.
Создатель — поле creator — у каждого пользователя это объект {id, login, legalName} (у главного администратора — он сам: 1С читает creator.id у каждого элемента). Для администратора, который читает список, верхние записи клиентов (управляющие компаний) показываются как его прямые подчинённые: у них creator.id равен id его сессии, как у Gelios. subordinatesCount — сколько пользователей создал этот пользователь.
/api/v1/usersсписок (fusid, fusl, fuse, flnl, fusph, fcrid, fisa, fisbl, pl, po)/api/v1/users/{user_id}пользователь/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"},…}
- login — 3–40 символов: латиница, цифры,
_ . @ -; уникален (409, если занят). password — от 6 символов. - creatorId — кто создаёт. Если это администратор, создаётся новый клиент: компания с названием
legalName(если пусто — по логину) и первой группой объектов; такая компания уже есть — пользователь добавляется в неё. Если это сотрудник компании, пользователь попадает в его компанию. Создателем можно указать только того, кого вы видите; чужойcreatorIdотклоняется (400, «пользователь не найден»). - isAdmin:
true— управляющий компании (видит все её объекты и пользователей),false— обычный пользователь с доступом к корневым группам компании. Администраторов системы через API не создают. - inn — наше дополнение: ИНН компании (10 или 12 цифр с проверкой).
- Прочие поля Gelios (
billingInfo,extraInfo,smtpConfigи т. п.) принимаются и игнорируются: у нас нет биллинга и этих настроек.
/api/v1/users/{user_id}legalName, email, phone, login, password, isBlock, isAdmin/api/v1/users/{user_id}удалить (нельзя себя и администраторов)Заблокированный пользователь не может войти ни в API, ни в веб-интерфейс, его токены перестают действовать.
Доступ пользователя к объектам
/api/v1/users/{user_id}/accesses/unitsдоступные объекты/api/v1/users/{user_id}/accesses/units/groupsгруппы компании и уровень доступа (0 — нет)/api/v1/users/{user_id}/accesses/units/groups/{group_id}{"newAccess":1} — дать, 0 — забратьДоступ выдаётся по группам объектов (и только пользователям с role=user: управляющие видят всю компанию). PUT …/accesses/units/{unit_id} по одному объекту не поддерживается и отвечает 422.
Видео
Сводка о состоянии видео на объектах: сколько каналов, идёт ли поток, какова глубина архива, какие неисправности. Данные берутся из кэша сервера, регистраторы при запросе не опрашиваются.
/api/v1/video/unitsсводка по всем доступным объектам| Параметр | Смысл |
|---|---|
hasErrors | true — только объекты с ошибками, false — только без ошибок |
videoPresent | фильтр по полю videoPresent |
minArchiveDepth | глубина архива не меньше N суток |
pl, po | страница |
/api/v1/video/units/{unit_id}/statusсводка по объекту/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.
/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).
429 иначе). Если устройство не прислало видео за 15 секунд, поток закрывается с ошибкой 502. Нагрузка на регистратор и канал связи такая же, как при просмотре в веб-интерфейсе: один и тот же канал смотрят все зрители одним потоком от устройства.Снимки
/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 | сколько каналов отдают поток сейчас |
videoPresent | true — поток идёт; false — регистратор не на связи или сообщил о неисправности камеры; null — на связи, но поток не открыт (неизвестно) |
archive | known; 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 — на портале документации.