SoundTouch Speaker Endpoint Documentation
This document describes the implementation of the /speaker endpoint for Bose SoundTouch devices, which enables Text-To-Speech (TTS) notifications and URL content playback.
Overview
The /speaker endpoint is used to play notification content on SoundTouch devices, including:
- Text-To-Speech messages using Google TTS
- Audio content from HTTP/HTTPS URLs
- Notification beeps (via
/playNotificationendpoint)
Important: This functionality is primarily supported by ST-10 (Series III) speakers. ST-300 and other models may not support this endpoint despite it appearing in their supported URLs.
API Reference
POST /speaker
Plays notification content on the speaker.
Request Body:
<play_info>
<url>URL_TO_AUDIO_CONTENT</url>
<app_key>YOUR_APPLICATION_KEY</app_key>
<service>SERVICE_NAME</service>
<message>MESSAGE_DESCRIPTION</message>
<reason>REASON_OR_FILENAME</reason>
<volume>VOLUME_LEVEL</volume> <!-- Optional: 0-100, omit for current volume -->
</play_info>Response:
<?xml version="1.0" encoding="UTF-8" ?>
<status>/speaker</status>GET /playNotification
Plays a simple notification beep sound.
Important: This endpoint requires a GET request, not POST. Earlier versions of this client library incorrectly used POST and would fail with HTTP 400 status.
Response:
<?xml version="1.0" encoding="UTF-8" ?>
<status>/playNotification</status>Go Client Library Usage
Text-To-Speech (TTS)
package main
import (
"log"
"github.com/gesellix/bose-soundtouch/pkg/client"
"github.com/gesellix/bose-soundtouch/pkg/models"
)
func main() {
config := &client.Config{
Host: "192.0.2.100",
Port: 8090,
}
client := client.NewClient(config)
// Play TTS at current volume (language code "EN", "DE", etc.)
err := client.PlayTTS("Hello, this is a test message", "YOUR_APP_KEY", "EN")
if err != nil {
log.Fatal(err)
}
// Play TTS at specific volume (70)
err = client.PlayTTS("Volume test message", "YOUR_APP_KEY", "EN", 70)
if err != nil {
log.Fatal(err)
}
}URL Content Playback
func main() {
config := &client.Config{
Host: "192.0.2.100",
Port: 8090,
}
client := client.NewClient(config)
// Play audio from URL
err := client.PlayURL(
"https://example.com/audio.mp3",
"YOUR_APP_KEY",
"Music Service",
"Song Title",
"Artist Name",
50, // volume level
)
if err != nil {
log.Fatal(err)
}
}Custom PlayInfo
func main() {
client := client.NewClient(config)
// Create custom play info
playInfo := models.NewPlayInfo(
"https://example.com/audio.mp3",
"YOUR_APP_KEY",
"Custom Service",
"Custom Message",
"Custom Reason",
).SetVolume(60)
err := client.PlayCustom(playInfo)
if err != nil {
log.Fatal(err)
}
}Notification Beep
func main() {
client := client.NewClient(config)
// Uses GET request (fixed in v2025.02+)
err := client.PlayNotificationBeep()
if err != nil {
log.Fatal(err)
}
}CLI Usage
Text-To-Speech
# Basic TTS (English)
soundtouch-cli speaker tts --text "Hello World" --app-key YOUR_KEY --host 192.0.2.100
# TTS with volume and language
soundtouch-cli speaker tts \
--text "Bonjour le monde" \
--app-key YOUR_KEY \
--volume 70 \
--language FR \
--host 192.0.2.100URL Content Playback
# Basic URL playback
soundtouch-cli speaker url \
--url "https://example.com/audio.mp3" \
--app-key YOUR_KEY \
--host 192.0.2.100
# URL playback with custom metadata
soundtouch-cli speaker url \
--url "https://example.com/song.mp3" \
--app-key YOUR_KEY \
--service "My Music Service" \
--message "Beautiful Song" \
--reason "Artist Name" \
--volume 60 \
--host 192.0.2.100Notification Beep
soundtouch-cli speaker beep --host 192.0.2.100Help
# General speaker help
soundtouch-cli speaker --help
# Detailed functionality help
soundtouch-cli speaker help
# Command-specific help
soundtouch-cli speaker tts --help
soundtouch-cli speaker url --helpSupported Languages for TTS
The following language codes are supported for Google TTS:
| Code | Language |
|---|---|
| EN | English |
| DE | German |
| ES | Spanish |
| FR | French |
| IT | Italian |
| NL | Dutch |
| PT | Portuguese |
| RU | Russian |
| ZH | Chinese |
| JA | Japanese |
| KO | Korean |
| AR | Arabic |
| HI | Hindi |
| TH | Thai |
Behavior Notes
Volume Control: If a volume is specified, the device will:
- Switch to the specified volume for playback
- Automatically restore the previous volume after playback completes
- If volume is 0 or omitted, content plays at current volume
Content Interruption:
- Currently playing content is paused during notification playback
- Original content resumes automatically after notification ends
- If currently playing content is already a notification, you may get an error
Multiroom Behavior:
- If the device is a zone master, notifications play on all zone members
- Volume changes affect all devices in the zone
Now Playing Display:
- Service name appears in the “artist” field
- Message appears in the “album” field
- Reason appears in the “track” field
- Custom artwork can be included in URL-based content
Error Handling
Common errors and their meanings:
- Device not found: Check host/port configuration
- Endpoint not supported: Device doesn’t support
/speakerendpoint (common with ST-300) - Invalid app key: App key is required for TTS and URL playback
- Network timeout: Check device connectivity
- Invalid URL: URL must be accessible and contain valid audio content
App Key Requirements
Both TTS and URL playback require an app_key parameter. This appears to be used for:
- Request authentication/identification
- Rate limiting
- Service tracking
You’ll need to provide your own application key. The format and generation method for valid app keys is not documented in the official API.
Google Cloud Text-to-Speech (via the AfterTouch service)
The direct speaker tts path above hands the speaker an (undocumented) Google
Translate URL to fetch. That endpoint is fine for short notifications but is
low quality, length-limited, and can change without notice.
For higher-quality speech (real voices, SSML, many languages) the AfterTouch
service can synthesize audio with Google Cloud Text-to-Speech and host it
locally for the speaker to play. Because Cloud TTS returns audio bytes from an
authenticated request (not a fetchable URL), the service caches the clip and
serves it at GET /media/tts/{id}, then tells the speaker to play that local
URL via /speaker. The same app_key constraint applies.
Provider selection
The service picks a TTS provider via --tts-provider (env TTS_PROVIDER):
translate(default): the Google Translate URL path. No credentials.google-cloud: Google Cloud TTS via a REST API key. No OAuth, no SDK.
Configuration (soundtouch-service)
| Flag | Env | Purpose |
|---|---|---|
--tts-provider | TTS_PROVIDER | translate or google-cloud |
--tts-google-api-key | TTS_GOOGLE_API_KEY | Google Cloud TTS API key (required for google-cloud) |
--tts-language | TTS_LANGUAGE | Default language. EN/DE for translate, BCP-47 like en-US for google-cloud |
--tts-voice | TTS_VOICE | Default Cloud TTS voice (e.g. en-US-Neural2-C); ignored by translate |
--tts-app-key | TTS_APP_KEY | Bose /speaker app_key used to play the clip |
--tts-volume | TTS_VOLUME | Default playback volume (0-100, 0 = keep current) |
Example:
TTS_PROVIDER=google-cloud \
TTS_GOOGLE_API_KEY=YOUR_GOOGLE_API_KEY \
TTS_LANGUAGE=en-US \
TTS_VOICE=en-US-Neural2-C \
TTS_APP_KEY=YOUR_APP_KEY \
soundtouch-serviceTriggering speech
Service HTTP API (under /setup, LAN-trust like the rest of the setup surface,
no auth):
curl -X POST http://soundtouch.local:8000/setup/tts/speak \
-H 'Content-Type: application/json' \
-d '{"host":"192.0.2.100","text":"Dinner is ready"}'deviceId may be used instead of host (the service resolves it to an IP from its datastore). Optional fields: language, voice, volume, and method
(speaker, the default /speaker notification path that ducks and resumes
playback, or radio, the LOCAL_INTERNET_RADIO path that needs no app_key but
replaces the current source).
CLI (speaker tts-cloud routes through the service for Cloud TTS, in contrast
to speaker tts which sends a Google Translate URL straight to the speaker):
soundtouch-cli speaker tts-cloud \
--service-url http://soundtouch.local:8000 \
--host 192.0.2.100 \
--text "Dinner is ready" \
--method speakerWeb UI: the TTS source view has a “Say something…” box. soundtouch-player proxies
it to the service, so it must be started with --service-url (the target is
server-configured, not entered in the browser, to avoid an SSRF proxy).
Notes and limitations
app_keyvalidation is handled automatically (speaker method). The speaker validates the key by callingGET /v1/authon Bose’s audio notification host (audionotification.api.bosecm.com, and a…dev…variant), which AfterTouch intercepts (DNS substring match onbosecm.com, plus/etc/hostsseeding during migration) and answers200. So any non-emptyapp_keyworks; you don’t need a real Bose-issued key. Theradiomethod needs noapp_keyat all.- Model support for the
speakermethod is the same as the direct/speakerpath (primarily ST-10 Series III). Use--method radioon models without it. - Reachability: the speaker must be able to reach the service’s
/media/tts/{id}URL. The service builds it from its configuredserver-url. - Synthesized clips are cached in memory for a short time and identical requests reuse the same clip.
Limitations
- Device Support: Limited to specific SoundTouch models (primarily ST-10 Series III)
- Audio Formats: Supported audio formats depend on device capabilities
- URL Requirements: URLs must be publicly accessible (no authentication)
- TTS Length: Very long TTS messages may be truncated
- Concurrent Playback: Cannot play multiple notifications simultaneously
Integration Examples
Home Automation
// Doorbell notification
client.PlayTTS("Someone is at the front door", "home-automation-key", "EN", 80)
// Security alert
client.PlayURL(
"https://myserver.com/alerts/security-breach.mp3",
"security-system-key",
"Security System",
"Alert",
"Motion detected in restricted area",
100,
)Development/Testing
# Test connectivity
soundtouch-cli speaker beep --host 192.0.2.100
# Test TTS functionality
soundtouch-cli speaker tts --text "Testing TTS functionality" --app-key test-key --host 192.0.2.100
# Test URL playback
soundtouch-cli speaker url --url "https://www.soundjay.com/misc/sounds/bell-ringing-05.wav" --app-key test-key --host 192.0.2.100Troubleshooting
- Command not found: Ensure you’re using a supported SoundTouch model
- No audio output: Check volume levels and device status
- TTS not working: Verify internet connectivity for Google TTS service
- URL content fails: Ensure URL is accessible and contains valid audio
- Volume not restored: May occur if device is powered off during playback
For more information, see the SoundTouch WebServices API documentation.