Admin
Now Playing
0 listening
Loading...
Request a Song
Queue0
Queue is empty
Server Stats
0
Listeners
0
Played
0
Queued
0
Library
Format
0s
Uptime
Upload
Total Sent
Music Library
0 songs
Enter admin token to view library

API Reference

Public Endpoints
GET/streamAudio stream (Ogg/Opus or MP3)
Usage Examples
# Stream to stdout curl http://localhost:{{PORT}}/stream --output - # Play with ffplay ffplay http://localhost:{{PORT}}/stream # Play with VLC vlc http://localhost:{{PORT}}/stream # Save to file curl http://localhost:{{PORT}}/stream -o recording.ogg
Stream supports ICY metadata for track info in compatible players.
GET/api/now-playingCurrent track + timestamps for sync
Best endpoint for game clients. Poll every 3-5s. Use serverTime to sync clocks, endsAt for transition timing, upcoming to pre-plan UI.
Response
{ "title": "Artist - Song Name", "listeners": 42, "isRequest": false, "duration": 240, // total seconds "startedAt": 1711036800000, // unix ms when song started "endsAt": 1711037040000, // unix ms when song ends "elapsed": 45.2, // seconds into song "remaining": 194.8, // seconds left "serverTime": 1711036845200, // server clock (for sync) "upcoming": [ // next 5 tracks (requests first) { "title": "Requested Song", "duration": 180, "isRequest": true }, { "title": "Playlist Song", "duration": 210, "isRequest": false } ] }
Unity/Lua sync: clockOffset = serverTime - os.time()*1000, then localElapsed = (os.time()*1000 + clockOffset - startedAt) / 1000. Use endsAt to schedule transition animations ahead of time.
GET/api/statusFull server status + timestamps
Response
{ "listeners": 42, "track": "Artist - Song Name", "isRequest": false, "duration": 240, "startedAt": 1711036800000, "elapsed": 45.2, "remaining": 194.8, "serverTime": 1711036845200, "format": "opus", "bitrate": 64, "uptime": 3600, "uptimeFormatted": "1h 0m", "queueLength": 3, "requestsEnabled": true, "playlistCount": 150, "tracksPlayed": 42, "bandwidth": { ... } }
GET/api/queueCurrent request queue
Response
{ "enabled": true, "queue": [ { "id": "abc123", "title": "Artist - Song", "duration": 240, "requestedAt": 1703001234567 } ] }
GET/api/historyRecently played tracks
Response
{ "history": [ { "title": "Artist - Song", "playedAt": 1703001234567, "wasRequest": false } ] }
GET/api/searchSearch YouTube
Full URL Example
https://radio.yoworld.info/api/search?q=never+gonna+give+you+up&limit=10
Parameters
q — Search query (required) limit — Max results, 1-20 (default: 10)
Response
{ "results": [ { "videoId": "dQw4w9WgXcQ", "title": "Rick Astley - Never Gonna Give You Up", "duration": 213, "durationFormatted": "3:33", "channel": "Rick Astley", "thumbnail": "https://i.ytimg.com/vi/.../hqdefault.jpg", "views": 1500000000, "url": "https://youtube.com/watch?v=dQw4w9WgXcQ" } ] }
Returns up to 20 results. Use limit to control count (default: 10). Fast — no yt-dlp needed.
POST/api/requestRequest a song
Request Body
// By YouTube URL: { "url": "https://youtube.com/watch?v=dQw4w9WgXcQ" } // By search query: { "query": "never gonna give you up" }
Success Response
{ "success": true, "title": "Rick Astley - Never Gonna Give You Up", "position": 3, "id": "abc123" }
Error Response
{ "error": "Requests are currently disabled" }
Admin Endpoints
All admin endpoints require Authorization: Bearer YOUR_TOKEN header
POST/api/admin/skipSkip current track
Response
{ "success": true, "skipped": "Artist - Song Name" }
POST/api/admin/shuffleShuffle playlist
Response
{ "success": true }
POST/api/admin/clearClear request queue
Response
{ "success": true, "cleared": 5 }
POST/api/admin/toggleEnable/disable requests
Request Body
{ "enabled": false }
Response
{ "enabled": false }
GET/api/admin/libraryList all songs in library
Response
{ "tracks": [ { "filename": "Artist - Song.opus", "title": "Artist - Song", "path": "/music/Artist - Song.opus" } ] }
POST/api/admin/library/addDownload and add song from YouTube
Request Body
{ "url": "https://youtube.com/watch?v=dQw4w9WgXcQ" }
Success Response
{ "success": true, "filename": "Rick Astley - Never Gonna Give You Up.opus", "title": "Rick Astley - Never Gonna Give You Up" }
POST/api/admin/library/deleteDelete song from library
Request Body
{ "filename": "Artist - Song.opus" }
Response
{ "success": true }
POST/api/admin/library/importImport YouTube playlist
Request Body
{ "url": "https://youtube.com/playlist?list=PLxxxxxxxx" }
Response
{ "importId": "abc123", "message": "Import started" }
Use GET /api/admin/library/import/status?id=abc123 to check progress
GET/api/admin/library/import/statusCheck import progress
Query Parameters
?id=abc123
Running Response
{ "status": "running", "total": 50, "completed": 25, "failed": 2 }
Complete Response
{ "status": "complete", "total": 50, "completed": 48, "failed": 2 }
Real-Time Events
GET/api/eventsServer-Sent Events (SSE) — for Unity / non-WebSocket
Connection (C# / Unity)
// Unity — use UnityWebRequest with DownloadHandlerScript var request = UnityWebRequest.Get("http://server:{{PORT}}/api/events"); request.SendWebRequest();
Connection (curl)
curl -N http://localhost:{{PORT}}/api/events
Events Received
// On connect — immediate current state: event: connected data: {"event":"connected","title":"Song Name","isRequest":false,"listeners":5} // When track changes: event: track_change data: {"event":"track_change","title":"New Song","isRequest":true,"duration":240} // When queue updates: event: queue_update data: {"event":"queue_update","length":3,"queue":[...]}
Same events as WebSocket but over plain HTTP. No WebSocket library needed. Sends keepalive every 30s. Reconnect on disconnect.
WS/wsWebSocket — for web browsers
Connection
const ws = new WebSocket('ws://localhost:{{PORT}}/ws'); ws.onmessage = (event) => { const data = JSON.parse(event.data); console.log(data.event, data); };
track_change Event
{ "event": "track_change", "title": "Artist - Song Name", "isRequest": false, "duration": 240 }
queue_update Event
{ "event": "queue_update", "length": 3, "queue": [ { "id": "abc", "title": "Song" } ] }
listeners_update Event
{ "event": "listeners_update", "count": 5 }