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 — no setup, 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 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 idyou'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","ended_at": null},{"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","ended_at": "2026-06-14T18:42:11Z"}]}
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.