Tuned Global

Background Music Service — Quick Start Guide

Overview

This guide covers integrating Tuned Global's APIs for background music services — the kind used in retail stores, restaurants, hotels, and venues. Unlike consumer streaming, background music players typically operate as store-and-forward systems: they cache audio locally on the playback device so music continues uninterrupted even when the network drops.

By the end of this guide you'll have: authenticated a venue device, fetched a scheduled playlist, cached tracks to local storage, played them back offline-capable, and logged plays for royalty reporting.

Estimated time: 15–20 minutes

Prerequisites

  • A StoreId issued by Tuned Global for your background music environment
  • OAuth2 client credentials (client ID and secret) from Tuned Global
  • A registered device ID for the venue player
  • cURL or Postman installed
  • Local storage available on the playback device (minimum 2 GB recommended)

Architecture: Store-and-Forward

Background music players differ from consumer apps in several key ways:

Aspect Consumer Streaming Store-and-Forward
Playback model Stream on demand Pre-cache, play locally
Network dependency Continuous Periodic sync only
Playlist control User-driven Centrally scheduled
Device type Phone/tablet Dedicated player, Raspberry Pi, POS system
Failover Buffering/stop Seamless from local cache

The typical sync cycle:

  1. Device connects to the API on a schedule (e.g. every 4 hours, or overnight)
  2. Fetches the current playlist assignment and any updates
  3. Downloads and caches any new tracks not already stored locally
  4. Removes expired tracks that are no longer in any active playlist
  5. Plays from local cache — no network required during playback
  6. Logs play events locally and uploads them in batch when connectivity is available

Step 1: Authenticate the Device

Obtain a JWT token using your device's service account credentials. Background music devices typically use client credentials grant rather than user/password.

Endpoint: POST https://api-authentication-connect.tunedglobal.com/oauth2/token

curl -X POST "https://api-authentication-connect.tunedglobal.com/oauth2/token" \
  -H "StoreId: YOUR_STORE_ID" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET"

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "bearer",
  "expires_in": 86400
}

Save the access_token. For store-and-forward devices, implement token refresh logic that requests a new token before expiry — the device may need to sync while unattended.

Tip: Store the token expiry timestamp locally so the device knows whether to re-authenticate before attempting a sync, even after a reboot.

Step 2: Fetch Playlist Assignment

Retrieve the playlist(s) currently assigned to this device or venue location. Background music playlists are typically managed centrally by the venue operator or brand team.

Endpoint: GET https://api-metadata-connect.tunedglobal.com/api/v2.4/playlists/{playlistId}

curl -X GET "https://api-metadata-connect.tunedglobal.com/api/v2.4/playlists/55001?offset=0&count=500" \
  -H "StoreId: YOUR_STORE_ID" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

The response includes the full track listing with Track IDs, durations, and metadata. Store this response locally as your playlist manifest.

To check for schedule or playlist changes without downloading the full track list:

Endpoint: GET https://api-metadata-connect.tunedglobal.com/api/v2.4/playlists/{playlistId}/updated

curl -X GET "https://api-metadata-connect.tunedglobal.com/api/v2.4/playlists/55001/updated" \
  -H "StoreId: YOUR_STORE_ID" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Compare the returned timestamp against your last sync to decide whether a full refresh is needed.

Step 3: Cache Audio to Device

This is the critical step for store-and-forward reliability. For each track in the playlist, request a download URL and save the audio file to local storage.

3a. Request Download Token

Endpoint: POST https://api-services-connect.tunedglobal.com/api/v3/plays/{deviceId}/{trackId}/token

curl -X POST "https://api-services-connect.tunedglobal.com/api/v3/plays/VENUE-PLAYER-01/987654/token" \
  -H "StoreId: YOUR_STORE_ID" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

3b. Get Download URL

Endpoint: POST https://api-services-connect.tunedglobal.com/api/v3/plays/{deviceId}/{trackId}/stream

curl -X POST "https://api-services-connect.tunedglobal.com/api/v3/plays/VENUE-PLAYER-01/987654/stream?streamType=Music&streamProvider=Tuned" \
  -H "StoreId: YOUR_STORE_ID" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '"STREAM_TOKEN_FROM_STEP_3A"'

3c. Download and Store Locally

curl -L -o /cache/music/987654.mp3 "SIGNED_URL_FROM_STEP_3B"

Important: The signed URL has a TTL (time-to-live). Download the file promptly after receiving the URL. Do not store the URL for later — store the audio file itself.

Caching Best Practices

  • Use the Track ID as the filename (e.g. 987654.mp3) so you can easily check which tracks are already cached
  • Check before downloading — compare the playlist manifest against files already on disk to avoid re-downloading unchanged tracks
  • Download in batches — process 5–10 tracks concurrently to speed up initial sync without overwhelming bandwidth
  • Verify file integrity — check that the downloaded file size is non-zero and matches expected duration; re-download corrupt files
  • Implement retry logic — transient network errors are expected; retry failed downloads with exponential backoff
  • Reserve disk space — monitor available storage and alert if cache usage exceeds 80% of allocated space
  • Handle storage full gracefully — if the device runs out of space, keep existing cached tracks playable and flag the sync as incomplete

Example cache management pseudocode:

# On each sync cycle:
remote_tracks = fetch_playlist_tracks(playlist_id)
local_tracks  = list_cached_files("/cache/music/")

