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

API Reference

Веб-интерфейс предоставляет REST API на порту 8080. Все эндпоинты возвращают JSON.

Статус всех плееров.

Ответ:

[
{
"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": 0,
"static_delay_ms": 300,
"listen_port": 8928,
"version": "2.70.0",
"build_date": "2026-05-11"
}
]

Server-Sent Events поток. Браузер подключается один раз; сервер отправляет data: {...} при каждом изменении состояния устройства. Веб-интерфейс использует его вместо polling.

События группируются с debounce-окном 100 мс для предотвращения шторма событий при быстрых изменениях состояния (например, BT-переподключение). Начальный ответ содержит 2 КБ padding-комментарий для сброса буферов HA Ingress прокси.

GET /api/status/stream
Accept: text/event-stream
data: [{"player_name": "Колонка в гостиной", "playing": true, ...}]
data: [{"player_name": "Колонка в гостиной", "playing": false, ...}]

Структурированная диагностика: адаптеры, синки, D-Bus, статус каждого устройства.

{ "version": "2.28.2", "build_date": "2026-03-13" }

Эндпоинт проверки здоровья. Возвращает 200 OK с {"status": "ok"}. Полезен для Docker health checks и балансировщиков нагрузки.

CORS preflight эндпоинт. Возвращает 204 No Content с соответствующими CORS-заголовками.

Возвращает список устройств, сгруппированных по 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 }
]
}
]

Хронологическая шкала восстановления, построенная из событий здоровья устройств и запуска.

{
"summary": { "entry_count": 3 },
"entries": [
{ "timestamp": "2026-03-22T19:00:00+00:00", "severity": "warning", "label": "BT reconnect", "summary": "..." }
]
}

Скачать текущую шкалу восстановления как CSV-файл (sendspin-recovery-timeline-<timestamp>.csv).

Повторно запустить одну безопасную проверку (например, подключение Bluetooth, верификация аудио-синка).

Body:

{ "check_key": "bluetooth", "device_names": ["Колонка в гостиной"] }
ПолеТипОписание
check_keystringОбязательное. Идентификатор проверки для повторного запуска
device_namesstring[]Опциональное. Ограничить проверку указанными устройствами

Ответ:

{ "check_key": "bluetooth", "summary": "All devices connected", "status": "pass" }

Возвращает 400, если check_key не распознан.

Текущие рекомендации ассистента задержки из recovery assistant. Включает рекомендованное значение PULSE_LATENCY_MSEC и пояснения.

Сохранить рекомендуемое значение задержки Pulse в config.json. Требуется перезапуск для применения.

Body: { "pulse_latency_msec": 800 }

Ответ:

{
"success": true,
"pulse_latency_msec": 800,
"restart_required": true,
"summary": "Saved Pulse latency 800 ms. Restart the bridge to apply the new buffer.",
"latency_assistant": { }
}

Пауза/воспроизведение на всех плеерах.

Body: { "action": "pause" } или { "action": "play" }

Пауза или воспроизведение конкретной MA-группы. При action="play" использует MA REST API (если настроен), чтобы все участники группы возобновили воспроизведение синхронно.

Body: { "group_id": "abc123", "action": "pause" } — action: "pause" или "play"

Установить громкость на одном или нескольких устройствах. Поддерживает индивидуальный, групповой и мультитаргетный режимы.

Параметры тела запроса:

ПолеТипОписание
volumeintegerЦелевая громкость (0–100). Обязательное.
macstringЦелевое устройство по MAC-адресу
player_namestringЦелевое устройство по имени плеера
player_namesstring[]Несколько устройств по именам
group_idstringВсе устройства в указанной группе синхронизации MA
groupbooleanПри true используется пропорциональная group_volume MA для участников группы
force_localbooleanПри 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 }

Пауза или воспроизведение одного плеера. Команда отправляется через IPC в целевой подпроцесс, который передаёт её по WebSocket-соединению в MA.

Body: { "player_name": "Колонка в гостиной", "action": "pause" } — action: "pause" или "play"

Включить/выключить mute. При включённом MUTE_VIA_MA и подключённом MA команда mute маршрутизируется через MA API. В противном случае mute применяется напрямую через PulseAudio.

Body: { "mac": "AA:BB:CC:DD:EE:FF", "muted": true }

Recovery-действие: принудительно снять mute с PulseAudio sink-а устройства в обход MA-маршрутизации. Нужно, когда PA-sink оказался замьючен на системном уровне (например, после краша или рестарта), хотя application-level mute уже выключен — иначе колонка продолжает молчать.

