Summary
Spec covers the BluOS Custom Integration HTTP API used to control iHeartRadio streaming (and other BluOS services) on Bluesound/NAD BluOS-enabled players. All commands are HTTP GET requests issued to http://<player_ip>:11000/<request>, with responses as UTF-8 encoded XML. Companion Lenbrook Service Discovery Protocol (LSDP) runs on UDP broadcast port 11430.
Transport
protocols:
- http
- udp
addressing:
port: 11000
base_url: "http://{player_ip}:11000"
auth:
type: none # inferred: no auth procedure in source
LSDP discovery uses UDP broadcast on port 11430 (IANA-registered to Lenbrook).
Traits
- powerable # inferred from /reboot endpoint (soft reboot documented)
- queryable # inferred from /Status and /SyncStatus query endpoints
- routable # inferred from input selection endpoints (/Play?url=, /Play?inputTypeIndex=)
- levelable # inferred from /Volume endpoint (volume up/down/set/mute)
Actions
# Section 2 - Status queries
- id: status_query
label: Playback Status
kind: query
command: "GET /Status"
params: []
notes: Supports long-polling via timeout and etag query params.
- id: sync_status_query
label: Player and Group Sync Status
kind: query
command: "GET /SyncStatus"
params: []
notes: Supports long-polling via timeout and etag query params.
# Section 3 - Volume control
- 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, integer 0-100
- name: tell_slaves
type: enum
values: [0, 1]
description: "0 = only selected player changes; 1 = all players in group change"
- id: volume_set_db_absolute
label: Set Volume (absolute dB)
kind: action
command: "GET /Volume?abs_db={db}&tell_slaves={tell_slaves}"
params:
- name: db
type: number
description: Absolute volume level in dB
- id: volume_set_db_relative
label: Adjust Volume (relative dB)
kind: action
command: "GET /Volume?db={delta_db}&tell_slaves={tell_slaves}"
params:
- name: delta_db
type: number
description: Relative volume change in dB (positive or negative)
- id: volume_mute
label: Mute Player
kind: action
command: "GET /Volume?mute=1"
params: []
- id: volume_unmute
label: Unmute Player
kind: action
command: "GET /Volume?mute=0"
params: []
- 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: []
# Section 4 - Playback control
- 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: Position in seconds to jump to in current track
- id: play_seek_trackid
label: Play with seek and track id
kind: action
command: "GET /Play?seek={seconds}&id={trackid}"
params:
- name: seconds
type: integer
- name: trackid
type: integer
description: Track number in queue (0-based or as exposed by /Playlist)
- id: play_url
label: Play streamed URL
kind: action
command: "GET /Play?url={encodedStreamURL}"
params:
- name: encodedStreamURL
type: string
description: URL of streamed custom audio, URL-encoded
- 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 (next track)
kind: action
command: "GET /Skip"
params: []
- id: back
label: Back (previous track)
kind: action
command: "GET /Back"
params: []
- id: shuffle
label: Set Shuffle State
kind: action
command: "GET /Shuffle?state={state}"
params:
- name: state
type: enum
values: [0, 1]
description: "0 = disable shuffle; 1 = enable shuffle"
- id: repeat
label: Set Repeat State
kind: action
command: "GET /Repeat?state={state}"
params:
- name: state
type: enum
values: [0, 1, 2]
description: "0 = repeat entire play queue; 1 = repeat current track; 2 = repeat off"
- id: action_radio_skip
label: Radio Station Action - Skip
kind: action
command: "GET /Action?service={service}&skip={trackid}"
params:
- name: service
type: string
description: Streaming service name (e.g. Slacker)
- name: trackid
type: string
description: Track id from action URL in /Status
- id: action_radio_love
label: Radio Station Action - Love
kind: action
command: "GET /Action?service={service}&love={trackid}"
params:
- name: service
type: string
- name: trackid
type: string
- id: action_radio_ban
label: Radio Station Action - Ban
kind: action
command: "GET /Action?service={service}&ban={trackid}"
params:
- name: service
type: string
- name: trackid
type: string
# Section 5 - Play queue management
- id: playlist_list
label: List Play Queue
kind: query
command: "GET /Playlist"
params: []
- id: playlist_status
label: Play Queue Status Only
kind: query
command: "GET /Playlist?length=1"
params: []
- id: playlist_page
label: List Play Queue Page
kind: query
command: "GET /Playlist?start={first}&end={last}"
params:
- name: first
type: integer
description: First entry index (starting from 0)
- name: last
type: integer
description: Last entry index
- id: queue_delete
label: Delete Track from Queue
kind: action
command: "GET /Delete?id={position}"
params:
- name: position
type: integer
description: Track position in queue
- id: queue_move
label: Move Track in Queue
kind: action
command: "GET /Move?new={destination}&old={origin}"
params:
- name: destination
type: integer
- name: origin
type: integer
- id: queue_clear
label: Clear Play Queue
kind: action
command: "GET /Clear"
params: []
- id: queue_save
label: Save Play Queue as Playlist
kind: action
command: "GET /Save?name={playlist_name}"
params:
- name: playlist_name
type: string
# Section 6 - Presets
- 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 number, or +1 (next) or -1 (previous)
- id: preset_next
label: Load Next Preset
kind: action
command: "GET /Preset?id=+1"
params: []
- id: preset_previous
label: Load Previous Preset
kind: action
command: "GET /Preset?id=-1"
params: []
# Section 7 - Browsing and searching
- id: browse_top
label: Top-Level Browse
kind: query
command: "GET /Browse"
params: []
- id: browse_key
label: Browse by Key
kind: query
command: "GET /Browse?key={key_value}"
params:
- name: key_value
type: string
description: URL-encoded key from prior browseKey / nextKey / parentKey
- id: browse_with_context
label: Browse with Inline Context Menu
kind: query
command: "GET /Browse?key={key_value}&withContextMenuItems=1"
params:
- name: key_value
type: string
- 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
# Section 8 - Player grouping
- id: group_add_slave
label: Group One Secondary Player
kind: action
command: "GET /AddSlave?slave={secondaryPlayerIP}&port={secondaryPlayerPort}&group={groupName}"
params:
- name: secondaryPlayerIP
type: string
- name: secondaryPlayerPort
type: integer
description: Default 11000
- name: groupName
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: secondaryPlayerIPs
type: string
description: Comma-separated IPs
- name: secondaryPlayerPorts
type: string
description: Comma-separated ports
- id: group_remove_slave
label: Remove One Secondary Player from Group
kind: action
command: "GET /RemoveSlave?slave={secondaryPlayerIP}&port={secondaryPlayerPort}"
params:
- name: secondaryPlayerIP
type: string
- name: secondaryPlayerPort
type: integer
- id: group_remove_slaves
label: Remove Multiple Secondary Players from Group
kind: action
command: "GET /RemoveSlave?slaves={secondaryPlayerIPs}&ports={secondaryPlayerPorts}"
params:
- name: secondaryPlayerIPs
type: string
- name: secondaryPlayerPorts
type: string
# Section 9 - Player reboot
- id: reboot
label: Reboot Player
kind: action
command: "POST /reboot"
params:
- name: yes
type: string
description: Any value (e.g. 1) submitted as form field
# Section 10 - Doorbell
- id: doorbell_play
label: Play Doorbell Chime
kind: action
command: "GET /Doorbell?play=1"
params: []
# Section 11 - Direct input
- id: input_select_url
label: Select Active Input via URL
kind: action
command: "GET /Play?url={URL_value}"
params:
- name: URL_value
type: string
description: URL attribute from /RadioBrowse?service=Capture
- id: input_select_index
label: Select External Input by Index (firmware > v3.8.0 and < v4.2.0)
kind: action
command: "GET /Play?inputIndex={IndexId}"
params:
- name: IndexId
type: integer
description: "1-based index of inputs from /Settings?id=capture (Bluetooth excluded)"
- id: input_select_type_index
label: Select External Input by Type-Index (firmware >= v4.2.0)
kind: action
command: "GET /Play?inputTypeIndex={typeIndex}"
params:
- name: typeIndex
type: string
description: "Format {type}-{index}. Types: spdif, analog, coax, bluetooth, arc, earc, phono, computer, aesebu, balanced, microphone. Index starts from 1."
# Section 12 - Bluetooth
- id: bluetooth_set_mode
label: Set Bluetooth Mode
kind: action
command: "GET /audiomodes?bluetoothAutoplay={value}"
params:
- name: value
type: enum
values: [0, 1, 2, 3]
description: "0 = Manual, 1 = Automatic, 2 = Guest, 3 = Disabled"
Feedbacks
- id: playback_state
type: enum
values: [play, pause, stop, stream, connecting]
description: Current player state, returned by /Status as <state>
- id: volume_level
type: integer
description: Volume level 0-100 (or -1 for fixed), returned in /Status and /Volume responses
- id: mute_state
type: enum
values: [0, 1]
description: 1 if muted, 0 if unmuted (also exposed as <mute>)
- id: db_level
type: number
description: Volume level in dB
- id: shuffle_state
type: enum
values: [0, 1]
description: 1 = shuffled, 0 = not shuffled
- id: repeat_state
type: enum
values: [0, 1, 2]
description: "0 = repeat queue, 1 = repeat track, 2 = repeat off"
- id: song_id
type: integer
description: Current track position in play queue (from <song> in /Status)
- id: etag
type: string
description: Opaque etag attribute on /Status and /SyncStatus roots, used for long-polling
- id: group_name
type: string
description: Group name when player is primary in group (from /Status <groupName>)
- id: group_volume
type: integer
description: Group volume when primary player (from /Status <groupVolume>)
Variables
# UNRESOLVED: no separately settable continuous variables beyond those exposed via Actions (volume level, mute, repeat, shuffle, bluetoothAutoplay). All settable parameters are covered as Actions.
Events
# UNRESOLVED: source does not describe unsolicited notification endpoints; long-polling on /Status and /SyncStatus is documented but it returns the same XML response shapes, not separate event types.
Macros
# UNRESOLVED: no multi-step sequences are documented in the source.
Safety
confirmation_required_for: []
interlocks: []
# UNRESOLVED: source contains no safety warnings, interlock procedures, or power-on sequencing requirements.
Notes
- All commands are HTTP GET requests against
http://<player_ip>:11000/<endpoint>, except/rebootwhich is POST. - Responses are UTF-8 encoded XML.
- LSDP (Lenbrook Service Discovery Protocol) is documented separately in §13. It uses UDP broadcast on port 11430 with magic word "LSDP", and serves as the recommended discovery mechanism because the document notes multicast-based mDNS is unreliable on some customer networks.
- Polling guidance: regular polling limited to at most one request every 30 seconds; long-poll not used to make two consecutive requests for the same resource less than 1 second apart.
- Volume range is typically -80..0 dB and is configurable via BluOS Controller app (Settings → Player → Audio).
- CI580 has four streamer nodes using ports 11000, 11010, 11020, 11030 (one port per node); default is 11000.
- For radio stations without a play queue, use /Action endpoint with action URLs returned in /Status elements.
- BluOS HUB input selection is supported only via the
/Play?url=direct input endpoint (§11.1). - External input selection has two forms depending on firmware:
inputIndexfor firmware newer than v3.8.0 and older than v4.2.0;inputTypeIndexfor firmware v4.2.0 or newer.
Provenance
source_domains:
- bluesoundprofessional.com
- bluos.io
- content-bluesound-com.s3.amazonaws.com
- bluesound.com
source_urls:
- https://bluesoundprofessional.com/wp-content/uploads/2025/06/BluOS-Custom-Integration-API_v1.7.pdf
- https://bluos.io/wp-content/uploads/2025/06/BluOS-Custom-Integration-API_v1.7.pdf
- https://bluos.io/downloads/
- https://content-bluesound-com.s3.amazonaws.com/uploads/2022/04/Custom-Integration-API-v1.4.pdf
- https://www.bluesound.com/pages/downloads
retrieved_at: 2026-07-22T00:45:57.300Z
last_checked_at: 2026-07-22T01:06:18.603Z
Verification Summary
verdict: verified
checked_at: 2026-07-22T01:06:18.603Z
matched_actions: 48
action_count: 48
confidence: medium
summary: "All 48 spec actions map to literal source endpoints with matching shapes; transport and LSDP port confirmed; only two helper query endpoints are unrepresented. (6 unresolved item(s) noted in Known Gaps.)"
Known Gaps
- "/RadioBrowse?service=Capture"
- "/Settings?id=capture&schemaVersion=32"
- "source describes the BluOS CI API in general, not iHeartRadio-specific extensions; iHeartRadio behaves as a streaming source within the API and uses standard endpoints."
- "no separately settable continuous variables beyond those exposed via Actions (volume level, mute, repeat, shuffle, bluetoothAutoplay). All settable parameters are covered as Actions."
- "source does not describe unsolicited notification endpoints; long-polling on /Status and /SyncStatus is documented but it returns the same XML response shapes, not separate event types."
- "no multi-step sequences are documented in the source."
- "source contains no safety warnings, interlock procedures, or power-on sequencing requirements."
- "iHeartRadio-specific control extensions are not documented in this generic BluOS CI API document; iHeartRadio is treated as a streaming service selectable via /Presets, /Browse, or /Play?url=. No iHeartRadio-only endpoints were enumerated in the source."
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0