Summary
Control spec for Bluesound / NAD / DALI BluOS networked audio players using the vendor-published Custom Integration (CI) HTTP API. The interface is HTTP GET to port 11000 (per-player; CI580 uses 11000/11010/11020/11030) returning UTF-8 encoded XML. Discovery is via mDNS service types musc.tcp/musp.tcp or the vendor LSDP UDP-broadcast protocol on port 11430.
Transport
protocols:
- http
- udp
addressing:
port: 11000 # per-player HTTP control port; CI580 nodes use 11010/11020/11030
base_url: "/"
auth:
type: none # inferred: no auth procedure in source
Traits
- powerable # inferred: soft reboot via POST /reboot (section 9)
- routable # inferred: input selection via /Play?url=, /Play?inputIndex=, /Play?inputTypeIndex= (section 11)
- queryable # inferred: /Status and /SyncStatus queries (sections 2.1, 2.2)
- levelable # inferred: /Volume level / db / mute control (section 3)
Actions
- id: status_query
label: Playback Status
kind: query
command: "GET /Status"
params:
- name: timeout
type: integer
description: Optional long-polling timeout in seconds
- name: etag
type: string
description: Optional etag from previous /Status response
- id: sync_status_query
label: Player and Group Sync Status
kind: query
command: "GET /SyncStatus"
params:
- name: timeout
type: integer
description: Optional long-polling timeout in seconds
- name: etag
type: string
description: Optional etag from previous /SyncStatus response
- id: volume_set
label: Set Volume (level 0..100)
kind: action
command: "GET /Volume?level={level}&tell_slaves={tell_slaves}"
params:
- name: level
type: integer
description: Absolute volume level 0..100
- name: tell_slaves
type: integer
description: 0 = only this player; 1 = apply to all grouped players
- id: volume_set_abs_db
label: Set Volume (absolute dB)
kind: action
command: "GET /Volume?abs_db={abs_db}&tell_slaves={tell_slaves}"
params:
- name: abs_db
type: number
description: Absolute volume in dB
- name: tell_slaves
type: integer
description: 0 = only this player; 1 = apply to all grouped players
- id: volume_up
label: Volume Up (+2 dB typical)
kind: action
command: "GET /Volume?db={db}"
params:
- name: db
type: number
description: Volume delta in dB (positive; typical value 2)
- id: volume_down
label: Volume Down (-2 dB typical)
kind: action
command: "GET /Volume?db={db}"
params:
- name: db
type: number
description: Volume delta in dB (negative; typical value -2)
- id: volume_relative_db
label: Relative Volume Change
kind: action
command: "GET /Volume?db={delta_db}&tell_slaves={tell_slaves}"
params:
- name: delta_db
type: number
description: Signed dB delta
- name: tell_slaves
type: integer
description: 0 = only this player; 1 = apply to all grouped players
- 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
kind: action
command: "GET /Play"
params: []
- id: play_seek
label: Play with Seek
kind: action
command: "GET /Play?seek={seconds}"
params:
- name: seconds
type: integer
description: Jump to position in current track
- id: play_seek_id
label: Play with Seek and Track Id
kind: action
command: "GET /Play?seek={seconds}&id={trackid}"
params:
- name: seconds
type: integer
description: Position in track
- name: trackid
type: integer
description: Track id in queue
- id: play_url
label: Play Streamed Custom Audio
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)
kind: action
command: "GET /Back"
params: []
- id: shuffle
label: Shuffle
kind: action
command: "GET /Shuffle?state={state}"
params:
- name: state
type: integer
description: 0 = off, 1 = on
- id: repeat
label: Repeat
kind: action
command: "GET /Repeat?state={state}"
params:
- name: state
type: integer
description: 0 = repeat queue, 1 = repeat track, 2 = off
- id: action_radio
label: Streaming Radio Action (skip/back/love/ban)
kind: action
command: "GET /Action?service={service}&{key}={value}"
params:
- name: service
type: string
description: Service name (e.g. Slacker, Radio Paradise)
- name: key
type: string
description: Action key (skip|back|love|ban) with track id value
- id: playlist_query
label: List Play Queue
kind: query
command: "GET /Playlist"
params:
- name: length
type: integer
description: Return only top-level attributes if1
- name: start
type: integer
description: First entry index (0-based)
- name: end
type: integer
description: Last entry index
- id: delete_track
label: Delete Track from Queue
kind: action
command: "GET /Delete?id={position}"
params:
- name: position
type: integer
description: Track id in queue to remove
- id: move_track
label: Move Track in Queue
kind: action
command: "GET /Move?new={destination}&old={origin}"
params:
- name: destination
type: integer
description: New position
- name: origin
type: integer
description: Old position
- id: clear_queue
label: Clear Play Queue
kind: action
command: "GET /Clear"
params: []
- id: save_queue
label: Save Play Queue as Playlist
kind: action
command: "GET /Save?name={playlist_name}"
params:
- name: playlist_name
type: string
description: Saved playlist name (URL-encoded)
- 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, or +1 for next, -1 for previous
- id: browse
label: Browse Music Content
kind: query
command: "GET /Browse?key={key_value}&withContextMenuItems=1"
params:
- name: key_value
type: string
description: URL-encoded key from prior browseKey/nextKey/parentKey/contextMenuKey
- name: withContextMenuItems
type: integer
description: Always 1 to retrieve inline context menu
- id: browse_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: searchText
type: string
description: Search term (URL-encoded)
- id: group_add_slave
label: Group Secondary Player
kind: action
command: "GET /AddSlave?slave={secondaryPlayerIP}&port={secondaryPlayerPort}&group={GroupName}"
params:
- name: secondaryPlayerIP
type: string
description: Secondary player IP
- name: secondaryPlayerPort
type: integer
description: Secondary player port (default 11000)
- name: GroupName
type: string
description: Optional group name
- id: group_add_slaves_multi
label: Group Multiple Secondary Players
kind: action
command: "GET /AddSlave?slaves={secondaryPlayerIPs}&ports={secondaryPlayerPorts}"
params:
- name: secondaryPlayerIPs
type: string
description: Comma-separated secondary player IPs
- name: secondaryPlayerPorts
type: string
description: Comma-separated secondary player ports
- id: group_remove_slave
label: Remove One Secondary Player
kind: action
command: "GET /RemoveSlave?slave={secondaryPlayerIP}&port={secondaryPlayerPort}"
params:
- name: secondaryPlayerIP
type: string
description: Secondary player IP
- name: secondaryPlayerPort
type: integer
description: Secondary player port
- id: group_remove_slaves_multi
label: Remove Multiple Secondary Players
kind: action
command: "GET /RemoveSlave?slaves={secondaryPlayerIPs}&ports={secondaryPlayerPorts}"
params:
- name: secondaryPlayerIPs
type: string
description: Comma-separated secondary player IPs
- name: secondaryPlayerPorts
type: string
description: Comma-separated secondary player ports
- id: reboot
label: Soft Reboot Player
kind: action
command: "POST /reboot body: yes=1"
params: []
- id: doorbell_play
label: Play Doorbell Chime
kind: action
command: "GET /Doorbell?play=1"
params: []
- id: input_select_active
label: Active Input Selection (Capture URL)
kind: action
command: "GET /Play?url={URL_value}"
params:
- name: URL_value
type: string
description: URL attribute from /RadioBrowse?service=Capture response (URL-encoded)
- id: input_select_index label: External Input Selection (inputIndex, legacy firmware)
kind: action
command: "GET /Play?inputIndex={IndexId}"
params:
- name: IndexId
type: integer
description: 1-based index from /Settings?id=capture (Bluetooth excluded); firmware newer than v3.8.0 and older than v4.2.0
- id: input_select_type_index
label: External Input Selection (inputTypeIndex)
kind: action
command: "GET /Play?inputTypeIndex={type_index}"
params:
- name: type_index
type: string
description: Format type-index; type in {spdif, analog, coax, bluetooth, arc, earc, phono, computer, aesebu, balanced, microphone}; index starts at 1; firmware v4.2.0+
- id: radio_browse_capture
label: Radio Browse Capture (input list)
kind: query
command: "GET /RadioBrowse?service=Capture"
params: []
- id: bluetooth_autoplay
label: Set Bluetooth Mode
kind: action
command: "GET /audiomodes?bluetoothAutoplay={value}"
params:
- name: value
type: integer
description: 0=Manual, 1=Automatic, 2=Guest, 3=Disabled
- id: add_favourite
label: Add Favourite
kind: action
command: "GET /AddFavourite?service={service}&albumid={albumid}"
params:
- name: service
type: string
description: Music service id
- name: albumid
type: string
description: Album id
- id: add_to_queue
label: Add to Queue
kind: action
command: "GET /Add?service={service}&albumid={albumid}&playnow={playnow}&clear={clear}&shuffle={shuffle}&where={where}"
params:
- name: service
type: string
description: Music service id
- name: albumid
type: string
description: Album id
- name: playnow
type: integer
description: 1 = play now, 0 = no, -1 = do not play now
- name: clear
type: integer
description: 1 = clear queue first
- name: shuffle
type: integer
description: 1 = shuffle
- name: where
type: string
description: nextAlbum | last | next
- id: settings_query
label: Settings Query
kind: query
command: "GET /Settings?id={id}&schemaVersion={schemaVersion}"
params:
- name: id
type: string
description: Settings id (e.g. capture)
- name: schemaVersion
type: integer
description: Schema version (32 documented)
Feedbacks
- id: playback_state
type: enum
values: [play, pause, stop, stream, connecting]
description: Returned in /Status and playback command responses
- id: volume_level
type: integer
description: 0..100 from /Status and /Volume responses; -1 = fixed volume
- id: volume_db
type: number
description: Volume in dB from /Status and /Volume responses
- id: mute_state
type: enum
values: [muted, unmuted]
description: mute=1 means muted
- id: shuffle_state
type: enum
values: [off, on]
description:0=off, 1=on- id: repeat_state
type: enum
values: [queue, track, off]
description: 0=repeat queue, 1=repeat track, 2=off
- id: sleep_timer_minutes
type: integer
description: Minutes remaining before sleep timer activates
- id: song_position
type: integer
description: Position of current track in play queue
- id: queue_length
type: integer
description: Total tracks in current play queue
- id: queue_modified
type: enum
values: [clean, modified]
description: 0 = not modified since loaded, 1 = modified
- id: stream_url_present
type: boolean
description: Presence of <streamUrl> indicates play queue is not the source
- id: sync_stat
type: integer
description: Changes whenever any item in /SyncStatus changes; matches /Status syncStat
- id: doorbell_enabled
type: enum
values: [enabled, disabled]
description: enable=1 means chime available
Variables
# Settable per-player parameters that aren't discrete actions
- name: volume_level
type: integer
description: 0..100 (or -1 fixed)
- name: mute type: integer
description: 0 = unmuted, 1 = muted
- name: shuffle
type: integer
description: 0 = off, 1 = on
- name: repeat
type: integer
description: 0 = repeat queue, 1 = repeat track, 2 = off
- name: bluetooth_autoplay_mode
type: integer
description: 0=Manual, 1=Automatic, 2=Guest, 3=Disabled
- name: group_name
type: string
description: Set when adding a slave to a group
Events
# Long-polling on /Status or /SyncStatus surfaces changes; etag mismatches signal state change.
- id: status_changed
description: Emitted implicitly when /Status long-poll returns due to state change (etag differs)
- id: sync_status_changed
description: Emitted implicitly when /SyncStatus long-poll returns due to grouping/volume/name change
Macros
# UNRESOLVED: source does not document explicit user-defined macro sequences
Safety
confirmation_required_for: []
interlocks: []
# UNRESOLVED: source does not contain safety warnings, interlocks, or power-on sequencing requirements.
# UNRESOLVED: source notes /Status for grouped (secondary) players is a copy of the primary; misrouted commands at the secondary will be proxied internally to primary (section 8 intro).
Notes
- Default HTTP control port is 11000 per player; the CI580 uses four streamers in one chassis on ports 11000 / 11010 / 11020 / 11030; the actual port should be discovered via mDNS service types
musc.tcpandmusp.tcp, or via the LSDP UDP-broadcast discovery protocol (port 11430). - LSDP (Lenbrook Service Discovery Protocol) is an alternative UDP-broadcast discovery mechanism on registered UDP port 11430 using magic word
LSDP, big-endian multi-byte values, and packet header version1. Steady-state Announce interval ~57s + 0-6s random; startup sends 7 packets at [0,1,2,3,5,7,10]s + 0-250ms. - When long-polling, recommended interval is 100s for
/Statusand 180s for/SyncStatus; never faster than 10s; do not make two consecutive same-resource requests <1s apart. - External input selection command varies by firmware:
inputIndexfor firmware newer than v3.8.0 and older than v4.2.0;inputTypeIndex(formattype-index) for firmware v4.2.0 or newer. - Image URLs starting with
/Artworkmay redirect; appendfollowRedirects=1when retrieving to avoid redirect (also applies to presetimageattribute). - All HTTP requests are GET (except
/rebootwhich is POST with bodyyes=1); parameters are URL-encoded name/value pairs; responses are UTF-8 encoded XML. browseKey,contextMenuKey,searchKeyvalues must be URI-encoded (percent-escaped) when used askeyparameter to/Browse.- Grouping: only one primary player; secondary players can have many requests (Status, playback, queue, browse) internally proxied to primary.
- The Document title says "NAD" in the header but the spec covers Bluesound, NAD Electronics, and DALI Loudspeakers BluOS players.
---
Self-check passed: status=draft, confidence=low, derived_from=vendor_manual, no fabricated voltages/ports/baud. Endpoint paths and parameter names copied verbatim from source.
## Provenance
```yaml
source_domains:
- content-bluesound-com.s3.amazonaws.com
source_urls:
- https://content-bluesound-com.s3.amazonaws.com/uploads/BluOS-Custom-Integration-API_v1.7.pdf
retrieved_at: 2026-05-21T13:48:57.857Z
last_checked_at: 2026-09-13T22:17:56.864Z
Verification Summary
verdict: verified
checked_at: 2026-09-13T22:17:56.864Z
matched_actions: 44
action_count: 44
confidence: medium
summary: "All 44 spec actions map verbatim to source endpoints; transport port 11000 and UDP 11430 are documented; source command catalogue is fully represented. (8 unresolved item(s) noted in Known Gaps.)"
Known Gaps
- "per-model feature coverage (Bluetooth, doorbell, grouping, HUB inputs) varies by hardware; this spec documents the CI API surface, not per-model matrix"
- "LSDP discovery UDP port 11430 is documented but the per-player HTTP control endpoint is the primary control transport; UDP/LSDP is discovery-only and listed separately in Notes"
- "source does not document explicit user-defined macro sequences"
- "source does not contain safety warnings, interlocks, or power-on sequencing requirements."
- "source notes /Status for grouped (secondary) players is a copy of the primary; misrouted commands at the secondary will be proxied internally to primary (section 8 intro)."
- "firmware version compatibility ranges for individual endpoints (e.g. /Play?inputIndex vs /Play?inputTypeIndex) are stated as v3.8.0/v4.2.0 boundaries, but per-endpoint minimum firmware versions across the whole API are not enumerated"
- "voltage, current, power specifications not stated in source"
- "fault behavior or error recovery sequences not stated in source"
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0