Body: { "player_name": "Колонка в гостиной" }

Возвращает 404, если устройство не найдено; 400, если у него не сконфигурирован audio-sink; 500, если pactl не смог снять mute.

Отправить нативную транспортную команду Sendspin конкретному устройству. Обходит MA REST API для минимальной задержки — команда передаётся через канал Sendspin Controller WebSocket.

Body:

ПолеТипОписание
actionstringОбязательное. Одно из: play, pause, stop, next, previous, volume, mute, repeat_off, repeat_one, repeat_all, shuffle, unshuffle, switch
device_indexintegerОбязательное. Индекс устройства в списке активных (с нуля)
valueanyОпциональное. Для volume (0–100) или mute (boolean)

Возвращает 400, если действие невалидно или не поддерживается устройством.

Ответ: { "success": true }

Эти эндпоинты требуют настройки MA_API_URL и MA_API_TOKEN (заполняются автоматически через «Sign in with Home Assistant» в режиме аддона, или задаются вручную).

Обнаружение серверов Music Assistant в сети через mDNS. Возвращает список найденных серверов.

Ответ:

{ "success": true, "servers": [{ "url": "http://192.168.1.10:8095", "name": "Music Assistant" }] }

Аутентификация с MA по логину и паролю. Поддерживает несколько провайдеров авторизации (ma, ha, ha-via-ma).

Body:

{ "ma_url": "http://192.168.1.10:8095", "username": "user", "password": "pass", "provider": "ma" }
ПолеОписание
ma_urlURL сервера MA (опционально, если уже настроен)
usernameИмя пользователя MA или HA
passwordПароль
providerПровайдер авторизации: "ma" (встроенный MA), "ha" (HA через MA OAuth), "ha-via-ma" (HA credentials через MA)

Ответ: { "success": true, "url": "...", "username": "...", "message": "..." }

Возвращает URL OAuth-авторизации через Home Assistant для входа через браузер.

Ответ: { "auth_url": "http://haos:8123/auth/authorize?..." }

Создаёт 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." }

Возвращает MA-группы синхронизации, обнаруженные через MA REST API. Пустой список, если MA API не настроен или обнаружение ещё не выполнялось.

[
{
"id": "ma-syncgroup-abc123",
"name": "Sendspin BT",
"members": [
{ "id": "...", "name": "Гостиная", "state": "playing", "volume": 48, "available": true }
]
}
]

Аутентификация через 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 для продолжения процесса.

Повторное обнаружение MA-групп без перезапуска бриджа. Считывает текущие MA_API_URL / MA_API_TOKEN из config.json.

Ответ:

{ "success": true, "syncgroups": 2, "mapped_players": 3, "groups": [{"id": "...", "name": "Sendspin BT"}] }

Текущие данные о воспроизведении из 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"
}

Команда управления воспроизведением для активной 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Опционально — целевая группа; без этого поля используется первая активная группа

Дамп состояния 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"]
}

Перезагрузить компоненты MA (учётные данные, WebSocket-монитор, кэш syncgroup) без перезапуска бриджа. Считывает текущие MA_API_URL / MA_API_TOKEN из config.json и запускает повторное обнаружение групп.

Ответ (202):

{
"success": true,
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "running",
"monitor_reloaded": true
}

Проксирование обложек MA через бридж, чтобы веб-интерфейс использовал same-origin URL изображений (избегая CORS-проблем).

Query-параметры:

ПараметрТипОписание
urlstringОбязательное. Путь или полный URL обложки на сервере MA
sigstringОбязательное. HMAC-подпись для защиты от SSRF

Возвращает бинарные данные обложки с оригинальным Content-Type (например, image/jpeg). Bearer-токен MA добавляется только при запросе к серверу MA. Возвращает 400 для невалидных URL или подписей, 413 для изображений больше 10 МБ.

Принудительное переподключение BT устройства.

Body: { "mac": "AA:BB:CC:DD:EE:FF" }

Запустить процедуру паринга (~25 сек). Устройство должно быть в режиме паринга.

Body: { "mac": "AA:BB:CC:DD:EE:FF", "adapter": "hci0" }

Переключить режим управления (Release/Reclaim).

Body: { "player_name": "Гостиная", "enabled": false }

Запускает фоновое сканирование BT-устройств (~10 сек). Возвращает ответ немедленно.

