diff --git a/Makefile b/Makefile index 920aa5a..b428ff0 100644 --- a/Makefile +++ b/Makefile @@ -124,6 +124,7 @@ test-http-client: /workdir/customer_support.http \ /workdir/power_on.http \ /workdir/get_provider_settings.http \ + /workdir/tunein_playback_station.http \ /workdir/get_full_account.http \ /workdir/get_group.http \ /workdir/unregister_device.http \ diff --git a/cmd/soundtouch-service/main.go b/cmd/soundtouch-service/main.go index 735803f..b9e497f 100644 --- a/cmd/soundtouch-service/main.go +++ b/cmd/soundtouch-service/main.go @@ -666,6 +666,7 @@ func setupRouter(server *handlers.Server) *chi.Mux { r.Get("/v1/playback/station/{stationID}", server.HandleTuneInPlayback) r.Get("/v1/playback/episodes/{podcastID}", server.HandleTuneInPodcastInfo) r.Get("/v1/playback/episode/{podcastID}", server.HandleTuneInPlaybackPodcast) + r.Post("/v1/token", server.HandleTuneInToken) }) r.Post("/orion/v1/playback/station/{data}", server.HandleOrionPlayback) diff --git a/cmd/soundtouch-service/testdata/router_routes.txt b/cmd/soundtouch-service/testdata/router_routes.txt index 4f27e27..afee359 100644 --- a/cmd/soundtouch-service/testdata/router_routes.txt +++ b/cmd/soundtouch-service/testdata/router_routes.txt @@ -71,6 +71,7 @@ POST /accounts/{account}/devices handlers.( POST /accounts/{account}/devices/{device}/presets/{presetNumber} handlers.(*Server).HandleMargeUpdatePreset-fm POST /accounts/{account}/devices/{device}/recents handlers.(*Server).HandleMargeAddRecent-fm POST /bmx/orion/v1/playback/station/{data} handlers.(*Server).HandleOrionPlayback-fm +POST /bmx/tunein/v1/token handlers.(*Server).HandleTuneInToken-fm POST /customer/account/{account} handlers.(*Server).HandleMargeUpdateAccountProfile-fm POST /customer/account/{account}/password handlers.(*Server).HandleMargeChangePassword-fm POST /mgmt/accounts/{accountId}/language handlers.(*Server).HandleMgmtUpdateAccountLanguage-fm diff --git a/pkg/service/handlers/handlers_bmx.go b/pkg/service/handlers/handlers_bmx.go index 98d58e1..51fc743 100644 --- a/pkg/service/handlers/handlers_bmx.go +++ b/pkg/service/handlers/handlers_bmx.go @@ -33,8 +33,24 @@ func (s *Server) HandleBMXRegistry(w http.ResponseWriter, _ *http.Request) { _, _ = w.Write([]byte(content)) } +func (s *Server) writeBMXUnauthorized(w http.ResponseWriter) { + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.WriteHeader(http.StatusUnauthorized) + _, _ = w.Write([]byte(` + +
Authorization not set. No access token found.
+`)) +} + // HandleTuneInPlayback returns TuneIn playback information. func (s *Server) HandleTuneInPlayback(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Authorization") == "" { + s.writeBMXUnauthorized(w) + return + } + stationID := chi.URLParam(r, "stationID") resp, err := bmx.TuneInPlayback(stationID) @@ -53,6 +69,11 @@ func (s *Server) HandleTuneInPlayback(w http.ResponseWriter, r *http.Request) { // HandleTuneInPodcastInfo returns TuneIn podcast information. func (s *Server) HandleTuneInPodcastInfo(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Authorization") == "" { + s.writeBMXUnauthorized(w) + return + } + podcastID := chi.URLParam(r, "podcastID") encodedName := r.URL.Query().Get("encoded_name") @@ -72,6 +93,11 @@ func (s *Server) HandleTuneInPodcastInfo(w http.ResponseWriter, r *http.Request) // HandleTuneInPlaybackPodcast returns TuneIn podcast playback information. func (s *Server) HandleTuneInPlaybackPodcast(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Authorization") == "" { + s.writeBMXUnauthorized(w) + return + } + podcastID := chi.URLParam(r, "podcastID") resp, err := bmx.TuneInPlaybackPodcast(podcastID) @@ -88,8 +114,40 @@ func (s *Server) HandleTuneInPlaybackPodcast(w http.ResponseWriter, r *http.Requ } } +// HandleTuneInToken returns a TuneIn access token. +func (s *Server) HandleTuneInToken(w http.ResponseWriter, r *http.Request) { + var req struct { + GrantType string `json:"grant_type"` + RefreshToken string `json:"refresh_token"` + } + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "Invalid request", http.StatusBadRequest) + return + } + + // For now, we return the provided refresh_token as access_token and refresh_token, + // mirroring the behavior seen in the recordings. + resp := map[string]string{ + "access_token": req.RefreshToken, + "refresh_token": req.RefreshToken, + } + + w.Header().Set("Content-Type", "application/json") + + if err := json.NewEncoder(w).Encode(resp); err != nil { + http.Error(w, "Failed to encode response", http.StatusInternalServerError) + return + } +} + // HandleOrionPlayback returns Orion playback information. func (s *Server) HandleOrionPlayback(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Authorization") == "" { + s.writeBMXUnauthorized(w) + return + } + data := chi.URLParam(r, "data") resp, err := bmx.PlayCustomStream(data) diff --git a/pkg/service/handlers/handlers_bmx_test.go b/pkg/service/handlers/handlers_bmx_test.go index ecfc455..949b6c6 100644 --- a/pkg/service/handlers/handlers_bmx_test.go +++ b/pkg/service/handlers/handlers_bmx_test.go @@ -87,7 +87,9 @@ func TestOrionPlayback(t *testing.T) { // Base64 encoded: {"streamUrl": "http://example.com/stream", "imageUrl": "http://example.com/img.jpg", "name": "Test Orion"} data := "eyJzdHJlYW1VcmwiOiAiaHR0cDovL2V4YW1wbGUuY29tL3N0cmVhbSIsICJpbWFnZVVybCI6ICJodHRwOi8vZXhhbXBsZS5jb20vaW1nLmpwZyIsICJuYW1lIjogIlRlc3QgT3Jpb24ifQ==" - res, err := http.Post(ts.URL+"/bmx/orion/v1/playback/station/"+data, "application/json", nil) + req, _ := http.NewRequest("POST", ts.URL+"/bmx/orion/v1/playback/station/"+data, nil) + req.Header.Set("Authorization", "Bearer mock-token") + res, err := http.DefaultClient.Do(req) if err != nil { t.Fatal(err) } @@ -149,3 +151,103 @@ func TestCustomPlayback(t *testing.T) { t.Errorf("Expected imageUrl %s, got %v", imageUrl, resp["imageUrl"]) } } + +func TestBMXUnauthorized(t *testing.T) { + r, _ := setupRouter("http://localhost:8001", nil) + + ts := httptest.NewServer(r) + defer ts.Close() + + paths := []struct { + method string + path string + }{ + {"GET", "/bmx/tunein/v1/playback/station/s123"}, + {"GET", "/bmx/tunein/v1/playback/episodes/p123"}, + {"GET", "/bmx/tunein/v1/playback/episode/p123"}, + {"POST", "/bmx/orion/v1/playback/station/data"}, + } + + for _, tc := range paths { + req, _ := http.NewRequest(tc.method, ts.URL+tc.path, nil) + res, err := http.DefaultClient.Do(req) + if err != nil { + t.Errorf("%s %s: %v", tc.method, tc.path, err) + continue + } + defer res.Body.Close() + + if res.StatusCode != http.StatusUnauthorized { + t.Errorf("%s %s: Expected status 401, got %v", tc.method, tc.path, res.Status) + } + + body, _ := io.ReadAll(res.Body) + bodyStr := string(body) + if !strings.Contains(bodyStr, "401 Unauthorized") || !strings.Contains(bodyStr, "No access token found.") { + t.Errorf("%s %s: Unexpected response body: %s", tc.method, tc.path, bodyStr) + } + } +} + +func TestHandleTuneInToken(t *testing.T) { + r, s := setupRouter("http://localhost:8001", nil) + s.SetMirrorSettings(false, nil, nil, "") + + ts := httptest.NewServer(r) + defer ts.Close() + + payload := `{"grant_type":"refresh_token","refresh_token":"test-refresh-token"}` + res, err := http.Post(ts.URL+"/bmx/tunein/v1/token", "application/json", strings.NewReader(payload)) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + + if res.StatusCode != http.StatusOK { + t.Errorf("Expected status 200, got %v", res.Status) + } + + var resp map[string]string + if err := json.NewDecoder(res.Body).Decode(&resp); err != nil { + t.Fatal(err) + } + + if resp["access_token"] != "test-refresh-token" { + t.Errorf("Expected access_token 'test-refresh-token', got %v", resp["access_token"]) + } + if resp["refresh_token"] != "test-refresh-token" { + t.Errorf("Expected refresh_token 'test-refresh-token', got %v", resp["refresh_token"]) + } +} + +func TestHandleTuneInPlayback_Authorized(t *testing.T) { + r, s := setupRouter("http://localhost:8001", nil) + s.SetMirrorSettings(false, nil, nil, "") + + ts := httptest.NewServer(r) + defer ts.Close() + + req, _ := http.NewRequest("GET", ts.URL+"/bmx/tunein/v1/playback/station/s166521", nil) + req.Header.Set("Authorization", "Bearer mock-token") + res, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + + if res.StatusCode != http.StatusOK { + t.Errorf("Expected status 200, got %v", res.Status) + } + + var resp map[string]interface{} + if err := json.NewDecoder(res.Body).Decode(&resp); err != nil { + t.Fatal(err) + } + + if resp["name"] == "" { + t.Errorf("Expected station name, got empty") + } + if audio, ok := resp["audio"].(map[string]interface{}); !ok || audio["streamUrl"] == "" { + t.Errorf("Expected audio streamUrl, got %v", resp["audio"]) + } +} diff --git a/pkg/service/handlers/main_test.go b/pkg/service/handlers/main_test.go index 5e27d68..7f2d016 100644 --- a/pkg/service/handlers/main_test.go +++ b/pkg/service/handlers/main_test.go @@ -26,15 +26,10 @@ func setupRouter(targetURL string, ds *datastore.DataStore) (*chi.Mux, *Server) r.Get("/tunein/v1/playback/station/{stationID}", server.HandleTuneInPlayback) r.Get("/tunein/v1/playback/episodes/{podcastID}", server.HandleTuneInPodcastInfo) r.Get("/tunein/v1/playback/episode/{podcastID}", server.HandleTuneInPlaybackPodcast) + r.Post("/tunein/v1/token", server.HandleTuneInToken) r.Post("/orion/v1/playback/station/{data}", server.HandleOrionPlayback) }) - // Legacy or direct domain calls without /bmx prefix - r.Get("/registry/v1/services", server.HandleBMXRegistry) - r.Get("/tunein/v1/playback/station/{stationID}", server.HandleTuneInPlayback) - r.Get("/tunein/v1/playback/episodes/{podcastID}", server.HandleTuneInPodcastInfo) - r.Get("/tunein/v1/playback/episode/{podcastID}", server.HandleTuneInPlaybackPodcast) - r.Post("/orion/v1/playback/station/{data}", server.HandleOrionPlayback) r.Get("/custom/v1/playback/{encodedURL}", server.HandleCustomPlayback) streamingRoutes := func(r chi.Router) { diff --git a/tests/.gitignore b/tests/.gitignore index 8fce603..f589fcf 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1 +1,2 @@ +2026*/ data/ diff --git a/tests/integration/http-client/tunein_playback_station.http b/tests/integration/http-client/tunein_playback_station.http new file mode 100644 index 0000000..77985ad --- /dev/null +++ b/tests/integration/http-client/tunein_playback_station.http @@ -0,0 +1,65 @@ +### GET /bmx/tunein/v1/playback/station/_station_ +GET {{host}}/bmx/tunein/v1/playback/station/_station_ +Host: content.api.bose.io +Accept: */* +Accept-Language: en +X-Bmx-Api-Key: bmx-api-key-dummy +X-Bmx-Device-Id: bmx-device-id-dummy +User-Agent: Bose_Lisa/27.0.6 + +> {% + client.test("Response is 401 Unauthorized", function() { + client.assert(response.status === 401, "Response status is not 401"); + }); + + client.test("Response body contains 'Unauthorized'", function() { + client.assert(response.body.includes("401 Unauthorized"), "Response body does not contain '401 Unauthorized'"); + client.assert(response.body.includes("No access token found."), "Response body does not contain 'No access token found.'"); + }); +%} + +### POST /bmx/tunein/v1/token +POST {{host}}/bmx/tunein/v1/token +Host: content.api.bose.io +User-Agent: Bose_Lisa/27.0.6 +Accept: */* +Accept-Language: en +X-Bmx-Api-Key: bmx-api-key-dummy +X-Bmx-Device-Id: bmx-device-id-dummy +Content-Type: application/json + +{"grant_type":"refresh_token","refresh_token":"eyJzZXJpYWwiOiAiY2NiZTkzNDMtYjY0MS00MjMxLWFhYTAtOTI3NTBmNjhjMjY3In0="} + +> {% + client.test("Response is 200 OK", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + + client.test("Response contains access_token and refresh_token", function() { + client.assert(response.body.hasOwnProperty("access_token"), "Response missing 'access_token'"); + client.assert(response.body.hasOwnProperty("refresh_token"), "Response missing 'refresh_token'"); + }); + + client.global.set("bmx_access_token", response.body.access_token); +%} + +### GET /bmx/tunein/v1/playback/station/_station_ (Authorized) +GET {{host}}/bmx/tunein/v1/playback/station/_station_ +Host: content.api.bose.io +User-Agent: Bose_Lisa/27.0.6 +Accept: */* +Accept-Language: en +Authorization: {{bmx_access_token}} +X-Bmx-Api-Key: bmx-api-key-dummy +X-Bmx-Device-Id: bmx-device-id-dummy + +> {% + client.test("Response is 200 OK", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + + client.test("Response contains audio information", function() { + client.assert(response.body.hasOwnProperty("audio"), "Response missing 'audio'"); + client.assert(response.body.audio.hasOwnProperty("streamUrl"), "Response missing 'streamUrl'"); + }); +%} diff --git a/tests/interactions_20260328-103522-477978.md b/tests/interactions_20260328-103522-477978.md new file mode 100644 index 0000000..8cd0a8a --- /dev/null +++ b/tests/interactions_20260328-103522-477978.md @@ -0,0 +1,249 @@ +Interactions for `20260328-103522-477978/`: + +| sequence number | category | ignore/done | request | response status | filename | +|-----------------|----------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------|--------------------------------------------------------------------------------------------------------| +| 0001 | self | ☑ | GET / | 200 OK | ./self/root/0001-20260328-103539.205-GET.http | +| 0002 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0002-20260328-103539.483-GET.http | +| 0003 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0003-20260328-103539.514-GET.http | +| 0004 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0004-20260328-103539.539-GET.http | +| 0005 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0005-20260328-103539.554-GET.http | +| 0006 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0006-20260328-103551.537-GET.http | +| 0007 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0007-20260328-103551.551-GET.http | +| 0008 | self | | GET /bmx/registry/v1/services | 200 OK | ./self/bmx/registry/v1/services/0008-20260328-103731.202-GET.http | +| 0009 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0009-20260328-103731.221-POST.http | +| 0010 | self | | POST /streaming/support/power_on | 200 OK | ./self/streaming/support/power_on/0010-20260328-103731.226-POST.http | +| 0011 | mirror | | POST /streaming/support/power_on | 200 OK | ./mirror/streaming/support/power_on/0011-20260328-103731.407-POST.http | +| 0012 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0012-20260328-103731.625-POST.http | +| 0013 | mirror | | GET /bmx/registry/v1/services | 200 OK | ./mirror/bmx/registry/v1/services/0013-20260328-103731.641-GET.http | +| 0014 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0014-20260328-103731.652-POST.http | +| 0015 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0015-20260328-103731.725-POST.http | +| 0016 | self | ☑ | GET / | 200 OK | ./self/root/0016-20260328-103731.804-GET.http | +| 0017 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0017-20260328-103731.806-POST.http | +| 0018 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0018-20260328-103732.053-POST.http | +| 0019 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0019-20260328-103732.173-POST.http | +| 0020 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0020-20260328-103732.229-POST.http | +| 0021 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0021-20260328-103733.180-POST.http | +| 0022 | self | | GET /streaming/sourceproviders | 200 OK | ./self/streaming/sourceproviders/0022-20260328-103733.439-GET.http | +| 0023 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0023-20260328-103733.587-POST.http | +| 0024 | self | | GET /streaming/account/{{accountId}}/full | 200 OK | ./self/streaming/account/{accountId}/full/0024-20260328-103733.945-GET.http | +| 0025 | mirror | | GET /streaming/account/{{accountId}}/full | 200 OK | ./mirror/streaming/account/{accountId}/full/0025-20260328-103734.751-GET.http | +| 0026 | self | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./self/streaming/account/{accountId}/provider_settings/0026-20260328-103735.894-GET.http | +| 0027 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0027-20260328-103735.914-GET.http | +| 0028 | self | | GET /streaming/device/{{device_id}}/streaming_token | 200 OK | ./self/streaming/device/{device_id}/streaming_token/0028-20260328-103735.931-GET.http | +| 0029 | self | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./self/streaming/account/{accountId}/provider_settings/0029-20260328-103735.954-GET.http | +| 0030 | mirror | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./mirror/streaming/account/{accountId}/provider_settings/0030-20260328-103736.065-GET.http | +| 0031 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0031-20260328-103736.093-GET.http | +| 0032 | mirror | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./mirror/streaming/account/{accountId}/provider_settings/0032-20260328-103736.130-GET.http | +| 0033 | self | | POST /oauth/device/{{device_id}}/music/musicprovider/15/token/cs3 | 200 OK | ./self/oauth/device/{device_id}/music/musicprovider/15/token/cs3/0033-20260328-103737.874-POST.http | +| 0034 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/presets | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/presets/0034-20260328-103905.297-GET.http | +| 0035 | self | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./self/streaming/software/update/account/{accountId}/0035-20260328-103905.306-GET.http | +| 0036 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/presets | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/presets/0036-20260328-103905.479-GET.http | +| 0037 | mirror | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./mirror/streaming/software/update/account/{accountId}/0037-20260328-103905.669-GET.http | +| 0038 | self | | GET /updates/soundtouch?serialnumber=_serial_ | 200 OK | ./self/updates/soundtouch/0038-20260328-103905.929-GET.http | +| 0039 | self | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./self/streaming/software/update/account/{accountId}/0039-20260328-104218.080-GET.http | +| 0040 | mirror | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./mirror/streaming/software/update/account/{accountId}/0040-20260328-104218.267-GET.http | +| 0041 | self | | GET /updates/soundtouch?serialnumber=_serial_ | 200 OK | ./self/updates/soundtouch/0041-20260328-104218.524-GET.http | +| 0042 | self | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./self/streaming/software/update/account/{accountId}/0042-20260328-104325.629-GET.http | +| 0043 | mirror | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./mirror/streaming/software/update/account/{accountId}/0043-20260328-104325.814-GET.http | +| 0044 | self | | GET /updates/soundtouch?serialnumber=_serial_ | 200 OK | ./self/updates/soundtouch/0044-20260328-104326.087-GET.http | +| 0045 | upstream | | DELETE https://streaming.bose.com/streaming/account/{{accountId}}/device/{{device_id}} | 400 Bad Request | ./upstream/streaming/account/{accountId}/device/{device_id}/0045-20260328-104348.987-DELETE.http | +| 0046 | self | | DELETE /streaming/account/{{accountId}}/device/{{device_id}} | 400 Bad Request | ./self/streaming/account/{accountId}/device/{device_id}/0046-20260328-104348.988-DELETE.http | +| 0047 | mirror | | DELETE /streaming/account/{{accountId}}/device/{{device_id}} | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/0047-20260328-104348.989-DELETE.http | +| 0048 | self | | POST /streaming/support/power_on | 200 OK | ./self/streaming/support/power_on/0048-20260328-104523.826-POST.http | +| 0049 | self | | GET /bmx/registry/v1/services | 200 OK | ./self/bmx/registry/v1/services/0049-20260328-104523.828-GET.http | +| 0050 | mirror | | POST /streaming/support/power_on | 400 Bad Request | ./mirror/streaming/support/power_on/0050-20260328-104524.002-POST.http | +| 0051 | mirror | | GET /bmx/registry/v1/services | 200 OK | ./mirror/bmx/registry/v1/services/0051-20260328-104524.277-GET.http | +| 0052 | mirror | ☑ | POST /streaming/account/{{accountId}}/device/ | 500 Internal Server Error | ./mirror/streaming/account/{accountId}/device/0052-20260328-105134.442-POST.http | +| 0053 | upstream | ☑ | POST https://streaming.bose.com/streaming/account/{{accountId}}/device/ | 201 Created | ./upstream/streaming/account/{accountId}/device/0053-20260328-105134.482-POST.http | +| 0054 | self | ☑ | POST /streaming/account/{{accountId}}/device/ | 201 Created | ./self/streaming/account/{accountId}/device/0054-20260328-105134.483-POST.http | +| 0055 | self | | GET /streaming/sourceproviders | 200 OK | ./self/streaming/sourceproviders/0055-20260328-105134.757-GET.http | +| 0056 | self | | GET /streaming/account/{{accountId}}/full | 200 OK | ./self/streaming/account/{accountId}/full/0056-20260328-105135.102-GET.http | +| 0057 | mirror | | GET /streaming/account/{{accountId}}/full | 200 OK | ./mirror/streaming/account/{accountId}/full/0057-20260328-105135.727-GET.http | +| 0058 | self | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./self/streaming/account/{accountId}/provider_settings/0058-20260328-105138.259-GET.http | +| 0059 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0059-20260328-105138.265-GET.http | +| 0060 | self | | POST /streaming/support/customersupport | 200 OK | ./self/streaming/support/customersupport/0060-20260328-105138.304-POST.http | +| 0061 | self | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./self/streaming/account/{accountId}/provider_settings/0061-20260328-105138.369-GET.http | +| 0062 | mirror | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./mirror/streaming/account/{accountId}/provider_settings/0062-20260328-105138.442-GET.http | +| 0063 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0063-20260328-105138.464-GET.http | +| 0064 | mirror | ☑ | POST /streaming/support/customersupport | 200 OK | ./mirror/streaming/support/customersupport/0064-20260328-105138.499-POST.http | +| 0065 | mirror | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./mirror/streaming/account/{accountId}/provider_settings/0065-20260328-105138.554-GET.http | +| 0066 | upstream | | GET https://events.api.bosecm.com/v1/blacklist/{{device_id}} | 405 Method Not Allowed | ./upstream/v1/blacklist/{device_id}/0066-20260328-105138.587-GET.http | +| 0067 | self | | GET /v1/blacklist/{{device_id}} | 405 Method Not Allowed | ./self/v1/blacklist/{device_id}/0067-20260328-105138.588-GET.http | +| 0068 | self | | GET /streaming/device/{{device_id}}/streaming_token | 200 OK | ./self/streaming/device/{device_id}/streaming_token/0068-20260328-105138.703-GET.http | +| 0069 | self | ☑ | GET / | 200 OK | ./self/root/0069-20260328-105138.868-GET.http | +| 0070 | self | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./self/streaming/software/update/account/{accountId}/0070-20260328-105139.565-GET.http | +| 0071 | self | | GET /streaming/sourceproviders | 200 OK | ./self/streaming/sourceproviders/0071-20260328-105139.581-GET.http | +| 0072 | self | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./self/streaming/account/{accountId}/provider_settings/0072-20260328-105139.612-GET.http | +| 0073 | mirror | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./mirror/streaming/software/update/account/{accountId}/0073-20260328-105139.857-GET.http | +| 0074 | mirror | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./mirror/streaming/account/{accountId}/provider_settings/0074-20260328-105139.861-GET.http | +| 0075 | self | | GET /streaming/account/{{accountId}}/full | 200 OK | ./self/streaming/account/{accountId}/full/0075-20260328-105140.030-GET.http | +| 0076 | mirror | | GET /streaming/account/{{accountId}}/full | 200 OK | ./mirror/streaming/account/{accountId}/full/0076-20260328-105140.172-GET.http | +| 0077 | self | | GET /updates/soundtouch?serialnumber=_serial_ | 200 OK | ./self/updates/soundtouch/0077-20260328-105140.196-GET.http | +| 0078 | upstream | | GET https://events.api.bosecm.com/v1/blacklist/{{device_id}} | 405 Method Not Allowed | ./upstream/v1/blacklist/{device_id}/0078-20260328-105146.094-GET.http | +| 0079 | self | | GET /v1/blacklist/{{device_id}} | 405 Method Not Allowed | ./self/v1/blacklist/{device_id}/0079-20260328-105146.094-GET.http | +| 0080 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0080-20260328-105146.457-POST.http | +| 0081 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0081-20260328-105146.867-POST.http | +| 0082 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0082-20260328-105148.464-POST.http | +| 0083 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0083-20260328-105148.876-POST.http | +| 0084 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0084-20260328-105549.637-POST.http | +| 0085 | self | | GET /bmx/registry/v1/services | 200 OK | ./self/bmx/registry/v1/services/0085-20260328-105549.645-GET.http | +| 0086 | self | | POST /streaming/support/power_on | 200 OK | ./self/streaming/support/power_on/0086-20260328-105549.665-POST.http | +| 0087 | mirror | | POST /streaming/support/power_on | 200 OK | ./mirror/streaming/support/power_on/0087-20260328-105549.864-POST.http | +| 0088 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0088-20260328-105550.089-POST.http | +| 0089 | mirror | | GET /bmx/registry/v1/services | 200 OK | ./mirror/bmx/registry/v1/services/0089-20260328-105550.097-GET.http | +| 0090 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0090-20260328-105551.010-POST.http | +| 0091 | self | ☑ | GET / | 200 OK | ./self/root/0091-20260328-105551.041-GET.http | +| 0092 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0092-20260328-105551.096-POST.http | +| 0093 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0093-20260328-105551.181-POST.http | +| 0094 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0094-20260328-105551.431-POST.http | +| 0095 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0095-20260328-105551.503-POST.http | +| 0096 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0096-20260328-105551.592-POST.http | +| 0097 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0097-20260328-105552.101-POST.http | +| 0098 | self | | GET /streaming/sourceproviders | 200 OK | ./self/streaming/sourceproviders/0098-20260328-105552.239-GET.http | +| 0099 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0099-20260328-105552.510-POST.http | +| 0100 | self | | GET /streaming/account/{{accountId}}/full | 200 OK | ./self/streaming/account/{accountId}/full/0100-20260328-105552.656-GET.http | +| 0101 | mirror | | GET /streaming/account/{{accountId}}/full | 200 OK | ./mirror/streaming/account/{accountId}/full/0101-20260328-105552.796-GET.http | +| 0102 | self | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./self/streaming/account/{accountId}/provider_settings/0102-20260328-105554.172-GET.http | +| 0103 | self | | GET /streaming/device/{{device_id}}/streaming_token | 200 OK | ./self/streaming/device/{device_id}/streaming_token/0103-20260328-105554.207-GET.http | +| 0104 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0104-20260328-105554.210-GET.http | +| 0105 | self | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./self/streaming/account/{accountId}/provider_settings/0105-20260328-105554.216-GET.http | +| 0106 | mirror | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./mirror/streaming/account/{accountId}/provider_settings/0106-20260328-105554.347-GET.http | +| 0107 | mirror | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./mirror/streaming/account/{accountId}/provider_settings/0107-20260328-105554.395-GET.http | +| 0108 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0108-20260328-105554.406-GET.http | +| 0109 | self | | POST /oauth/device/{{device_id}}/music/musicprovider/15/token/cs3 | 200 OK | ./self/oauth/device/{device_id}/music/musicprovider/15/token/cs3/0109-20260328-105556.138-POST.http | +| 0110 | self | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./self/streaming/software/update/account/{accountId}/0110-20260328-105606.529-GET.http | +| 0111 | mirror | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./mirror/streaming/software/update/account/{accountId}/0111-20260328-105606.699-GET.http | +| 0112 | self | | GET /updates/soundtouch?serialnumber=_serial_ | 200 OK | ./self/updates/soundtouch/0112-20260328-105606.961-GET.http | +| 0113 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0113-20260328-105612.425-POST.http | +| 0114 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0114-20260328-105612.493-POST.http | +| 0115 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0115-20260328-105612.582-POST.http | +| 0116 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0116-20260328-105612.851-POST.http | +| 0117 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0117-20260328-105612.906-POST.http | +| 0118 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0118-20260328-105613.000-POST.http | +| 0119 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0119-20260328-105614.239-POST.http | +| 0120 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0120-20260328-105614.649-POST.http | +| 0121 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0121-20260328-111412.273-POST.http | +| 0122 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0122-20260328-111412.689-POST.http | +| 0123 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0123-20260328-170446.020-GET.http | +| 0124 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0124-20260328-170446.206-GET.http | +| 0125 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0125-20260328-202258.172-GET.http | +| 0126 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0126-20260328-202258.374-GET.http | +| 0127 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0127-20260328-202300.656-GET.http | +| 0128 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0128-20260328-202300.841-GET.http | +| 0129 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0129-20260328-205953.361-GET.http | +| 0130 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0130-20260328-205953.560-GET.http | +| 0131 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0131-20260328-210005.518-GET.http | +| 0132 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0132-20260328-210005.707-GET.http | +| 0133 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0133-20260329-094502.893-GET.http | +| 0134 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0134-20260329-094503.109-GET.http | +| 0135 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0135-20260329-094510.575-GET.http | +| 0136 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0136-20260329-094510.907-GET.http | +| 0137 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0137-20260329-102911.229-GET.http | +| 0138 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0138-20260329-102911.443-GET.http | +| 0139 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0139-20260329-102923.636-GET.http | +| 0140 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0140-20260329-102923.807-GET.http | +| 0141 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0141-20260329-155214.420-GET.http | +| 0142 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0142-20260329-155216.805-GET.http | +| 0143 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0143-20260329-155221.905-GET.http | +| 0144 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0144-20260329-155222.082-GET.http | +| 0145 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/recents | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/recents/0145-20260329-185442.017-GET.http | +| 0146 | upstream | | GET https://streaming.bose.com/streaming/account/{{accountId}}/device/{{device_id}}/recents | 200 OK | ./upstream/streaming/account/{accountId}/device/{device_id}/recents/0146-20260329-185442.128-GET.http | +| 0147 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/recents | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/recents/0147-20260329-185442.130-GET.http | +| 0148 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0148-20260329-193915.264-GET.http | +| 0149 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0149-20260329-193915.468-GET.http | +| 0150 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0150-20260329-215246.808-GET.http | +| 0151 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0151-20260329-215247.001-GET.http | +| 0152 | self | ☑ | GET / | 200 OK | ./self/root/0152-20260329-233126.264-GET.http | +| 0153 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0153-20260329-233126.506-GET.http | +| 0154 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0154-20260329-233126.515-GET.http | +| 0155 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0155-20260329-233126.531-GET.http | +| 0156 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0156-20260329-233126.542-GET.http | +| 0157 | self | ☑ | GET / | 200 OK | ./self/root/0157-20260329-233128.611-GET.http | +| 0158 | self | ☑ | GET / | 200 OK | ./self/root/0158-20260329-233128.790-GET.http | +| 0159 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0159-20260329-233129.065-GET.http | +| 0160 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0160-20260329-233129.089-GET.http | +| 0161 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0161-20260329-233129.099-GET.http | +| 0162 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0162-20260329-233129.105-GET.http | +| 0163 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0163-20260329-233137.103-GET.http | +| 0164 | self | ☑ | GET /mgmt/spotify/accounts | 200 OK | ./self/mgmt/spotify/accounts/0164-20260329-233137.130-GET.http | +| 0165 | self | ☑ | GET /mgmt/accounts | 200 OK | ./self/mgmt/accounts/0165-20260329-233206.623-GET.http | +| 0166 | self | ☑ | GET /mgmt/accounts/{{accountId}} | 200 OK | ./self/mgmt/accounts/{accountId}/0166-20260329-233206.693-GET.http | +| 0167 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0167-20260329-233249.970-POST.http | +| 0168 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0168-20260329-233250.408-POST.http | +| 0169 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0169-20260329-233257.652-POST.http | +| 0170 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0170-20260329-233257.674-POST.http | +| 0171 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0171-20260329-233258.075-POST.http | +| 0172 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0172-20260329-233258.097-POST.http | +| 0173 | mirror | ☑ | GET /bmx/tunein/v1/playback/station/s166521 | 401 Unauthorized | ./mirror/bmx/tunein/v1/playback/station/s166521/0173-20260329-233258.121-GET.http | +| 0174 | self | ☑ | GET /bmx/tunein/v1/playback/station/s166521 | 200 OK | ./self/bmx/tunein/v1/playback/station/s166521/0174-20260329-233258.171-GET.http | +| 0175 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0175-20260329-233258.625-POST.http | +| 0176 | upstream | ☑ | POST https://content.api.bose.io/bmx/tunein/v1/token | 200 OK | ./upstream/bmx/tunein/v1/token/0176-20260329-233259.006-POST.http | +| 0177 | self | ☑ | POST /bmx/tunein/v1/token | 200 OK | ./self/bmx/tunein/v1/token/0177-20260329-233259.008-POST.http | +| 0178 | mirror | ☑ | POST /bmx/tunein/v1/token | 200 OK | ./mirror/bmx/tunein/v1/token/0178-20260329-233259.013-POST.http | +| 0179 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0179-20260329-233259.046-POST.http | +| 0180 | self | ☑ | GET /bmx/tunein/v1/playback/station/s166521 | 200 OK | ./self/bmx/tunein/v1/playback/station/s166521/0180-20260329-233259.719-GET.http | +| 0181 | mirror | ☑ | GET /bmx/tunein/v1/playback/station/s166521 | 200 OK | ./mirror/bmx/tunein/v1/playback/station/s166521/0181-20260329-233300.084-GET.http | +| 0182 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0182-20260329-233302.393-POST.http | +| 0183 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0183-20260329-233302.636-POST.http | +| 0184 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0184-20260329-233302.655-POST.http | +| 0185 | self | | POST /streaming/account/{{accountId}}/device/{{device_id}}/recent | 201 Created | ./self/streaming/account/{accountId}/device/{device_id}/recent/0185-20260329-233302.671-POST.http | +| 0186 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0186-20260329-233302.906-POST.http | +| 0187 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0187-20260329-233303.115-POST.http | +| 0188 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0188-20260329-233303.118-POST.http | +| 0189 | mirror | | POST /streaming/account/{{accountId}}/device/{{device_id}}/recent | 201 Created | ./mirror/streaming/account/{accountId}/device/{device_id}/recent/0189-20260329-233303.759-POST.http | +| 0190 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0190-20260329-233304.143-POST.http | +| 0191 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0191-20260329-233304.269-POST.http | +| 0192 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0192-20260329-233304.554-POST.http | +| 0193 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0193-20260329-233304.685-POST.http | +| 0194 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0194-20260329-233305.629-POST.http | +| 0195 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0195-20260329-233306.040-POST.http | +| 0196 | mirror | | POST /bmx/tunein/v1/report?stream_id=e536753726&guide_id=s166521&listen_id=1774819980&stream_type=liveRadio | 200 OK | ./mirror/bmx/tunein/v1/report/0196-20260329-233306.072-POST.http | +| 0197 | upstream | | POST https://content.api.bose.io/bmx/tunein/v1/report?stream_id=e536753726&guide_id=s166521&listen_id=1774819980&stream_type=liveRadio | 200 OK | ./upstream/bmx/tunein/v1/report/0197-20260329-233306.182-POST.http | +| 0198 | self | | POST /bmx/tunein/v1/report?stream_id=e536753726&guide_id=s166521&listen_id=1774819980&stream_type=liveRadio | 200 OK | ./self/bmx/tunein/v1/report/0198-20260329-233306.184-POST.http | +| 0199 | self | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./self/streaming/software/update/account/{accountId}/0199-20260329-233317.196-GET.http | +| 0200 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/presets | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/presets/0200-20260329-233317.206-GET.http | +| 0201 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/presets | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/presets/0201-20260329-233317.394-GET.http | +| 0202 | mirror | | GET /streaming/software/update/account/{{accountId}} | 200 OK | ./mirror/streaming/software/update/account/{accountId}/0202-20260329-233317.409-GET.http | +| 0203 | self | | GET /updates/soundtouch?serialnumber=_serial_ | 200 OK | ./self/updates/soundtouch/0203-20260329-233317.838-GET.http | +| 0204 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0204-20260329-233330.871-POST.http | +| 0205 | mirror | | PUT /streaming/account/{{accountId}}/device/{{device_id}}/preset/6 | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/preset/6/0205-20260329-233331.093-PUT.http | +| 0206 | upstream | | PUT https://streaming.bose.com/streaming/account/{{accountId}}/device/{{device_id}}/preset/6 | 500 Internal Server Error | ./upstream/streaming/account/{accountId}/device/{device_id}/preset/6/0206-20260329-233331.096-PUT.http | +| 0207 | self | | PUT /streaming/account/{{accountId}}/device/{{device_id}}/preset/6 | 500 Internal Server Error | ./self/streaming/account/{accountId}/device/{device_id}/preset/6/0207-20260329-233331.096-PUT.http | +| 0208 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0208-20260329-233331.323-POST.http | +| 0209 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0209-20260329-233331.938-POST.http | +| 0210 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0210-20260329-233331.982-POST.http | +| 0211 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0211-20260329-233332.366-POST.http | +| 0212 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0212-20260329-233332.396-POST.http | +| 0213 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0213-20260329-233344.994-POST.http | +| 0214 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0214-20260329-233345.001-POST.http | +| 0215 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0215-20260329-233345.427-POST.http | +| 0216 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0216-20260329-233345.430-POST.http | +| 0217 | mirror | | POST /bmx/tunein/v1/report?stream_id=e536753726&guide_id=s166521&listen_id=1774819980&last_titt=0&duration_balance=0&stream_type=liveRadio | 200 OK | ./mirror/bmx/tunein/v1/report/0217-20260329-233345.547-POST.http | +| 0218 | upstream | | POST https://content.api.bose.io/bmx/tunein/v1/report?stream_id=e536753726&guide_id=s166521&listen_id=1774819980&last_titt=0&duration_balance=0&stream_type=liveRadio | 200 OK | ./upstream/bmx/tunein/v1/report/0218-20260329-233345.651-POST.http | +| 0219 | self | | POST /bmx/tunein/v1/report?stream_id=e536753726&guide_id=s166521&listen_id=1774819980&last_titt=0&duration_balance=0&stream_type=liveRadio | 200 OK | ./self/bmx/tunein/v1/report/0219-20260329-233345.651-POST.http | +| 0220 | self | | GET /bmx/registry/v1/services | 200 OK | ./self/bmx/registry/v1/services/0220-20260329-233504.445-GET.http | +| 0221 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0221-20260329-233504.467-POST.http | +| 0222 | self | | POST /streaming/support/power_on | 200 OK | ./self/streaming/support/power_on/0222-20260329-233504.475-POST.http | +| 0223 | mirror | | POST /streaming/support/power_on | 200 OK | ./mirror/streaming/support/power_on/0223-20260329-233504.668-POST.http | +| 0224 | mirror | | GET /bmx/registry/v1/services | 200 OK | ./mirror/bmx/registry/v1/services/0224-20260329-233504.879-GET.http | +| 0225 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0225-20260329-233504.891-POST.http | +| 0226 | self | ☑ | GET / | 200 OK | ./self/root/0226-20260329-233505.214-GET.http | +| 0227 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0227-20260329-233505.548-POST.http | +| 0228 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0228-20260329-233505.560-POST.http | +| 0229 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0229-20260329-233505.735-POST.http | +| 0230 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0230-20260329-233505.980-POST.http | +| 0231 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0231-20260329-233505.994-POST.http | +| 0232 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0232-20260329-233506.158-POST.http | +| 0233 | self | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./self/v1/scmudc/{device_id}/0233-20260329-233506.707-POST.http | +| 0234 | self | | GET /streaming/sourceproviders | 200 OK | ./self/streaming/sourceproviders/0234-20260329-233506.769-GET.http | +| 0235 | self | | GET /streaming/account/{{accountId}}/full | 200 OK | ./self/streaming/account/{accountId}/full/0235-20260329-233507.099-GET.http | +| 0236 | mirror | ☑ | POST /v1/scmudc/{{device_id}} | 200 OK | ./mirror/v1/scmudc/{device_id}/0236-20260329-233507.137-POST.http | +| 0237 | mirror | | GET /streaming/account/{{accountId}}/full | 200 OK | ./mirror/streaming/account/{accountId}/full/0237-20260329-233507.277-GET.http | +| 0238 | self | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./self/streaming/account/{accountId}/device/{device_id}/group/0238-20260329-233508.639-GET.http | +| 0239 | self | | GET /streaming/device/{{device_id}}/streaming_token | 200 OK | ./self/streaming/device/{device_id}/streaming_token/0239-20260329-233508.642-GET.http | +| 0240 | self | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./self/streaming/account/{accountId}/provider_settings/0240-20260329-233508.755-GET.http | +| 0241 | mirror | | GET /streaming/account/{{accountId}}/device/{{device_id}}/group/ | 200 OK | ./mirror/streaming/account/{accountId}/device/{device_id}/group/0241-20260329-233508.809-GET.http | +| 0242 | self | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./self/streaming/account/{accountId}/provider_settings/0242-20260329-233508.866-GET.http | +| 0243 | mirror | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./mirror/streaming/account/{accountId}/provider_settings/0243-20260329-233508.968-GET.http | +| 0244 | mirror | | GET /streaming/account/{{accountId}}/provider_settings | 200 OK | ./mirror/streaming/account/{accountId}/provider_settings/0244-20260329-233509.041-GET.http | +| 0245 | self | | POST /oauth/device/{{device_id}}/music/musicprovider/15/token/cs3 | 200 OK | ./self/oauth/device/{device_id}/music/musicprovider/15/token/cs3/0245-20260329-233510.807-POST.http |