API Reference
Веб-интерфейс предоставляет REST API на порту 8080. Все эндпоинты возвращают JSON.
Статус и мониторинг
Заголовок раздела «Статус и мониторинг»GET /api/status
Заголовок раздела «GET /api/status»Статус всех плееров.
Ответ:
[ { "player_name": "Колонка в гостиной", "mac": "AA:BB:CC:DD:EE:FF", "connected": true, "server_connected": true, "bluetooth_connected": true, "bluetooth_since": "2026-03-05T10:00:00", "server_since": "2026-03-05T10:00:01", "playing": true, "volume": 48, "muted": false, "current_track": "Song Title", "current_artist": "Artist Name", "audio_format": "flac 48000Hz/24-bit/2ch", "connected_server_url": "ws://192.168.1.10:8928/sendspin", "bluetooth_mac": "AA:BB:CC:DD:EE:FF", "bluetooth_adapter": "C0:FB:F9:62:D6:9D", "bluetooth_adapter_name": "Адаптер в гостиной", "bluetooth_adapter_hci": "hci0", "has_sink": true, "sink_name": "bluez_sink.AA_BB_CC_DD_EE_FF.a2dp_sink", "bt_management_enabled": true, "ma_connected": true, "group_id": "abc123", "group_name": "Sendspin BT", "sync_status": "In sync", "sync_delay_ms": -600, "static_delay_ms": -600, "listen_port": 8928, "version": "2.28.2", "build_date": "2026-03-11" }]GET /api/status/stream
Заголовок раздела «GET /api/status/stream»Server-Sent Events поток. Браузер подключается один раз; сервер отправляет data: {...} при каждом изменении состояния устройства. Веб-интерфейс использует его вместо polling.
События группируются с debounce-окном 100 мс для предотвращения шторма событий при быстрых изменениях состояния (например, BT-переподключение). Начальный ответ содержит 2 КБ padding-комментарий для сброса буферов HA Ingress прокси.
GET /api/status/streamAccept: text/event-stream
data: [{"player_name": "Колонка в гостиной", "playing": true, ...}]data: [{"player_name": "Колонка в гостиной", "playing": false, ...}]GET /api/diagnostics
Заголовок раздела «GET /api/diagnostics»Структурированная диагностика: адаптеры, синки, D-Bus, статус каждого устройства.
GET /api/version
Заголовок раздела «GET /api/version»{ "version": "2.28.2", "build_date": "2026-03-13" }GET /api/health
Заголовок раздела «GET /api/health»Эндпоинт проверки здоровья. Возвращает 200 OK с {"status": "ok"}. Полезен для Docker health checks и балансировщиков нагрузки.
GET /api/preflight
Заголовок раздела «GET /api/preflight»CORS preflight эндпоинт. Возвращает 204 No Content с соответствующими CORS-заголовками.
GET /api/groups
Заголовок раздела «GET /api/groups»Возвращает список устройств, сгруппированных по MA-группам синхронизации. Устройства с одинаковым group_id объединяются в одну запись; одиночные плееры (без группы) отображаются отдельно с group_id: null.
[ { "group_id": "abc123", "group_name": "Sendspin BT", "avg_volume": 52, "playing": true, "members": [ { "player_name": "Гостиная", "volume": 48, "playing": true, "connected": true, "bluetooth_connected": true } ] }, { "group_id": null, "group_name": null, "avg_volume": 70, "playing": false, "members": [ { "player_name": "Спальня", "volume": 70, "playing": false, "connected": true, "bluetooth_connected": false } ] }]Управление воспроизведением
Заголовок раздела «Управление воспроизведением»POST /api/pause_all
Заголовок раздела «POST /api/pause_all»Пауза/воспроизведение на всех плеерах.
Body: { "action": "pause" } или { "action": "play" }
POST /api/group/pause
Заголовок раздела «POST /api/group/pause»Пауза или воспроизведение конкретной MA-группы. При action="play" использует MA REST API (если настроен), чтобы все участники группы возобновили воспроизведение синхронно.
Body: { "group_id": "abc123", "action": "pause" } — action: "pause" или "play"
POST /api/volume
Заголовок раздела «POST /api/volume»Установить громкость на одном или нескольких устройствах. Поддерживает индивидуальный, групповой и мультитаргетный режимы.
Параметры тела запроса:
| Поле | Тип | Описание |
|---|---|---|
volume | integer | Целевая громкость (0–100). Обязательное. |
mac | string | Целевое устройство по MAC-адресу |
player_name | string | Целевое устройство по имени плеера |
player_names | string[] | Несколько устройств по именам |
group_id | string | Все устройства в указанной группе синхронизации MA |
group | boolean | При true используется пропорциональная group_volume MA для участников группы |
force_local | boolean | При true обходит MA API и использует прямой PulseAudio (pactl) |
Если не указан ни один из параметров таргетирования (mac, player_name, player_names, group_id), громкость применяется ко всем устройствам.
Логика маршрутизации (при включённом VOLUME_VIA_MA и подключённом MA):
group: true— отправляетgroup_volumeодин раз на каждую уникальную группу синхронизации MA среди выбранных устройств. MA применяет пропорциональную дельту, сохраняя соотношения. Устройства, не входящие ни в одну группу, получают точное значение напрямую через PulseAudio.group: false(по умолчанию) — отправляетvolume_setкаждому устройству индивидуально через MA API.- Ответ возвращается сразу с
"via": "ma". Интерфейс обновляется, когда bridge_daemon получает эхо от MA (~500 мс).
Фоллбэк: если MA недоступен, VOLUME_VIA_MA отключён или указан force_local: true, громкость устанавливается напрямую через PulseAudio и статус обновляется мгновенно.
// Индивидуально{ "mac": "AA:BB:CC:DD:EE:FF", "volume": 75 }
// Группа (пропорционально для групп синхронизации, точно для одиночных){ "volume": 40, "group": true }
// Принудительно через pactl{ "mac": "AA:BB:CC:DD:EE:FF", "volume": 50, "force_local": true }POST /api/pause
Заголовок раздела «POST /api/pause»Пауза или воспроизведение одного плеера. Команда отправляется через IPC в целевой подпроцесс, который передаёт её по WebSocket-соединению в MA.
Body: { "player_name": "Колонка в гостиной", "action": "pause" } — action: "pause" или "play"
POST /api/mute
Заголовок раздела «POST /api/mute»Включить/выключить mute. При включённом MUTE_VIA_MA и подключённом MA команда mute маршрутизируется через MA API. В противном случае mute применяется напрямую через PulseAudio.
Body: { "mac": "AA:BB:CC:DD:EE:FF", "muted": true }
Интеграция с Music Assistant
Заголовок раздела «Интеграция с Music Assistant»Эти эндпоинты требуют настройки MA_API_URL и MA_API_TOKEN (заполняются автоматически через «Sign in with Home Assistant» в режиме аддона, или задаются вручную).
GET /api/ma/discover
Заголовок раздела «GET /api/ma/discover»Обнаружение серверов Music Assistant в сети через mDNS. Возвращает список найденных серверов.
Ответ:
{ "success": true, "servers": [{ "url": "http://192.168.1.10:8095", "name": "Music Assistant" }] }POST /api/ma/login
Заголовок раздела «POST /api/ma/login»Аутентификация с MA по логину и паролю. Поддерживает несколько провайдеров авторизации (ma, ha, ha-via-ma).
Body:
{ "ma_url": "http://192.168.1.10:8095", "username": "user", "password": "pass", "provider": "ma" }| Поле | Описание |
|---|---|
ma_url | URL сервера MA (опционально, если уже настроен) |
username | Имя пользователя MA или HA |
password | Пароль |
provider | Провайдер авторизации: "ma" (встроенный MA), "ha" (HA через MA OAuth), "ha-via-ma" (HA credentials через MA) |
Ответ: { "success": true, "url": "...", "username": "...", "message": "..." }
GET /api/ma/ha-auth-page
Заголовок раздела «GET /api/ma/ha-auth-page»Возвращает URL OAuth-авторизации через Home Assistant для входа через браузер.
Ответ: { "auth_url": "http://haos:8123/auth/authorize?..." }
POST /api/ma/ha-silent-auth
Заголовок раздела «POST /api/ma/ha-silent-auth»Создаёт MA API токен, используя HA сессионный токен. Доступно только в режиме аддона (запуск как HA addon с Ingress).
Body: { "ha_token": "<HA access token>", "ma_url": "http://192.168.1.x:8095" }
Процесс: Бридж подключается к HA WebSocket с предоставленным токеном, вызывает auth/current_user для получения информации о пользователе, затем отправляет JSONRPC запрос на MA Ingress endpoint с заголовками X-Remote-User-* для создания долгоживущего токена. Токен сохраняется в config.json и подключение к MA API устанавливается немедленно.
Ответ:
{ "success": true, "url": "http://192.168.1.x:8095", "username": "Renso", "message": "Connected to Music Assistant via Home Assistant." }GET /api/ma/groups
Заголовок раздела «GET /api/ma/groups»Возвращает MA-группы синхронизации, обнаруженные через MA REST API. Пустой список, если MA API не настроен или обнаружение ещё не выполнялось.
[ { "id": "ma-syncgroup-abc123", "name": "Sendspin BT", "members": [ { "id": "...", "name": "Гостиная", "state": "playing", "volume": 48, "available": true } ] }]POST /api/ma/ha-login
Заголовок раздела «POST /api/ma/ha-login»Аутентификация через HA с помощью логина и пароля, затем обмен HA токена на MA API токен. Используется в режиме Docker/LXC, когда MA работает как HA addon.
Body:
{ "ma_url": "http://192.168.1.10:8095", "username": "ha_user", "password": "ha_pass" }Ответ: { "success": true, "url": "...", "username": "...", "message": "Connected to Music Assistant via Home Assistant credentials." }
Поддерживает 2FA: если HA login flow требует MFA, ответ включает "step": "mfa" с flow_id для продолжения процесса.
POST /api/ma/rediscover
Заголовок раздела «POST /api/ma/rediscover»Повторное обнаружение MA-групп без перезапуска бриджа. Считывает текущие MA_API_URL / MA_API_TOKEN из config.json.
Ответ:
{ "success": true, "syncgroups": 2, "mapped_players": 3, "groups": [{"id": "...", "name": "Sendspin BT"}] }GET /api/ma/nowplaying
Заголовок раздела «GET /api/ma/nowplaying»Текущие данные о воспроизведении из MA. Возвращает {"connected": false} если MA-интеграция не активна.
{ "connected": true, "state": "playing", "track": "Song Title", "artist": "Artist Name", "album": "Album Name", "image_url": "http://...", "elapsed": 142.5, "elapsed_updated_at": "2026-03-05T10:01:30", "duration": 279, "shuffle": false, "repeat": "off", "queue_index": 3, "queue_total": 12, "syncgroup_id": "ma-syncgroup-abc123"}POST /api/ma/queue/cmd
Заголовок раздела «POST /api/ma/queue/cmd»Команда управления воспроизведением для активной MA-группы.
Body:
{ "action": "next", "syncgroup_id": "ma-syncgroup-abc123" }| Поле | Описание |
|---|---|
action | "next", "previous", "shuffle", "repeat" или "seek" |
value | Для shuffle: true/false. Для repeat: "off", "all", "one". Для seek: секунды (int) |
syncgroup_id | Опционально — целевая группа; без этого поля используется первая активная группа |
GET /api/debug/ma
Заголовок раздела «GET /api/debug/ma»Дамп состояния MA-интеграции для диагностики: ключи кэша now-playing, обнаруженные группы, ID плееров, живые ID очередей из MA WebSocket.
{ "cache_keys": ["ma-syncgroup-abc123"], "groups": [...], "clients": [{ "player_name": "Гостиная", "player_id": "...", "group_id": "abc123" }], "live_queue_ids": ["up_abc123def456"]}Bluetooth-управление
Заголовок раздела «Bluetooth-управление»POST /api/bt/reconnect
Заголовок раздела «POST /api/bt/reconnect»Принудительное переподключение BT устройства.
Body: { "mac": "AA:BB:CC:DD:EE:FF" }
POST /api/bt/pair
Заголовок раздела «POST /api/bt/pair»Запустить процедуру паринга (~25 сек). Устройство должно быть в режиме паринга.
Body: { "mac": "AA:BB:CC:DD:EE:FF", "adapter": "hci0" }
POST /api/bt/management
Заголовок раздела «POST /api/bt/management»Переключить режим управления (Release/Reclaim).
Body: { "player_name": "Гостиная", "enabled": false }
POST /api/bt/scan
Заголовок раздела «POST /api/bt/scan»Запускает фоновое сканирование BT-устройств (~10 сек). Возвращает ответ немедленно.
Ответ: { "job_id": "550e8400-e29b-41d4-a716-446655440000" }
GET /api/bt/scan/result/<job_id>
Заголовок раздела «GET /api/bt/scan/result/<job_id>»Опрос результатов сканирования.
Ответ при выполнении:
{ "status": "running" }Ответ после завершения:
{ "status": "done", "devices": [ { "mac": "AA:BB:CC:DD:EE:FF", "name": "JBL Flip 5" } ]}Ответ при ошибке:
{ "status": "done", "error": "Scan failed: bluetoothctl timed out" }GET /api/bt/adapters
Заголовок раздела «GET /api/bt/adapters»Список доступных BT-адаптеров.
GET /api/bt/paired
Заголовок раздела «GET /api/bt/paired»Список спаренных устройств по каждому адаптеру.
GET /api/logs
Заголовок раздела «GET /api/logs»Последние строки лога приложения.
Query параметры:
lines— количество строк (по умолчанию100)
POST /api/restart
Заголовок раздела «POST /api/restart»Перезапустить сервис.
POST /api/set-password
Заголовок раздела «POST /api/set-password»Установить или изменить пароль веб-интерфейса. Недоступно в режиме HA addon (используйте управление пользователями HA).
Body: { "password": "mysecretpassword" } (минимум 8 символов)
Ответ: { "success": true }
POST /api/settings/log_level
Заголовок раздела «POST /api/settings/log_level»Изменить уровень логирования немедленно и сохранить в config.json. Изменение распространяется на все подпроцессы — перезапуск не нужен.
Body: { "level": "debug" } — "info" или "debug"
Ответ: { "success": true, "level": "DEBUG" }
Конфигурация
Заголовок раздела «Конфигурация»GET /api/config
Заголовок раздела «GET /api/config»Текущая конфигурация из config.json.
POST /api/config
Заголовок раздела «POST /api/config»Сохранить конфигурацию.
Body: JSON объект с полями конфигурации (см. раздел Настройка).
GET /api/config/download
Заголовок раздела «GET /api/config/download»Скачать текущий config.json как файл-вложение. Ответ содержит заголовок Content-Disposition с именем файла, включающим метку времени (например, config-2026-03-15T10-30-00.json).
POST /api/config/upload
Заголовок раздела «POST /api/config/upload»Загрузить файл config.json. Принимает multipart/form-data с полем file, содержащим JSON-конфигурацию.
Загруженный файл проверяется как валидный JSON перед сохранением. Конфиденциальные ключи (AUTH_PASSWORD_HASH, SECRET_KEY, MA_API_TOKEN) сохраняются из текущей конфигурации и не перезаписываются загруженным файлом.
Ответ:
{ "success": true, "message": "Configuration uploaded successfully" }Ответ при ошибке (невалидный JSON):
{ "success": false, "error": "Invalid JSON in uploaded file" }Примеры использования
Заголовок раздела «Примеры использования»# Получить статус всех плееровcurl http://localhost:8080/api/status
# Подписаться на обновления в реальном времени (SSE)curl -N http://localhost:8080/api/status/stream
# Установить громкость 50% на конкретном устройствеcurl -X POST http://localhost:8080/api/volume \ -H 'Content-Type: application/json' \ -d '{"mac": "AA:BB:CC:DD:EE:FF", "value": 50}'
# Поставить на паузу все плеерыcurl -X POST http://localhost:8080/api/pause_all \ -H 'Content-Type: application/json' \ -d '{"action": "pause"}'
# Поставить на паузу конкретную MA-группуcurl -X POST http://localhost:8080/api/group/pause \ -H 'Content-Type: application/json' \ -d '{"group_id": "abc123", "action": "pause"}'
# Перейти к следующему треку (требует настройки MA API)curl -X POST http://localhost:8080/api/ma/queue/cmd \ -H 'Content-Type: application/json' \ -d '{"action": "next"}'
# Запустить BT-сканирование и опросить результатJOB=$(curl -s -X POST http://localhost:8080/api/bt/scan | python3 -c "import sys,json; print(json.load(sys.stdin)['job_id'])")curl http://localhost:8080/api/bt/scan/result/$JOB
# Получить диагностикуcurl http://localhost:8080/api/diagnostics | python3 -m json.tool
# Изменить уровень логированияcurl -X POST http://localhost:8080/api/settings/log_level \ -H 'Content-Type: application/json' \ -d '{"level": "debug"}'