Summary
BluOS is an OS / music-management stack found in Bluesound, NAD Electronics, DALI Loudspeakers and other products. This spec covers the Custom Integration HTTP API plus the LSDP (Lenbrook Service Discovery Protocol) UDP discovery protocol documented for BluOS players, including playback, volume, queue, presets, browsing, grouping, reboot, doorbell chime, direct input and Bluetooth-mode control.
Transport
protocols:
- http
- udp
addressing:
port: 11000 # control API port for BluOS players (CI580 nodes use 11000/11010/11020/11030)
base_url: http://{player_ip}:{port} # control API base URL pattern
auth:
type: none # inferred: no login/password/auth procedure in source
Traits
# - queryable (inferred from /Status, /Volume, /SyncStatus, /Playlist, /Presets, /RadioBrowse)
# - routable (inferred from /AddSlave, /RemoveSlave player-grouping commands and /Play?url input switching)
# - levelable (inferred from /Volume?level, /Volume?db, /Volume?abs_db volume commands)
# - powerable (inferred from /reboot POST reboot command and Play/Pause/Stop transport state)
powerable: false # UNRESOLVED: explicit power on/off not documented; /reboot is soft reboot, not power control
queryable: true # inferred from query command examples
routable: true # inferred from input/group routing examples
levelable: true # inferred from volume control examples
Actions
- id: status
label: Playback Status (with optional long-polling)
kind: query
command: "GET /Status?timeout={seconds}&etag={etag-value}"
params:
- name: timeout
type: integer
description: Optional long-poll interval in seconds (recommended 100; min 60; never faster than 10).
- name: etag-value
type: string
description: Optional etag attribute from previous /Status response.
- id: sync_status
label: Player and Group Sync Status (with optional long-polling)
kind: query
command: "GET /SyncStatus?timeout={seconds}&etag={etag-value}"
params:
- name: timeout
type: integer
description: Optional long-poll interval in seconds (recommended 180).
- name: etag-value
type: string
description: Optional etag attribute from previous /SyncStatus response.
- id: volume_set_level
label: Set Volume (absolute 0-100)
kind: action
command: "GET /Volume?level={level}&tell_slaves={on_off}"
params:
- name: level
type: integer
description: Absolute volume 0..100.
- name: tell_slaves
type: integer
description: 0 = only this player; 1 = apply to entire group.
- id: volume_set_abs_db
label: Set Volume (absolute dB)
kind: action
command: "GET /Volume?abs_db={db}&tell_slaves={on_off}"
params:
- name: db
type: number
description: Absolute volume in dB.
- name: tell_slaves
type: integer
description: 0 = only this player; 1 = apply to entire group.
- id: volume_relative_db
label: Set Volume (relative dB delta)
kind: action
command: "GET /Volume?db={delta-db}&tell_slaves={on_off}"
params:
- name: delta-db
type: number
description: Positive or negative dB delta.
- name: tell_slaves
type: integer
description: 0 = only this player; 1 = apply to entire group.
- id: volume_up
label: Volume Up (typical +2 dB)
kind: action
command: "GET /Volume?db=2"
params: []
- id: volume_down
label: Volume Down (typical -2 dB)
kind: action
command: "GET /Volume?db=-2"
params: []
- id: mute_on
label: Mute On
kind: action
command: "GET /Volume?mute=1"
params: []
- id: mute_off
label: Mute Off
kind: action
command: "GET /Volume?mute=0"
params: []
- id: play
label: Play (resume or start)
kind: action
command: "GET /Play?seek={seconds}&id={trackid}"
params:
- name: seek
type: integer
description: Optional. Jump to position in seconds within current track.
- name: id
type: integer
description: Optional. Track id in the queue.
- id: play_url
label: Play Stream URL
kind: action
command: "GET /Play?url={encodedStreamURL}"
params:
- name: encodedStreamURL
type: string
description: URL-encoded stream URL.
- id: pause
label: Pause
kind: action
command: "GET /Pause"
params: []
- id: pause_toggle
label: Pause Toggle
kind: action
command: "GET /Pause?toggle=1"
params: []
- id: stop
label: Stop
kind: action
command: "GET /Stop"
params: []
- id: skip
label: Skip to Next Track
kind: action
command: "GET /Skip"
params: []
- id: back
label: Back (previous track or restart current)
kind: action
command: "GET /Back"
params: []
- id: shuffle
label: Shuffle Queue On/Off
kind: action
command: "GET /Shuffle?state={state}"
params:
- name: state
type: integer
description: 0 = disable shuffle; 1 = enable shuffle.
- id: repeat
label: Set Repeat Mode
kind: action
command: "GET /Repeat?state={state}"
params:
- name: state
type: integer
description: 0 = repeat queue; 1 = repeat track; 2 = repeat off.
- id: radio_action
label: Streaming Radio Station Action (skip/back/love/ban)
kind: action
command: "GET /Action?service={service-name}&{action-name}={action-id}"
params:
- name: service-name
type: string
description: Service id (e.g. Slacker).
- name: action-name
type: string
description: One of skip, back, love, ban (with the URL provided by /Status action element).
- id: playlist_list
label: List Play Queue Tracks (paginated)
kind: query
command: "GET /Playlist?start={first}&end={last}"
params:
- name: start
type: integer
description: First entry (0-based).
- name: end
type: integer
description: Last entry.
- id: playlist_status
label: Play Queue Status Only
kind: query
command: "GET /Playlist?length=1"
params: []
- id: playlist_delete
label: Delete Track from Queue
kind: action
command: "GET /Delete?id={position}"
params:
- name: id
type: integer
description: Track id (queue position) to delete.
- id: playlist_move
label: Move Track in Queue
kind: action
command: "GET /Move?new={destination}&old={origin}"
params:
- name: new
type: integer
description: New queue position.
- name: old
type: integer
description: Old queue position.
- id: playlist_clear
label: Clear Queue
kind: action
command: "GET /Clear"
params: []
- id: playlist_save
label: Save Queue as Named Playlist
kind: action
command: "GET /Save?name={playlist_name}"
params:
- name: name
type: string
description: Playlist name (URL-encode spaces).
- id: presets_list
label: List Presets
kind: query
command: "GET /Presets"
params: []
- id: preset_load
label: Load Preset
kind: action
command: "GET /Preset?id={presetId}"
params:
- name: presetId
type: string
description: Preset id, +1 for next preset, -1 for previous preset.
- id: browse
label: Browse Music Content
kind: query
command: "GET /Browse?key={key-value}&withContextMenuItems={0|1}"
params:
- name: key-value
type: string
description: URL-encoded browseKey, nextKey, parentKey, or contextMenuKey.
- name: withContextMenuItems
type: integer
description: 1 to include inline context menu.
- id: search
label: Search Music Content
kind: query
command: "GET /Browse?key={key-value}&q={searchText}"
params:
- name: key-value
type: string
description: URL-encoded searchKey from prior response.
- name: q
type: string
description: Search string.
- id: group_add_slave
label: Group One Secondary Player
kind: action
command: "GET /AddSlave?slave={secondaryPlayerIP}&port={secondaryPlayerPort}&group={GroupName}"
params:
- name: slave
type: string
description: IP address of the secondary player.
- name: port
type: integer
description: Port of the secondary player (default 11000; CI580 uses 11000/11010/11020/11030).
- name: group
type: string
description: Optional group name.
- id: group_add_slaves
label: Group Multiple Secondary Players
kind: action
command: "GET /AddSlave?slaves={secondaryPlayerIPs}&ports={secondaryPlayerPorts}"
params:
- name: slaves
type: string
description: Comma-separated IP addresses.
- name: ports
type: string
description: Comma-separated port numbers.
- id: group_remove_slave
label: Remove One Secondary Player
kind: action
command: "GET /RemoveSlave?slave={secondaryPlayerIP}&port={secondaryPlayerPort}"
params:
- name: slave
type: string
description: IP of the secondary player to remove.
- name: port
type: integer
description: Port of the secondary player to remove.
- id: group_remove_slaves
label: Remove Multiple Secondary Players
kind: action
command: "GET /RemoveSlave?slaves={secondaryPlayerIPs}&ports={secondaryPlayerPorts}"
params:
- name: slaves
type: string
description: Comma-separated IP addresses.
- name: ports
type: string
description: Comma-separated port numbers.
- id: reboot
label: Soft Reboot Player
kind: action
command: "POST /reboot with parameter yes=1"
params: []
- id: doorbell
label: Play Doorbell Chime
kind: action
command: "GET /Doorbell?play=1"
params: []
- id: input_select_url
label: Active Input Selection by URL (HUB inputs)
kind: action
command: "GET /Play?url={URL_value}"
params:
- name: url
type: string
description: URL value from /RadioBrowse?service=Capture response (URL-encoded).
- id: radio_browse_capture
label: List Active Inputs (Capture service)
kind: query
command: "GET /RadioBrowse?service=Capture"
params: []
- id: input_select_index_legacy
label: External Input Selection by index (firmware > v3.8.0 and < v4.2.0)
kind: action
command: "GET /Play?inputIndex={IndexId}"
params:
- name: inputIndex
type: integer
description: 1-based index of inputs from /Settings?id=capture&schemaVersion=32 (Bluetooth excluded).
- id: capture_settings
label: Capture Settings (for legacy inputIndex)
kind: query
command: "GET /Settings?id=capture&schemaVersion=32"
params: []
- id: input_select_type_index
label: External Input Selection by type-index (firmware v4.2.0+)
kind: action
command: "GET /Play?inputTypeIndex={type-index}"
params:
- name: type-index
type: string
description: "Format {type}-{index}. Types: spdif, analog, coax, bluetooth, arc, earc, phono, computer, aesebu, balanced, microphone. Index starts at 1."
- id: bluetooth_mode
label: Set Bluetooth Autoplay Mode
kind: action
command: "GET /audiomodes?bluetoothAutoplay={value}"
params:
- name: value
type: integer
description: 0 = Manual, 1 = Automatic, 2 = Guest, 3 = Disabled.
- id: lsdp_announce
label: LSDP Announce (UDP broadcast)
kind: action
command: "LSDP Announce packet broadcast to UDP port 11430"
params: []
- id: lsdp_query
label: LSDP Query (UDP broadcast)
kind: action
command: "LSDP Query packet broadcast to UDP port 11430"
params: []
- id: lsdp_delete
label: LSDP Delete (UDP broadcast)
kind: action
command: "LSDP Delete packet broadcast to UDP port 11430"
params: []
Feedbacks
- id: volume_state
type: object
description: |
Volume level (0..100 or -1 for fixed) plus dB, mute flag, optional pre-mute level
(muteDb, muteVolume). Returned by /Volume and embedded in /Status as <volume>.
- id: playback_state
type: enum
values: [play, pause, stop, stream, connecting]
description: Returned by /Status as <state> and by /Play, /Pause, /Stop responses.
- id: shuffle_state
type: enum
values: [0, 1]
description: Returned by /Status as <shuffle> and /Playlist as shuffle attribute.
- id: repeat_state
type: enum
values: [0, 1, 2]
description: 0 = repeat queue, 1 = repeat track, 2 = repeat off. /Status <repeat>, /Playlist repeat attr.
- id: sync_group
type: object
description: |
Group name and member list. Returned by /SyncStatus as <group> and <master>/<slave> elements.
- id: now_playing
type: object
description: |
Album, artist, name, title1/title2/title3, totlen, secs, image, service, quality,
streamUrl. Returned by /Status.
- id: battery
type: object
description: |
Optional. level (percent), charging (1/0), icon URL. Returned by /Status and /SyncStatus
when player has a battery pack.
- id: doorbell_status
type: object
description: enable, volume, chime audio path. Returned by /Doorbell.
- id: radio_station_action
type: object
description: |
Available radio station actions (skip, back, love, ban) with URLs. Returned as <actions>
within /Status when a streamUrl is present.
- id: queue_id
type: integer
description: pid/prid queue and preset ids returned by /Status, /Playlist, /Presets.
Variables
# UNRESOLVED: source documents discrete command-driven settings (volume level, mute, repeat,
# shuffle, input, bluetooth mode) rather than settable parameter variables. No separate
# Variables list is supported by the source.
Events
# UNRESOLVED: source does not document unsolicited push notifications beyond the long-polling
# pattern (which is pull-based). No streaming event subscription protocol is described.
Macros
# UNRESOLVED: no multi-step macro sequences described in source.
Safety
confirmation_required_for:
- reboot # /reboot is a destructive soft-reboot operation affecting all clients
interlocks: []
# UNRESOLVED: no explicit safety warnings, electrical interlocks, or power-on sequencing
# procedures are described in the source.
Notes
- All HTTP endpoints respond with UTF-8 encoded XML.
- BluOS players use UDP port 11000 (node 1 of CI580) / 11010 / 11020 / 11030 by default; the actual port should be discovered via mDNS services
musc.tcpandmusp.tcp. - Long polling: when not used, polling rate should not exceed one request every 30 seconds. When used, two consecutive requests for the same resource must not be made less than one second apart.
- /Status polling: recommended interval 100 s; never faster than 10 s.
- /SyncStatus polling: recommended interval 180 s.
- External input selection has three documented variants with different firmware requirements:
- /Play?url=URL_value for active inputs and HUB inputs (always supported).
- /Play?inputIndex=N for firmware > v3.8.0 and < v4.2.0.
- /Play?inputTypeIndex={type}-{index} for firmware v4.2.0+.
- LSDP (Lenbrook Service Discovery Protocol) uses UDP broadcast on port 11430, IANA-registered to Lenbrook. Packet header starts with magic "LSDP" (4 ASCII bytes). Protocol version = 1. Startup sends 7 packets at [0, 1, 2, 3, 5, 7, 10s] + (0 to 250ms random). Steady-state Announce period 57s + (0 to 6s random).
- /reboot is a POST (not GET) — every other documented endpoint uses GET.
- "powerable" trait intentionally left false: source documents only soft reboot (/reboot) and playback state transitions (play/pause/stop); no dedicated power-on/off command is described.
Provenance
source_domains:
- bluos.io
source_urls:
- https://bluos.io/wp-content/uploads/2025/06/BluOS-Custom-Integration-API_v1.7.pdf
retrieved_at: 2026-08-24T06:01:46.885Z
last_checked_at: 2026-08-24T22:16:27.042Z
Verification Summary
verdict: verified
checked_at: 2026-08-24T22:16:27.042Z
matched_actions: 44
action_count: 44
confidence: medium
summary: "All 44 spec actions map verbatim to documented HTTP endpoints or LSDP message types in the source; transport parameters (port 11000, UDP11430) are supported; ratio44/31 above 0.9 floor. (7 unresolved item(s) noted in Known Gaps.)"
Known Gaps
- "firmware compatibility ranges for individual endpoints are documented (e.g. /Play?inputIndex is only valid for BluOS firmware newer than v3.8.0 and older than v4.2.0, /Play?inputTypeIndex requires v4.2.0+) but not consolidated for the unified driver; concrete device model coverage beyond \"BluOS players\" is not enumerated in the source."
- "explicit power on/off not documented; /reboot is soft reboot, not power control"
- "source documents discrete command-driven settings (volume level, mute, repeat,"
- "source does not document unsolicited push notifications beyond the long-polling"
- "no multi-step macro sequences described in source."
- "no explicit safety warnings, electrical interlocks, or power-on sequencing"
- "Concrete device model coverage (Bluesound NODE, POWERNODE, PULSE, NAD CI580, DALI etc.) and per-model firmware compatibility matrix not stated in source. Per-command response payload schemas beyond those quoted (status, volume, playlist, presets, doorbell, sync, radiotime, settings) are documented as \"ignore undocumented responses\" rather than enumerated. LSDP message block fields beyond Announce/Query/Delete headers are not present in the supplied excerpt."
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0