Know what's playing
on any stream
Register a live radio or broadcast stream URL and we recognise every track as it airs: a timestamped now-playing log with ISRC, artist, release, and cross-platform IDs, across 90M+ tracks.
Register a stream URL
POST the direct URL of any internet radio or broadcast stream. Monitoring starts immediately, with no setup and no audio to upload.
We monitor it continuously
We pull the audio around the clock and recognise each track as it plays, against an acoustic index spanning 90M+ tracks.
Poll the now-playing log
Read the current track, or the full timestamped history. Each entry is a plain track object with ISRC, release, genre, and platform IDs.
Register a stream
One call with the stream URL. You get back a stream id you'll poll for results. Keep your API key on the server.
# Register a live stream URL - we start monitoring it immediatelycurl -X POST https://api.sonovault.now/v1/streams \-H "x-api-key: YOUR_API_KEY" \-H "Content-Type: application/json" \-d '{"url":"https://stream.example.com/radio.mp3","name":"My Station"}'# -> { "id": "9f2c...", "url": "...", "name": "My Station", "status": "active" }
Poll for what's playing
Get the current now-playing track, or the full timestamped log. Use ?since= to fetch only what's new since your last poll.
# What's playing right nowcurl https://api.sonovault.now/v1/streams/9f2c... \-H "x-api-key: YOUR_API_KEY"
# The timestamped recognition log (newest first; ?since= for incremental polling)curl "https://api.sonovault.now/v1/streams/9f2c.../history?since=2026-06-14T18:00:00Z" \-H "x-api-key: YOUR_API_KEY"
const API = "https://api.sonovault.now";const headers = { "x-api-key": process.env.SONOVAULT_API_KEY };// 1. Register the stream onceconst { id } = await fetch(`${API}/v1/streams`, {method: "POST",headers: { ...headers, "Content-Type": "application/json" },body: JSON.stringify({ url: "https://stream.example.com/radio.mp3", name: "My Station" }),}).then((r) => r.json());// 2. Poll the now-playing track (e.g. every 30s)setInterval(async () => {const { now_playing } = await fetch(`${API}/v1/streams/${id}`, { headers }).then((r) => r.json());if (now_playing) {const t = now_playing.track;console.log(`${t.artists[0].name} - ${t.title} (since ${now_playing.started_at})`);}}, 30_000);
The response
now_playing.track and each history entry are plain track objects (the same shape returned by track search). now_playing is null during ad breaks, talk, or unrecognised audio.
{"id": "9f2c8e1a-...","url": "https://stream.example.com/radio.mp3","name": "My Station","status": "active","runtime_status": "running","now_playing": {"track": {"id": 121217540,"title": "One More Time","artists": [{ "id": 9001, "name": "Daft Punk", "is_primary": true }],"releases": [{ "id": 4242, "title": "Discovery", "release_date": "2001-03-12" }],"isrc": "GBDUW0000054","duration": 320,"genre": ["Electronic"],"subgenre": ["French House"]},"started_at": "2026-06-14T18:42:11Z"},"last_recognized_at": "2026-06-14T18:43:02Z"}
{"plays": [{"track": { "id": 121217540, "title": "One More Time", "artists": [{ "id": 9001, "name": "Daft Punk", "is_primary": true }], "isrc": "GBDUW0000054" },"started_at": "2026-06-14T18:42:11Z"},{"track": { "id": 988213, "title": "Strangest Thing", "artists": [{ "id": 7720, "name": "The War On Drugs", "is_primary": true }], "isrc": "USAT21703012" },"started_at": "2026-06-14T18:37:40Z"}]}
Monitor a stream from your dashboard
Logged-in users get a Stream Monitoring tool in the dashboard: paste a stream URL, watch the live now-playing track and recognition history, and stop monitoring with a click. Same recognition as the API.