Ответ: { "job_id": "550e8400-e29b-41d4-a716-446655440000" }

Опрос результатов сканирования.

Ответ при выполнении:

{ "status": "running" }

Ответ после завершения:

{
"status": "done",
"devices": [
{ "mac": "AA:BB:CC:DD:EE:FF", "name": "JBL Flip 5" }
]
}

Ответ при ошибке:

{ "status": "done", "error": "Scan failed: bluetoothctl timed out" }

Список доступных BT-адаптеров.

Список спаренных устройств по каждому адаптеру.

Удалить (распарить) устройство из стека BlueZ.

Body: { "mac": "AA:BB:CC:DD:EE:FF" }

Ответ: { "ok": true, "mac": "AA:BB:CC:DD:EE:FF" }

Подробная информация bluetoothctl info для устройства: статус паринга, доверия и подключения.

Body: { "mac": "AA:BB:CC:DD:EE:FF" }

Ответ:

{
"mac": "AA:BB:CC:DD:EE:FF",
"name": "Колонка в гостиной",
"alias": "Колонка в гостиной",
"paired": "yes",
"bonded": "yes",
"trusted": "yes",
"connected": "yes",
"icon": "audio-card",
"raw": ["Device AA:BB:CC:DD:EE:FF ...", "..."]
}

Отключить Bluetooth-устройство без удаления паринга.

Body: { "mac": "AA:BB:CC:DD:EE:FF" }

Ответ: { "ok": true, "mac": "AA:BB:CC:DD:EE:FF" }

Включить или выключить питание Bluetooth-адаптера.

Body:

ПолеТипОписание
adapterstringИдентификатор адаптера (hci0, hci1 или MAC-адрес). Пустое = адаптер по умолчанию
powerbooleantrue — включить, false — выключить (по умолчанию: true)

Ответ: { "ok": true, "power": true }

Разбудить устройство из режима ожидания (переподключает Bluetooth и перезапускает подпроцесс демона).

Body: { "player_name": "Колонка в гостиной" }

Возвращает 409, если устройство не находится в режиме ожидания.

Ответ: { "success": true, "message": "Device waking from standby" }

Перевести устройство в режим ожидания (отключает Bluetooth и переключает подпроцесс демона на null-синк). Снижает энергопотребление неактивных колонок.

Body: { "player_name": "Колонка в гостиной" }

Возвращает 409, если устройство уже в режиме ожидания.

Ответ: { "success": true, "message": "Device entering standby" }

Удалить устройство и переподключить с нуля. Выполняется асинхронно: удаление → перезагрузка питания → сканирование → паринг → доверие → подключение.

Body:

ПолеТипОписание
macstringОбязательное. MAC-адрес устройства
adapterstringОпциональное. Идентификатор адаптера (hci0 или MAC-адрес)

Возвращает 409, если другая Bluetooth-операция уже выполняется.

Ответ: { "job_id": "550e8400-e29b-41d4-a716-446655440000" }

Опрос результата сброса и переподключения.

Ответ (выполняется): { "status": "running" }

Ответ (завершено):

{ "status": "done", "success": true, "connected": true, "mac": "AA:BB:CC:DD:EE:FF" }

Спарить новое Bluetooth-устройство по MAC-адресу (существующий клиент бриджа не требуется). Используется для устройств, обнаруженных при сканировании, но ещё не добавленных в конфигурацию.

Body:

ПолеТипОписание
macstringОбязательное. MAC-адрес устройства
adapterstringОпциональное. Идентификатор адаптера

Возвращает 409, если другая Bluetooth-операция уже выполняется.

Ответ: { "job_id": "550e8400-e29b-41d4-a716-446655440000" }

Опрос результата автономного паринга.

Ответ (выполняется): { "status": "running" }

Ответ (завершено): { "status": "done", "success": true, "mac": "AA:BB:CC:DD:EE:FF" }

Сгенерировать диагностический пакет для bug report. Возвращает JSON-объект с замаскированной системной информацией, состоянием устройств, последними логами, Bluetooth/audio-диагностикой и helper-текстом для GitHub issue.

Текущий ответ включает:

  • markdown_short — компактное Markdown summary для issue body
  • text_full — полный скачиваемый plain-text report
  • suggested_description — редактируемое описание, собранное на основе диагностики
  • report — замаскированный structured payload с диагностикой

