Know what's playing
on any stream
Register a live radio or broadcast stream URL and we detect every track as it airs: a timestamped play log with ISRC, artist, release, and cross-platform IDs, plus a signed webhook for every confirmed play. 93M+ 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 93M+ tracks. How the engine works
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);
Or don't poll: webhooks & live feed
Register a webhook and we POST a signed stream.play.started event to your endpoint the moment a track is detected on any of your monitored streams; stream.offline and stream.online events cover the stream itself. Prefer a connection you hold open? The same events arrive on a Server-Sent Events feed. Both are bundled with stream monitoring and use no API credits.
# Get a signed POST for every confirmed play - no pollingcurl -X POST https://api.sonovault.now/v1/webhooks \-H "x-api-key: YOUR_API_KEY" \-H "Content-Type: application/json" \-d '{"url":"https://your-app.example.com/hooks/sonovault","event_types":["stream.play.started","stream.offline","stream.online"]}'# -> { "id": "wh_...", "secret": "whsec_..." } (store the secret to verify deliveries)
# Or a live Server-Sent Events feed across all your streamscurl -N https://api.sonovault.now/v1/streams/live \-H "x-api-key: YOUR_API_KEY" \-H "Accept: text/event-stream"
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.