to_download = remote_tracks - local_tracks    # New tracks to cache
to_remove   = local_tracks - remote_tracks    # Expired tracks to clean up

for track_id in to_remove:
    delete("/cache/music/{track_id}.mp3")

for track_id in to_download:
    token = request_stream_token(device_id, track_id)
    url   = request_stream_url(device_id, track_id, token)
    download(url, "/cache/music/{track_id}.mp3")

Step 4: Local Playback

Once tracks are cached, playback happens entirely from local storage with no network dependency.

Playback Loop

The player should:

  1. Read the locally stored playlist manifest
  2. Play tracks in the defined order (or shuffle, depending on venue configuration)
  3. Loop continuously — background music should never stop
  4. Record play events to a local log file for later upload

Handling Gaps

If a track file is missing or corrupt:

  • Skip to the next track immediately
  • Log the error locally
  • Flag the track for re-download on the next sync cycle
  • Never stop playback because of a single missing file

Scheduling

Many background music deployments use daypart scheduling — different playlists for morning, lunch, evening, etc. The device should:

  • Store multiple playlist manifests if assigned a schedule
  • Switch playlists at the configured times using the device's local clock
  • Sync all scheduled playlists during the cache cycle, not just the currently active one

Step 5: Log Playback Events

Logging is mandatory for royalty reporting and compliance, even for background music. The key difference: store-and-forward players log locally first and upload in batch when connectivity is available.

5a. Log Locally During Playback

For each track played, record:

{
  "TrackId": 987654,
  "LogPlayType": "Start",
  "Seconds": 0,
  "Source": "Playlist",
  "SourceId": "55001",
  "Guid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "Country": "AU",
  "PlayerType": "BackgroundPlayer",
  "Timestamp": "2026-03-31T09:15:00Z",
  "DeviceId": "VENUE-PLAYER-01"
}

Log the same event types as consumer playback:

LogPlayType       When                                          Seconds
---------------   -------------------------------------------   ----------------
Start             Playback begins                               0
30SecondMark      30 seconds elapsed (mandatory for royalties)  30
EndOfFile         Track finishes                                Total duration
Skip              Track skipped (e.g. schedule change)          Current position

5b. Batch Upload Play Logs

During each sync cycle, upload accumulated play logs to the API.

Endpoint: POST https://api-services-connect.tunedglobal.com/api/v3/plays/{deviceId}

curl -X POST "https://api-services-connect.tunedglobal.com/api/v3/plays/VENUE-PLAYER-01" \
  -H "StoreId: YOUR_STORE_ID" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "TrackId": 987654,
    "LogPlayType": "Start",
    "Seconds": 0,
    "Source": "Playlist",
    "SourceId": "55001",
    "Guid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "Country": "AU",
    "PlayerType": "BackgroundPlayer"
  }'

Upload each log entry individually or iterate through the local log file. After a successful upload (HTTP 200), mark the entry as synced so it isn't re-uploaded.

Critical: Do not delete local logs until you have confirmed successful upload. If the upload fails, retain the logs and retry on the next sync cycle. Play logs are legally required for royalty reporting — losing them is not acceptable.

Step 6: Sync Cycle Summary

Tie it all together in a single sync routine that runs on a timer (e.g. every 4–6 hours):

1. Re-authenticate if token is expired or near expiry
2. Check for playlist updates (Step 2 — /updated endpoint)
3. If playlist changed:
   a. Fetch new playlist manifest
   b. Remove tracks no longer in any active playlist
   c. Download and cache new tracks (Step 3)
4. Upload pending play logs (Step 5b)
5. Report sync status (success/failure, tracks cached, logs uploaded)

Network Resilience

The sync cycle should be fully idempotent — if it fails partway through, the next run picks up where it left off:

  • Partially downloaded files should be discarded and re-downloaded
  • Play logs that failed to upload remain in the local queue
  • Playlist manifest updates are atomic: apply the new manifest only after all new tracks are cached

Troubleshooting

Error                          Cause                                    Solution
----------------------------   ---------------------------------------- ------------------------------------------------
403 on stream/download         Token expired or subscription lapsed     Re-authenticate (Step 1), check licence status
Playback silence               Cache file missing or corrupt            Check disk, trigger manual sync
Play logs not appearing        Upload failed or entries not synced      Check local log queue, verify network on sync
Disk full                      Cache exceeds allocated storage          Increase storage or reduce playlist size
Playlist not updating          Sync cycle not running or /updated stale Verify cron/timer, check API connectivity
Tracks re-downloading          Track IDs not matching local filenames   Ensure filename matches Track ID exactly

Quick Reference — Sync Endpoints

Action                 Method   Endpoint
---------------------  ------   --------------------------------------------------------
Authenticate           POST     /oauth2/token
Fetch playlist         GET      /api/v2.4/playlists/{playlistId}
Check playlist update  GET      /api/v2.4/playlists/{playlistId}/updated
Request stream token   POST     /api/v3/plays/{deviceId}/{trackId}/token
Get download URL       POST     /api/v3/plays/{deviceId}/{trackId}/stream
Upload play log        POST     /api/v3/plays/{deviceId}

Notes

  • Replace YOUR_STORE_ID, YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_ACCESS_TOKEN, and example IDs with your actual credentials from Tuned Global.
  • Background music licensing is separate from consumer streaming. Confirm your licence covers public performance rights for the territories where devices are deployed.
  • For large venue networks (100+ devices), contact Tuned Global about bulk sync endpoints and fleet management APIs.

On this page