Поле suggested_description предназначено для bug-report dialog в web UI. Оно кратко суммирует recent issue-worthy logs, состояние Bluetooth/устройств, здоровье subprocess/daemon, D-Bus/bluetoothd и статус MA connectivity без раскрытия секретов.

Возвращает {"available": true|false} — настроен ли на этом мосту GitHub-App прокси для отправки issue. Web UI использует этот флаг, чтобы решить, показывать ли кнопку «Отправить отчёт» пользователям без учётки GitHub.

Создаёт GitHub issue через App-прокси от имени пользователя без учётки GitHub. Требует настроенный прокси (см. /api/bugreport/proxy-available), иначе возвращает 503.

Тело запроса (JSON):

ПолеОписание
titleЗаголовок issue (5–200 символов)
descriptionОписание (10–5000 символов)
emailКонтактный email (должен содержать @)
diagnostics_textОпционально: замаскированный текст диагностики (обрезается до лимита GitHub в 65 536 символов)

Прокси применяет rate limit по IP клиента. Типовые ошибки: 400 (валидация), 429 (rate limit), 503 (прокси не настроен).

Последние строки лога приложения.

Query параметры:

  • lines — количество строк (по умолчанию 100)

Скачать полный лог сервиса (до 500 строк) как текстовый файл (sendspin-logs-<timestamp>.txt). Читает из journalctl, HA Supervisor или docker logs в зависимости от среды выполнения.

Перезапустить сервис.

Установить или изменить пароль веб-интерфейса. Недоступно в режиме HA addon (используйте управление пользователями HA).

Body: { "password": "mysecretpassword" } (минимум 8 символов)

Ответ: { "success": true }

Изменить уровень логирования немедленно и сохранить в config.json. Изменение распространяется на все подпроцессы — перезапуск не нужен.

Body: { "level": "debug" }"info" или "debug"

Ответ: { "success": true, "level": "DEBUG" }

Опрос результата асинхронной проверки обновлений.

Ответ (выполняется): { "status": "running", "channel": "stable" }

Ответ (завершено):

{ "success": true, "update_available": true, "tag": "v2.28.2", "version": "2.28.2", "current_version": "2.28.1" }

Текущая конфигурация из config.json.

Сохранить конфигурацию.

Body: JSON объект с полями конфигурации (см. раздел Настройка).

Скачать текущий config.json как файл-вложение. Ответ содержит заголовок Content-Disposition с именем файла, включающим метку времени (например, config-2026-03-15T10-30-00.json).

Загрузить файл 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" }

Валидация конфигурации без сохранения. Возвращает ошибки, предупреждения и нормализованную конфигурацию.

Body: Полный или частичный JSON-объект конфигурации.

Ответ (200 — валидно):

{
"valid": true,
"errors": [],
"warnings": [{ "field": "BLUETOOTH_DEVICES[0].mac", "message": "..." }],
"normalized_config": { }
}

Ответ (400 — невалидно):

{
"valid": false,
"errors": [{ "field": "SENDSPIN_PORT", "message": "Invalid SENDSPIN_PORT: abc" }],
"warnings": [],
"normalized_config": { }
}

Получить предложения областей (areas) из Home Assistant с использованием временного HA-токена. Полезно для маппинга адаптеров к комнатам в UI. Работает только в режиме аддона или при доступности HA.

Body:

ПолеТипОписание
ha_tokenstringОбязательное. Действующий access-токен HA
adaptersobject[]Опциональное. Список объектов адаптеров для сопоставления с устройствами HA
include_devicesbooleanОпциональное. Включить детали устройств HA в ответ

Ответ:

{
"success": true,
"areas": [{ "area_id": "living_room", "name": "Гостиная" }],
"bridge_name_suggestions": ["Living Room Bridge"]
}

Страница входа. Автоматически определяет доступные методы аутентификации:

  • Режим аддона HA — login flow Home Assistant с поддержкой 2FA/TOTP
  • MA подключён — валидация учётных данных Music Assistant (или HA через MA)
  • Standalone — локальная парольная аутентификация (PBKDF2-SHA256)

Обработка формы входа. Проверяет учётные данные через определённый бэкенд, обеспечивает CSRF-защиту и применяет блокировку от перебора (настраивается через параметры BRUTE_FORCE_*).

При успехе устанавливает аутентифицированную сессию и перенаправляет на запрошенную страницу. При ошибке повторно отображает страницу входа с сообщением об ошибке.

Очистить аутентифицированную сессию и перенаправить на страницу входа.

Окно терминала
# Получить статус всех плееров
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"}'