#+TITLE: Asteroid Radio - API Endpoints Reference #+AUTHOR: Asteroid Radio Development Team #+DATE: 2026-01-26 * Overview Asteroid Radio provides a comprehensive JSON API built with Radiance's =define-api= framework. All API endpoints return JSON responses and follow RESTful conventions. ** Base URL All API endpoints are prefixed with =/api/asteroid/= ** Authentication Protected endpoints require user authentication via session cookies. Unauthenticated requests to protected endpoints will return an error response. ** Response Format All API responses follow this structure: #+BEGIN_SRC json { "status": "success" | "error", "message": "Human-readable message", "data": { ... } // Optional, endpoint-specific data } #+END_SRC * Status Endpoints ** GET /api/asteroid/status Get server status and system information. *** Authentication Not required *** Response #+BEGIN_SRC json { "status": "success", "server": "asteroid-radio", "version": "1.0", "uptime": 3600 } #+END_SRC ** GET /api/asteroid/auth-status Check current authentication status. *** Authentication Not required *** Response #+BEGIN_SRC json { "loggedIn": true, "username": "admin", "role": "admin" } #+END_SRC ** GET /api/asteroid/icecast-status Get Icecast streaming server status and current track information. *** Authentication Not required *** Response #+BEGIN_SRC json { "icestats": { "source": { "title": "Artist - Track Name", "listeners": 5, "genre": "Electronic", "bitrate": 128 } } } #+END_SRC * Track Endpoints ** GET /api/asteroid/tracks Get list of all tracks in the music library. *** Authentication Required *** Response #+BEGIN_SRC json { "status": "success", "tracks": [ { "id": "track-id-123", "title": "Track Name", "artist": "Artist Name", "album": "Album Name", "duration": 245, "format": "mp3" } ] } #+END_SRC ** GET /api/asteroid/admin/tracks Get administrative track listing (admin only). *** Authentication Required (Admin role) *** Response Same as =/api/asteroid/tracks= but includes additional metadata for administration. * Player Control Endpoints ** GET /api/asteroid/player/status Get current player status. *** Authentication Required *** Response #+BEGIN_SRC json { "status": "success", "player": { "state": "playing" | "paused" | "stopped", "currentTrack": { "id": "track-id-123", "title": "Track Name", "artist": "Artist Name" }, "position": 45, "duration": 245 } } #+END_SRC ** POST /api/asteroid/player/play Play a specific track. *** Authentication Required *** Parameters - =track-id= (required) - ID of the track to play *** Example Request #+BEGIN_SRC bash curl -X POST http://localhost:8080/api/asteroid/player/play \ -d "track-id=track-id-123" #+END_SRC *** Response #+BEGIN_SRC json { "status": "success", "message": "Playing track", "player": { "state": "playing", "currentTrack": { ... } } } #+END_SRC ** POST /api/asteroid/player/pause Pause current playback. *** Authentication Required *** Response #+BEGIN_SRC json { "status": "success", "message": "Playback paused", "player": { "state": "paused" } } #+END_SRC ** POST /api/asteroid/player/stop Stop current playback. *** Authentication Required *** Response #+BEGIN_SRC json { "status": "success", "message": "Playback stopped", "player": { "state": "stopped" } } #+END_SRC ** POST /api/asteroid/player/resume Resume paused playback. *** Authentication Required *** Response #+BEGIN_SRC json { "status": "success", "message": "Playback resumed", "player": { "state": "playing" } } #+END_SRC * Playlist Endpoints ** GET /api/asteroid/playlists Get all playlists for the current user. *** Authentication Required *** Response #+BEGIN_SRC json { "status": "success", "playlists": [ { "id": "playlist-id-123", "name": "My Playlist", "description": "Favorite tracks", "trackCount": 15, "created": "2025-10-10T12:00:00Z" } ] } #+END_SRC ** POST /api/asteroid/playlists/create Create a new playlist. *** Authentication Required *** Parameters - =name= (required) - Playlist name - =description= (optional) - Playlist description *** Example Request #+BEGIN_SRC bash curl -X POST http://localhost:8080/api/asteroid/playlists/create \ -d "name=My Playlist&description=Favorite tracks" #+END_SRC *** Response #+BEGIN_SRC json { "status": "success", "message": "Playlist created successfully", "playlist": { "id": "playlist-id-123", "name": "My Playlist", "description": "Favorite tracks" } } #+END_SRC ** GET /api/asteroid/playlists/get Get details of a specific playlist. *** Authentication Required *** Parameters - =playlist-id= (required) - ID of the playlist *** Example Request #+BEGIN_SRC bash curl "http://localhost:8080/api/asteroid/playlists/get?playlist-id=playlist-id-123" #+END_SRC *** Response #+BEGIN_SRC json { "status": "success", "playlist": { "id": "playlist-id-123", "name": "My Playlist", "description": "Favorite tracks", "tracks": [ { "id": "track-id-123", "title": "Track Name", "artist": "Artist Name" } ] } } #+END_SRC ** POST /api/asteroid/playlists/add-track Add a track to a playlist. *** Authentication Required *** Parameters - =playlist-id= (required) - ID of the playlist - =track-id= (required) - ID of the track to add *** Example Request #+BEGIN_SRC bash curl -X POST http://localhost:8080/api/asteroid/playlists/add-track \ -d "playlist-id=playlist-id-123&track-id=track-id-456" #+END_SRC *** Response #+BEGIN_SRC json { "status": "success", "message": "Track added to playlist" } #+END_SRC ** POST /api/asteroid/playlists/remove-track Remove a track from a playlist. *** Authentication Required *** Parameters - =playlist-id= (required) - ID of the playlist - =track-id= (required) - ID of the track to remove *** Response #+BEGIN_SRC json { "status": "success", "message": "Track removed from playlist" } #+END_SRC ** POST /api/asteroid/playlists/delete Delete a playlist. *** Authentication Required *** Parameters - =playlist-id= (required) - ID of the playlist *** Response #+BEGIN_SRC json { "status": "success", "message": "Playlist deleted" } #+END_SRC * Admin Endpoints ** POST /api/asteroid/admin/scan-library Scan the music library for new tracks. *** Authentication Required (Admin role) *** Response #+BEGIN_SRC json { "status": "success", "message": "Library scan completed", "tracks-added": 42 } #+END_SRC ** GET /api/asteroid/users Get all users. *** Authentication Required (Admin role) *** Response Returns a JSON object with a =users= array. ** POST /api/asteroid/users/create Create a new user. *** Authentication Required (Admin role) *** Parameters - =username= (required) - =email= (required) - =password= (required) - =role= (required) *** Response Returns a JSON object indicating success or failure. * Stream Playlist File Endpoints (Admin Only) These endpoints manage playlist files in the =playlists/= directory, and control the currently active =playlists/stream-queue.m3u=. ** GET /api/asteroid/stream/playlists List available playlist files in =playlists/= (excluding =stream-queue.m3u=). *** Authentication Required (Admin role) *** Response Returns a JSON object with a =playlists= array of filenames. ** POST /api/asteroid/stream/playlists/load Load a playlist file into =playlists/stream-queue.m3u= and return its paths. *** Authentication Required (Admin role) *** Parameters - =name= (required) - Playlist filename to load ** POST /api/asteroid/stream/playlists/save Save the in-memory stream queue to =playlists/stream-queue.m3u=. *** Authentication Required (Admin role) ** POST /api/asteroid/stream/playlists/save-as Save the current stream queue to a new playlist file. *** Authentication Required (Admin role) *** Parameters - =name= (required) - New playlist filename (=.m3u= suffix is optional) ** POST /api/asteroid/stream/playlists/clear Clear =playlists/stream-queue.m3u= and empty the in-memory stream queue. *** Authentication Required (Admin role) ** GET /api/asteroid/stream/playlists/current Return the current =playlists/stream-queue.m3u= contents with best-effort track info. *** Authentication Required (Admin role) * Liquidsoap Control Endpoints (Admin Only) ** GET /api/asteroid/liquidsoap/status Get Liquidsoap status including uptime, current metadata, and remaining time. *** Authentication Required (Admin role) ** POST /api/asteroid/liquidsoap/skip Skip the current track in the stream queue. *** Authentication Required (Admin role) ** POST /api/asteroid/liquidsoap/reload Force Liquidsoap to reload the playlist. *** Authentication Required (Admin role) ** POST /api/asteroid/liquidsoap/restart Restart the Liquidsoap Docker container. *** Authentication Required (Admin role) ** POST /api/asteroid/icecast/restart Restart the Icecast Docker container. *** Authentication Required (Admin role) * Stream Queue Endpoints ** GET /api/asteroid/stream/queue Get the current stream queue. *** Authentication Required (Admin role) *** Response #+BEGIN_SRC json { "status": "success", "queue": [ { "id": "track-id-123", "title": "Track Name", "artist": "Artist Name", "path": "/path/to/file.mp3" } ] } #+END_SRC ** POST /api/asteroid/stream/queue/add Add a track to the stream queue. *** Authentication Required (Admin role) *** Parameters - =track-id= (required) - ID of the track to add - =position= (optional) - Position in queue ("end" or index, default "end") ** POST /api/asteroid/stream/queue/remove Remove a track from the stream queue. *** Authentication Required (Admin role) *** Parameters - =track-id= (required) - ID of the track to remove ** POST /api/asteroid/stream/queue/clear Clear the entire stream queue. *** Authentication Required (Admin role) ** POST /api/asteroid/stream/queue/add-playlist Add all tracks from a playlist to the stream queue. *** Authentication Required (Admin role) *** Parameters - =playlist-id= (required) - ID of the playlist to add ** POST /api/asteroid/stream/queue/reorder Reorder tracks in the stream queue. *** Authentication Required (Admin role) *** Parameters - =track-ids= (required) - Ordered list of track IDs ** POST /api/asteroid/stream/queue/load-m3u Load the stream queue from =playlists/stream-queue.m3u=. *** Authentication Required (Admin role) * Recently Played Endpoints ** GET /api/asteroid/recently-played Get recently played tracks. *** Authentication Not required *** Parameters - =mount= (optional) - Stream mount point (default: main stream) *** Response #+BEGIN_SRC json { "status": "success", "tracks": [ { "title": "Artist - Track Name", "played_at": "2026-01-26T12:00:00Z" } ] } #+END_SRC * Playlist Scheduler Endpoints (Admin Only) ** GET /api/asteroid/scheduler/status Get the current scheduler status. *** Authentication Required (Admin role) *** Response #+BEGIN_SRC json { "status": "success", "enabled": true, "current_playlist": "Asteroid-Low-Orbit.m3u", "current_hour": 14, "schedule": [ {"hour": 0, "playlist": "Late-Night.m3u"}, {"hour": 6, "playlist": "Morning.m3u"} ], "available_playlists": ["Asteroid-Low-Orbit.m3u", "Late-Night.m3u"] } #+END_SRC ** POST /api/asteroid/scheduler/enable Enable the playlist scheduler. *** Authentication Required (Admin role) ** POST /api/asteroid/scheduler/disable Disable the playlist scheduler (stops automatic playlist changes). *** Authentication Required (Admin role) ** POST /api/asteroid/scheduler/load-current Load the playlist for the current hour. *** Authentication Required (Admin role) ** GET /api/asteroid/scheduler/schedule Get the full schedule. *** Authentication Required (Admin role) ** POST /api/asteroid/scheduler/update Update a schedule entry. *** Authentication Required (Admin role) *** Parameters - =hour= (required) - Hour (0-23) - =playlist= (required) - Playlist filename ** POST /api/asteroid/scheduler/remove Remove a schedule entry. *** Authentication Required (Admin role) *** Parameters - =hour= (required) - Hour to remove from schedule * Track Request Endpoints ** POST /api/asteroid/requests/submit Submit a track request. *** Authentication Required *** Parameters - =title= (required) - Track title to request - =message= (optional) - Message with the request *** Response #+BEGIN_SRC json { "status": "success", "message": "Request submitted" } #+END_SRC ** GET /api/asteroid/requests/my Get current user's requests. *** Authentication Required *** Response #+BEGIN_SRC json { "status": "success", "requests": [ { "id": 1, "title": "Artist - Track", "status": "pending", "created_at": "2026-01-26T12:00:00Z" } ] } #+END_SRC ** GET /api/asteroid/requests/recent Get recently played requests (public). *** Authentication Not required ** GET /api/asteroid/admin/requests/pending Get pending requests for admin review. *** Authentication Required (Admin role) ** GET /api/asteroid/admin/requests/list Get requests by status. *** Authentication Required (Admin role) *** Parameters - =status= (optional) - Filter by status: "pending", "approved", "rejected", "played" (default: "pending") ** GET /api/asteroid/admin/requests/approved Get approved requests ready to queue. *** Authentication Required (Admin role) ** POST /api/asteroid/admin/requests/approve Approve a track request. *** Authentication Required (Admin role) *** Parameters - =id= (required) - Request ID ** POST /api/asteroid/admin/requests/reject Reject a track request. *** Authentication Required (Admin role) *** Parameters - =id= (required) - Request ID ** POST /api/asteroid/admin/requests/play Mark a request as played and add to queue. *** Authentication Required (Admin role) *** Parameters - =id= (required) - Request ID * User Custom Playlist Endpoints ** GET /api/asteroid/library/browse Browse the music library. *** Authentication Required *** Parameters - =search= (optional) - Search term - =artist= (optional) - Filter by artist - =album= (optional) - Filter by album - =page= (optional) - Page number for pagination ** GET /api/asteroid/user/playlists Get current user's custom playlists. *** Authentication Required ** GET /api/asteroid/user/playlists/get Get a specific user playlist. *** Authentication Required *** Parameters - =id= (required) - Playlist ID ** POST /api/asteroid/user/playlists/create Create a new user playlist. *** Authentication Required *** Parameters - =name= (required) - Playlist name - =description= (optional) - Playlist description ** POST /api/asteroid/user/playlists/update Update a user playlist. *** Authentication Required *** Parameters - =id= (required) - Playlist ID - =name= (optional) - New name - =description= (optional) - New description - =tracks= (optional) - Updated track list ** POST /api/asteroid/user/playlists/submit Submit a playlist for admin review. *** Authentication Required *** Parameters - =id= (required) - Playlist ID ** POST /api/asteroid/user/playlists/delete Delete a user playlist. *** Authentication Required *** Parameters - =id= (required) - Playlist ID ** GET /api/asteroid/admin/user-playlists Get all submitted user playlists for review. *** Authentication Required (Admin role) ** POST /api/asteroid/admin/user-playlists/review Review a submitted playlist. *** Authentication Required (Admin role) *** Parameters - =id= (required) - Playlist ID - =action= (required) - "approve" or "reject" - =notes= (optional) - Review notes ** GET /api/asteroid/admin/user-playlists/preview Preview a submitted playlist. *** Authentication Required (Admin role) *** Parameters - =id= (required) - Playlist ID * User Favorites Endpoints ** GET /api/asteroid/user/favorites Get current user's favorite tracks. *** Authentication Required *** Response #+BEGIN_SRC json { "status": "success", "favorites": [ { "track_id": 123, "title": "Artist - Track", "rating": 5, "added_at": "2026-01-26T12:00:00Z" } ] } #+END_SRC ** POST /api/asteroid/user/favorites/add Add a track to favorites. *** Authentication Required *** Parameters - =track-id= (optional) - Track ID - =title= (optional) - Track title (if track-id not provided) - =rating= (optional) - Rating 1-5 ** POST /api/asteroid/user/favorites/remove Remove a track from favorites. *** Authentication Required *** Parameters - =track-id= (optional) - Track ID - =title= (optional) - Track title (if track-id not provided) ** POST /api/asteroid/user/favorites/rate Rate a favorite track. *** Authentication Required *** Parameters - =track-id= (required) - Track ID - =rating= (required) - Rating 1-5 ** GET /api/asteroid/user/favorites/check Check if a track is in favorites. *** Authentication Required *** Parameters - =track-id= (required) - Track ID *** Response #+BEGIN_SRC json { "is_favorite": true, "rating": 5 } #+END_SRC * User Listening History Endpoints ** GET /api/asteroid/user/history Get current user's listening history. *** Authentication Required ** POST /api/asteroid/user/history/record Record a track listen. *** Authentication Required *** Parameters - =track-id= (optional) - Track ID - =title= (optional) - Track title - =duration= (optional) - Listen duration in seconds - =completed= (optional) - Whether track was completed (0 or 1) ** POST /api/asteroid/user/history/clear Clear listening history. *** Authentication Required ** GET /api/asteroid/user/activity Get listening activity data for charts. *** Authentication Required *** Parameters - =days= (optional) - Number of days to include (default: 30) *** Response #+BEGIN_SRC json { "status": "success", "activity": [ {"date": "2026-01-26", "minutes": 120, "tracks": 25} ] } #+END_SRC * User Profile Endpoints ** GET /api/asteroid/user/profile Get current user's profile data. *** Authentication Required *** Response #+BEGIN_SRC json { "status": "success", "user": { "username": "user123", "email": "user@example.com", "role": "listener", "avatar": "/avatars/user123.png", "created_at": "2025-10-01T12:00:00Z" } } #+END_SRC ** GET /api/asteroid/user/listening-stats Get user's listening statistics. *** Authentication Required ** GET /api/asteroid/user/recent-tracks Get user's recently listened tracks. *** Authentication Required *** Parameters - =limit= (optional) - Number of tracks (default: 3) - =offset= (optional) - Offset for pagination (default: 0) ** GET /api/asteroid/user/top-artists Get user's top artists. *** Authentication Required *** Parameters - =limit= (optional) - Number of artists (default: 5) ** POST /api/asteroid/user/avatar/upload Upload a user avatar. *** Authentication Required *** Request Multipart form data with image file. ** GET /api/asteroid/user/avatar Get current user's avatar URL. *** Authentication Required * User Account Endpoints ** POST /api/asteroid/user/change-password Change current user's password. *** Authentication Required *** Parameters - =current-password= (required) - Current password - =new-password= (required) - New password ** POST /api/asteroid/admin/reset-password Reset any user's password (admin only). *** Authentication Required (Admin role) *** Parameters - =username= (required) - Username - =new-password= (required) - New password ** POST /api/asteroid/user/activate Activate or deactivate a user account. *** Authentication Required (Admin role) *** Parameters - =user-id= (required) - User ID - =active= (required) - "true" or "false" ** POST /api/asteroid/user/role Change a user's role. *** Authentication Required (Admin role) *** Parameters - =user-id= (required) - User ID - =role= (required) - New role ("admin", "dj", "listener") ** GET /api/asteroid/user-stats Get user statistics (counts by role, active users, etc.). *** Authentication Required (Admin role) * Frontend Partial Endpoints These endpoints return HTML partials or JSON for frontend updates. ** GET /api/asteroid/partial/now-playing Get HTML partial with current now-playing information. *** Authentication Not required *** Parameters - =mount= (optional) - Stream mount point *** Response HTML fragment for embedding in page. ** GET /api/asteroid/partial/now-playing-inline Get inline text with now-playing info (for admin dashboard and widgets). *** Authentication Not required *** Parameters - =mount= (optional) - Stream mount point *** Response Plain text: "Artist - Track Title" ** GET /api/asteroid/partial/now-playing-json Get JSON with now-playing info including track ID for favorites. *** Authentication Not required *** Parameters - =mount= (optional) - Stream mount point *** Response #+BEGIN_SRC json { "title": "Artist - Track Name", "track_id": 123, "listeners": 5 } #+END_SRC ** GET /api/asteroid/channel-name Get the current curated channel name. *** Authentication Not required *** Response #+BEGIN_SRC json { "channel": "Asteroid Low Orbit" } #+END_SRC * Listener Statistics Endpoints ** GET /api/asteroid/stats/current Get the current listener statistics. *** Authentication Not required ** GET /api/asteroid/stats/daily Get the daily listener statistics. *** Authentication Required (Admin role) *** Response Returns a JSON object containing daily listener statistics. ** GET /api/asteroid/stats/geo Get the geographical listener statistics. *** Authentication Required (Admin role) *** Response Returns a JSON object containing geographical listener statistics. ** GET /api/asteroid/stats/geo/cities Get the listener statistics by city. *** Authentication Required (Admin role) *** Response Returns a JSON object containing the country and a =cities= array with per-city aggregates. * Utility Endpoints ** GET /api/asteroid/spectrum-analyzer.js Get the dynamically generated JavaScript for the spectrum analyzer. *** Authentication Not required *** Response JavaScript code for the spectrum analyzer visualization. * Error Responses All endpoints may return error responses in this format: #+BEGIN_SRC json { "status": "error", "message": "Description of the error" } #+END_SRC ** Common HTTP Status Codes - =200= - Success - =400= - Bad Request (missing or invalid parameters) - =401= - Unauthorized (authentication required) - =403= - Forbidden (insufficient permissions) - =404= - Not Found (resource doesn't exist) - =500= - Internal Server Error * Testing API Endpoints ** Using curl #+BEGIN_SRC bash # Get server status curl http://localhost:8080/api/asteroid/status # Get auth status curl http://localhost:8080/api/asteroid/auth-status # Get tracks (requires authentication) curl -b cookies.txt http://localhost:8080/api/asteroid/tracks # Play a track curl -X POST -b cookies.txt http://localhost:8080/api/asteroid/player/play \ -d "track-id=123" #+END_SRC ** Using the Test Suite The project includes a comprehensive test suite: #+BEGIN_SRC bash ./test-server.sh #+END_SRC See =docs/TESTING.org= for details. * Browser Detection API endpoints support a =browser= parameter for dual usage (API + browser): #+BEGIN_SRC bash # API usage - returns JSON curl -X POST http://localhost:8080/api/asteroid/playlists/create \ -d "name=Test" # Browser usage - redirects to page curl -X POST http://localhost:8080/api/asteroid/playlists/create \ -d "name=Test&browser=true" #+END_SRC When =browser=true= is passed, endpoints will redirect to appropriate pages instead of returning JSON. * Rate Limiting API endpoints implement rate limiting to prevent abuse. Excessive requests may result in temporary blocking. * Future Enhancements Planned API improvements: - WebSocket support for real-time updates - Pagination for large result sets - Advanced search and filtering - Batch operations - API versioning - OAuth2 authentication option