A modern, high-performance HTTP API for controlling Sonos speakers, designed for Alexa skill integration and home automation.
This is a complete TypeScript rewrite of the original node-sonos-http-api, focused on speed, reliability, and minimal dependencies.
Version 1.6.0 adds enhanced authentication monitoring, deferred preset validation, and improved server status reporting.
- ⚡ Lightning fast - Near-instant response times using native Node.js HTTP
- 🎯 Alexa-ready - Drop-in replacement for jishi's node-sonos-http-api
- 📦 Minimal dependencies - Just 2 runtime dependencies vs 50+ in legacy
- 🔍 TypeScript - Full type safety with comprehensive error handling
- 🐳 Docker-first - Production-ready container with health checks
- 🎵 Music services - Apple Music, Spotify, Pandora, local library search
- 🔊 TTS support - Multiple text-to-speech providers
- 🏠 Group control - Manage speaker groups and stereo pairs
- 🛡️ Robust error handling - Typed errors with automatic retry logic
- 📊 96% test coverage - Comprehensive test suite
- 🔐 Secure - Optional authentication with trusted network support
- 🎧 Spotify Integration - Play tracks, albums, playlists with OAuth2 search
- Sonos S2 system - S1 systems are not supported
- Node.js 18+ - Uses native Node.js APIs
- Network access - Must be on same network as Sonos devices
-
Spotify Premium account - Free accounts cannot be controlled via API
-
Account linked in Sonos app - Spotify must be configured in your Sonos system
-
Required favorites - Add at least one of each to Sonos favorites:
- A Spotify track
- A Spotify album
- A Spotify playlist
These favorites are used to extract authentication tokens since S2 systems don't expose account details via API
Typical response times:
- Play/pause commands: <100ms
- Volume changes: <100ms
- Music search: <200ms
- Group operations: <150ms
- Enhanced Authentication Status - New
/pandora/statusand/spotify/statusendpoints show detailed auth state - Proactive Token Refresh - Spotify tokens now refresh automatically on startup when configured
- Server Summary JSON - The
server-summary.shscript now supports--jsonflag for structured output - Deferred Preset Validation - Presets validate only when used, preventing issues with devices discovered later
- sonosdebug.sh Utility - New script for managing debug settings remotely with network-aware defaults
- Bug Fixes - Library search playback, Pandora cache loading, preset favorite resolution
# Quick start with Docker
docker run -d \
--name sonos-alexa-api \
--network host \
-e DEFAULT_ROOM="Living Room" \
kshartman/sonos-alexa-api:v1.6.0
# Or using Docker Compose (recommended)
curl -O https://raw.githubusercontent.com/kshartman/sonos-alexa-api/main/docker-compose.example.yml
mv docker-compose.example.yml docker-compose.yml
# Edit docker-compose.yml with your settings
docker-compose up -d
# View logs
docker logs -f sonos-alexa-apiDocker Hub: kshartman/sonos-alexa-api
See DOCKER.md for detailed Docker usage and configuration.
npm install
npm startThe API can be configured through multiple sources with the following precedence:
- Default values
settings.jsonfile- Environment variables (highest priority)
The npm start command now loads .env files automatically using dotenv:
# Copy example and customize
cp example.env .env
# Edit .env with your settingsKey environment variables:
# Server
PORT=5005
HOST=sonosapi.local # Display name only (listens on 0.0.0.0)
TTS_HOST_IP=192.168.1.100 # Optional - auto-detected if not set
# Logging & Debug
LOG_LEVEL=info # error, warn, info, debug, trace
DEBUG_CATEGORIES=api,discovery # api,discovery,soap,topology,favorites,presets,upnp,sse,all
NODE_ENV=development # development or production
LOGGER=winston # winston or pino
# Authentication (optional)
AUTH_USERNAME=admin
AUTH_PASSWORD=secret
AUTH_TRUSTED_NETWORKS=192.168.1.0/24
# Defaults
DEFAULT_ROOM=LivingRoom
DEFAULT_SERVICE=apple
CREATE_DEFAULT_PRESETS=false # Auto-generate presets from favorites
# TTS
TTS_PROVIDER=google
TTS_LANG=en-US
# Spotify OAuth (for search functionality)
SPOTIFY_CLIENT_ID=your-client-id
SPOTIFY_CLIENT_SECRET=your-client-secret
SPOTIFY_REDIRECT_URI=http://localhost:5005/spotify/callback
SPOTIFY_REFRESH_TOKEN=your-refresh-token # Optional - obtained after OAuth flow
# Music Library
LIBRARY_RANDOM_QUEUE_LIMIT=100See .env.example for all available options.
Environment variables can be overridden on the command line:
# Override specific settings
DEBUG_CATEGORIES=api,discovery npm start
# Enable all debug categories (verbose)
DEBUG_CATEGORIES=all npm start
# Disable all debug categories for fastest startup
DEBUG_CATEGORIES= npm start
# Enable preset generation temporarily
CREATE_DEFAULT_PRESETS=true npm startControl log verbosity with DEBUG_CATEGORIES:
api- API request/response logging (enabled by default)discovery- Device discovery detailssoap- SOAP request/response XML (verbose)topology- UPnP topology eventsfavorites- Favorite resolution detailspresets- Preset loading and conversion (can be verbose)upnp- Raw UPnP event detailssse- Server-Sent Events for webhooksall- Enable all categories
Note: The presets category can generate hundreds of log lines during startup. It's recommended to enable it only when debugging preset issues.
DEBUG_CATEGORIES=all npm start
DEBUG_CATEGORIES= npm start
CREATE_DEFAULT_PRESETS=true npm start
### settings.json (Deprecated)
**⚠️ Deprecated**: Use environment variables instead.
Kept only for backward compatibility.
For reference, the settings.json format is:
```json
{
"port": 5005,
"host": "sonosapi.local",
"defaultRoom": "Living Room",
"defaultService": "apple",
"announceVolume": 40,
"auth": {
"username": "admin",
"password": "secret",
"rejectUnauthorized": true,
"trustedNetworks": ["192.168.1.0/24"]
},
"tts": {
"provider": "google",
"lang": "en-US"
},
"macSay": {
"voice": "Samantha",
"rate": 175
},
"pandora": {
"username": "your-pandora-username",
"password": "your-pandora-password"
},
"library": {
"randomQueueLimit": 50,
"reindexInterval": "1 week"
}
}
See the Help & Usage Guide for common usage patterns and examples, or the OpenAPI specification for complete endpoint documentation.
The API supports Spotify search and playback through OAuth2 authentication. There are two ways to configure Spotify:
If you already have a Spotify refresh token:
# Add to your .env file
SPOTIFY_CLIENT_ID=your-client-id
SPOTIFY_CLIENT_SECRET=your-client-secret
SPOTIFY_REFRESH_TOKEN=your-refresh-token-
Create a Spotify App
- Go to Spotify Developer Dashboard
- Create a new app
- Add your redirect URI to the app settings:
- For local development:
http://localhost:5005/spotify/callback - For production:
https://your-domain.com/spotify/callback
- For local development:
- Copy the Client ID and Client Secret
-
Configure the API
# Add to your .env file SPOTIFY_CLIENT_ID=your-client-id SPOTIFY_CLIENT_SECRET=your-client-secret SPOTIFY_REDIRECT_URI=http://localhost:5005/spotify/callback -
Authenticate
- Option A - Browser: Visit
http://localhost:5005/spotify/authand follow the flow - Option B - Headless: Use the setup script:
This script will guide you through manual authentication and help you obtain a refresh token.
./scripts/spotify-auth-setup.sh
- Option A - Browser: Visit
-
Multi-Instance Support
For multiple deployments (e.g., different homes):
# Set a unique instance ID INSTANCE_ID=home-nameEach instance maintains its own token storage in
data/spotify-tokens-{instance-id}.json
For headless deployments, configure your proxy to handle OAuth callbacks:
nginx example:
location /spotify/callback {
proxy_pass http://localhost:5005;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}See the deploy/ directory for complete proxy configuration examples.
The API supports Pandora playback with some important considerations:
The most reliable way to use Pandora with this API is to add your stations as Sonos favorites first. This is the approach we strongly recommend because:
- Reliability - Favorites always work and don't depend on external APIs
- No API Blocks - The unofficial Pandora API can block access or change without notice
- Faster - No need to query external services
- Official Support - Uses Sonos's built-in favorite system
- Open the Sonos app
- Navigate to Pandora and find your station
- Press and hold (or right-click) on the station
- Select "Add to My Sonos" or "Add to Favorites"
- The station is now available via the API:
# List all favorites curl http://localhost:5005/favorites # Play a Pandora favorite curl http://localhost:5005/OfficeSpeakers/favorite/Classic%20Rock%20Radio
The API also supports playing Pandora stations directly by name, but this method:
- Requires Pandora credentials in settings.json
- Uses an unofficial API that may stop working
- Can trigger Pandora's bot detection and block your IP
- Is slower and less reliable
The API now includes automatic bot detection backoff:
- If Pandora blocks a login attempt, the API enters a backoff period starting at 24 hours
- Subsequent failures increase the backoff to 36 hours, then 48 hours maximum
- The backoff resets only after a successful login
- During backoff, all login attempts are blocked locally to prevent further triggering Pandora's bot detection
If you still want to use this method:
{
"pandora": {
"username": "your-pandora-username",
"password": "your-pandora-password"
}
}Then you can play stations directly:
curl http://localhost:5005/OfficeSpeakers/pandora/play/Classic%20Rock%20RadioImportant: When Pandora API credentials are not configured, incorrect, or blocked by Pandora, the API automatically falls back to searching your Sonos favorites. This fallback only works for stations you've already added as favorites in the Sonos app.
- The API automatically manages Pandora session locks using a silence file technique
- Station switching is reliable and takes about 3-5 seconds
- Thumbs up/down functionality is supported
- Station discovery works through both the unofficial API (if credentials are valid) and by browsing your Sonos favorites
- Station cache is automatically refreshed: favorites every 5 minutes, API stations every 24 hours
A common issue occurs when you delete and re-add a Pandora account in Sonos. The old favorites remain but won't play because they reference the deleted account's session number. These "ghost" favorites will fail with SOAP 500/501 errors.
Use the included diagnostic script to find problematic Pandora favorites:
cd scripts
./pandoradump.sh
# Output shows session numbers (SN) for each Pandora favorite:
# Ambient Radio | 25 | 236 | 8296 | ST | 4115366826458437828 | Pandora
# Chicago Blues | 3 | 236 | 8296 | ST | 142640745130511057 | Pandora <- Old SN
# Classic Rock Radio | 25 | 236 | 8296 | ST | 116482263994085703 | PandoraIn this example, "Chicago Blues" has SN=3 while others have SN=25, indicating it's from an old account.
Note about Multiple Pandora Accounts: While the example above assumes a single Pandora account per household, it's technically possible to have multiple valid Pandora accounts with different session numbers. However, this API makes a simplifying assumption:
- Favorites playback: Preserves the original session number from each favorite, so multi-account favorites should work
- Direct station play (
/pandora/play/): Always uses the highest session number found, which may not work for stations from other accounts - This limitation exists because we cannot reliably determine which session numbers are currently valid without attempting to play content
-
Remove the old favorite in the Sonos app:
- Go to My Sonos/Favorites
- Find the problematic station
- Remove it from favorites
-
Re-add from current Pandora account:
- Navigate to Pandora in the Sonos app
- Find the station again
- Add it back to favorites
-
Verify the fix:
./pandoradump.sh # All stations should now show the same SN
When playing stations by name, the API automatically uses the highest session number found. Ghost favorites will still fail to play regardless of the method used. It's best to clean them up for a better experience.
Monitor the authentication state of music services:
# Check Pandora status
curl http://localhost:5005/pandora/status
# Response shows detailed state:
{
"authenticated": true,
"hasCredentials": true,
"authStatus": {
"success": true,
"timestamp": "2025-07-14T18:25:24.428Z"
},
"stationCount": 82,
"apiStations": 68,
"favoriteStations": 0,
"bothSources": 14,
"cacheAge": "5m ago",
"message": "Pandora authenticated - 82 stations (68 from API cached 5m ago, 0 from favorites)"
}
# Check Spotify status
curl http://localhost:5005/spotify/status
# Response shows token state:
{
"authenticated": true,
"hasTokens": true,
"tokenExpired": false,
"hasRefreshToken": true,
"expiresIn": "45m",
"lastAuth": "2025-07-14T18:25:22.831Z",
"authAge": "5m ago",
"message": "Spotify authenticated (token expires in 45m)"
}Monitor the overall server status with the included summary script:
# Text output (default)
./scripts/server-summary.sh localhost 5005
# JSON output for monitoring tools
./scripts/server-summary.sh localhost 5005 --json | jq
# Example JSON output includes:
{
"server": {
"host": "localhost",
"port": 5005,
"version": "1.6.0",
"environment": "development",
"started": "2025-07-14T18:25:22.630Z",
"uptimeSeconds": 3600
},
"entities": {
"devices": 14,
"zones": 11,
"presets": { "valid": 133, "total": 133, "awaitingValidation": false },
"musicServices": 101,
"musicLibrary": { "tracks": 49322, "albums": 3819, "artists": 4621 },
"pandoraStations": 82
},
"readiness": {
"discovery": true,
"servicesCache": true,
"musicLibrary": true,
"upnpSubscriptions": true,
"topology": true,
"allReady": true
},
"authentication": {
"pandora": { /* full status object */ },
"spotify": { /* full status object */ }
}
}The summary script provides:
- Color-coded authentication states (green=authenticated, yellow=partial, red=failed)
- Human-readable cache ages and token expiry times
- Entity counts and system readiness status
- JSON output with proper ISO 8601 timestamps for integration with monitoring tools
The scripts/ directory contains helpful utilities:
server-summary.sh- Compact server status overview with optional JSON outputsonosdump.sh- Raw device state dump for a single Sonos devicepandoradump.sh- Diagnose ghost Pandora favoritesspotify-auth-setup.sh- Manual Spotify OAuth flow for headless systemsanalyze-content.sh- Analyze favorites, presets, and music libraryanalyze-infrastructure.sh- Detailed device and network analysisanalyze-build.sh- Analyze build configuration and startup stateanalyze-auth-failures.sh- Diagnose authentication issues with music servicessonosdebug.sh- Interactive debug control for log levels and categories
This project is built on the excellent foundation of:
- node-sonos-http-api by @jishi - The original HTTP API
- node-sonos-discovery by @jishi - The Sonos discovery library
This rewrite maintains full API compatibility while modernizing the codebase with:
- TypeScript for type safety
- Minimal dependencies (2 vs 50+)
- Modern async/await patterns
- Native Node.js HTTP server
- Comprehensive test coverage
- ✅ Local Music Library
- ✅ Apple Music (via iTunes Search API)
- ✅ Pandora (with account)
- ✅ Line-In playback
- ✅ Spotify (Direct playback + OAuth2 search) - NEW in v1.5.0
- ❌ SiriusXM (no public API)
- ❌ Amazon Music (no public API)
- ❌ Deezer (not implemented)
- Node.js 18+ (uses native Node.js APIs)
- Sonos S2 system (S1 not supported)
- Network access to Sonos devices
MIT License - see LICENSE file for details.
Contributions are welcome! Please read our Contributing Guidelines first.
# Install dependencies
npm install
# Run in development mode (forces LOG_LEVEL=debug, DEBUG_CATEGORIES=all)
npm run dev
# Run tests
npm test
# Run specific test file
npm test -- integration/playback-tests.ts
# Build for production
npm run buildThe project includes tools for analyzing your Sonos system:
# Analyze system infrastructure
./analyze-infrastructure.sh [home-name] [api-url]
# Analyze content (favorites, presets, music library)
./analyze-content.sh [home-name] [api-url] [room-name]These tools generate detailed reports in the homes/ directory documenting your system configuration, device capabilities, and content. The content analyzer creates:
content-analysis.md- Favorites breakdown by type and servicepreset-validation-results.md- Preset validation statusmusic-library-analysis.md- Library statistics and top artists/albumsmusic-library.json- Complete track database (optimized, pretty-printed with jq)
For detailed Docker deployment instructions, environment variables, and configuration options, see DOCKER.md.
The API supports optional HTTP Basic Authentication with trusted network bypass:
- Set credentials in
settings.json - Configure trusted networks (CIDR notation supported)
- Requests from trusted networks bypass authentication
- All other requests require authentication
For HTTPS, use a reverse proxy like nginx, Apache, Caddy, or HAProxy. See deploy/ for example nginx and Apache configurations.
- No devices found: Ensure the API server is on the same network as your Sonos devices
- Authentication errors: Check your credentials and trusted networks configuration
- Slow music library: The library indexes on startup; large libraries may take 10-30 seconds
- Docker networking: Use
--network hostfor SSDP discovery to work