# Serena API docs ## Overview **Base URL:** `http://localhost:8080/api` ## Authentication The API uses Bearer token authentication. Include the token in the Authorization header: ``` Authorization: Bearer ``` ### Token Types - **Owner Token**: Generated when creating a radio station, allows full station management - **Client Token**: Generated when joining a station, allows participation in the station ## API Endpoints ### Radio Station Management #### Create Radio Station Creates a new radio station and returns an owner token. **Endpoint:** `POST /radio-stations` **Request Body:** ```json { "name": "My Awesome Station", "description": "The best music station ever" } ``` **Response:** ```json { "success": true, "message": "Radio station created successfully", "data": { "station": { "id": "station-uuid", "name": "My Awesome Station", "description": "The best music station ever", "ownerId": "owner-uuid", "joinCode": "ABC123", "createdAt": "2025-08-01T10:00:00", "active": true, "connectedClients": [], "songQueue": [], "currentlyPlaying": null }, "ownerToken": "jwt-token-here", "message": "Radio station created successfully. Use this token to manage your station." } } ``` #### Get All Radio Stations Retrieves all radio stations. Requires authentication. **Endpoint:** `GET /radio-stations?activeOnly=true` **Query Parameters:** - `activeOnly` (boolean, default: false): Filter to only active stations **Response:** ```json { "success": true, "message": "Success", "data": [ { "id": "station-uuid", "name": "Station Name", "description": "Station Description", "ownerId": "owner-uuid", "joinCode": "ABC123", "createdAt": "2025-08-01T10:00:00", "active": true, "connectedClients": ["client1", "client2"], "songQueue": [], "currentlyPlaying": null } ] } ``` #### Get Radio Station by ID Retrieves a specific radio station. Requires authentication. **Endpoint:** `GET /radio-stations/{stationId}` **Response:** ```json { "success": true, "message": "Success", "data": { "id": "station-uuid", "name": "Station Name", "description": "Station Description", "ownerId": "owner-uuid", "joinCode": "ABC123", "createdAt": "2025-08-01T10:00:00", "active": true, "connectedClients": [], "songQueue": [], "currentlyPlaying": null } } ``` #### Get Radio Station by Join Code Retrieves a radio station using its join code. No authentication required. **Endpoint:** `GET /radio-stations/join/{joinCode}` **Response:** ```json { "success": true, "message": "Success", "data": { "id": "station-uuid", "name": "Station Name", "description": "Station Description", "ownerId": "owner-uuid", "joinCode": "ABC123", "createdAt": "2025-08-01T10:00:00", "active": true, "connectedClients": [], "songQueue": [], "currentlyPlaying": null } } ``` #### Update Radio Station Updates a radio station. Only the station owner can update it. **Endpoint:** `PUT /radio-stations/{stationId}` **Request Body:** ```json { "name": "Updated Station Name", "description": "Updated description" } ``` **Response:** ```json { "success": true, "message": "Radio station updated successfully", "data": { "id": "station-uuid", "name": "Updated Station Name", "description": "Updated description", "ownerId": "owner-uuid", "joinCode": "ABC123", "createdAt": "2025-08-01T10:00:00", "active": true, "connectedClients": [], "songQueue": [], "currentlyPlaying": null } } ``` #### Delete Radio Station Deletes a radio station. Only the station owner can delete it. **Endpoint:** `DELETE /radio-stations/{stationId}` **Response:** ```json { "success": true, "message": "Radio station deleted successfully", "data": null } ``` ### Client Management #### Connect Client to Station Connects a client to a radio station using a join code. No authentication required. **Endpoint:** `POST /clients/connect` **Request Body (Option 1 - Using station ID and join code):** ```json { "username": "john_doe", "radioStationId": "station-uuid", "joinCode": "ABC123" } ``` **Request Body (Option 2 - Using join code only):** ```json { "username": "john_doe", "joinCode": "ABC123" } ``` **Response:** ```json { "success": true, "message": "Successfully connected to radio station", "data": { "client": { "id": "client-uuid", "username": "john_doe", "radioStationId": "station-uuid", "connectedAt": "2025-08-01T10:00:00", "active": true }, "clientToken": "jwt-token-here", "message": "Successfully connected to radio station. Use this token for further requests." } } ``` #### Disconnect Client Disconnects a client from a station. Only the station owner can disconnect clients. **Endpoint:** `DELETE /clients/{clientId}/disconnect` **Response:** ```json { "success": true, "message": "Client disconnected successfully", "data": null } ``` #### Get Client Information Retrieves information about a specific client. Requires authentication. **Endpoint:** `GET /clients/{clientId}` **Response:** ```json { "success": true, "message": "Success", "data": { "id": "client-uuid", "username": "john_doe", "radioStationId": "station-uuid", "connectedAt": "2025-08-01T10:00:00", "active": true } } ``` #### Get Connected Clients Retrieves all clients connected to a radio station. Requires authentication. **Endpoint:** `GET /clients/station/{radioStationId}` **Response:** ```json { "success": true, "message": "Success", "data": [ { "id": "client-uuid", "username": "john_doe", "radioStationId": "station-uuid", "connectedAt": "2025-08-01T10:00:00", "active": true } ] } ``` ### Song Management #### Add Song to Queue Adds a song to the station's queue. Requires authentication. **Endpoint:** `POST /radio-stations/{stationId}/songs` **Request Body:** ```json { "title": "Bohemian Rhapsody", "artist": "Queen", "album": "A Night at the Opera", "duration": 355, "url": "https://example.com/song.mp3" } ``` **Response:** ```json { "success": true, "message": "Song added to queue successfully", "data": { "id": "song-uuid", "title": "Bohemian Rhapsody", "artist": "Queen", "album": "A Night at the Opera", "duration": 355, "url": "https://example.com/song.mp3", "addedBy": "user-uuid", "addedAt": "2025-08-01T10:00:00", "votes": {}, "upvotes": 0, "downvotes": 0 } } ``` #### Get Song Queue Retrieves the current song queue, sorted by score (upvotes - downvotes). Requires authentication. **Endpoint:** `GET /radio-stations/{stationId}/songs/queue` **Response:** ```json { "success": true, "message": "Success", "data": [ { "id": "song-uuid", "title": "Bohemian Rhapsody", "artist": "Queen", "album": "A Night at the Opera", "duration": 355, "url": "https://example.com/song.mp3", "addedBy": "user-uuid", "addedAt": "2025-08-01T10:00:00", "votes": { "user1": "UPVOTE", "user2": "DOWNVOTE" }, "upvotes": 1, "downvotes": 1 } ] } ``` #### Get Currently Playing Song Retrieves the currently playing song. Requires authentication. **Endpoint:** `GET /radio-stations/{stationId}/songs/current` **Response:** ```json { "success": true, "message": "Success", "data": { "id": "song-uuid", "title": "Bohemian Rhapsody", "artist": "Queen", "album": "A Night at the Opera", "duration": 355, "url": "https://example.com/song.mp3", "addedBy": "user-uuid", "addedAt": "2025-08-01T10:00:00", "votes": {}, "upvotes": 0, "downvotes": 0 } } ``` #### Play Next Song Plays the next song from the queue (highest scoring song). Only station owners can control playback. **Endpoint:** `POST /radio-stations/{stationId}/songs/next` **Response:** ```json { "success": true, "message": "Playing next song", "data": { "id": "song-uuid", "title": "Bohemian Rhapsody", "artist": "Queen", "album": "A Night at the Opera", "duration": 355, "url": "https://example.com/song.mp3", "addedBy": "user-uuid", "addedAt": "2025-08-01T10:00:00", "votes": {}, "upvotes": 0, "downvotes": 0 } } ``` #### Vote on Song Casts a vote (upvote or downvote) on a song. Requires authentication. **Endpoint:** `POST /radio-stations/{stationId}/songs/{songId}/vote` **Request Body:** ```json { "voteType": "UPVOTE" } ``` **Vote Types:** - `UPVOTE`: Positive vote - `DOWNVOTE`: Negative vote **Response:** ```json { "success": true, "message": "Vote recorded successfully", "data": { "id": "song-uuid", "title": "Bohemian Rhapsody", "artist": "Queen", "album": "A Night at the Opera", "duration": 355, "url": "https://example.com/song.mp3", "addedBy": "user-uuid", "addedAt": "2025-08-01T10:00:00", "votes": { "current-user-id": "UPVOTE" }, "upvotes": 1, "downvotes": 0 } } ``` #### Remove Vote from Song Removes the current user's vote from a song. Requires authentication. **Endpoint:** `DELETE /radio-stations/{stationId}/songs/{songId}/vote` **Response:** ```json { "success": true, "message": "Vote removed successfully", "data": null } ``` ## Error Responses All error responses follow this format: ```json { "success": false, "message": "Error description", "data": null } ``` ### Common HTTP Status Codes - `200 OK`: Request successful - `201 Created`: Resource created successfully - `400 Bad Request`: Invalid request data - `401 Unauthorized`: Authentication required or token invalid - `403 Forbidden`: Access denied (e.g., not station owner) - `404 Not Found`: Resource not found ### Common Error Messages - `"User not authenticated"`: Missing or invalid authentication token - `"Radio station not found"`: Station ID or join code not found - `"Only the station owner can..."`: Action requires owner privileges - `"Failed to connect to radio station. Invalid join code or station not found."`: Join code is invalid - `"Client not found"`: Client ID not found ## Usage Examples ### Creating a Station and Adding Songs 1. **Create a station:** ```bash curl -X POST http://localhost:8080/api/radio-stations \ -H "Content-Type: application/json" \ -d '{"name": "My Station", "description": "Great music"}' ``` 2. **Use the returned owner token for authenticated requests:** ```bash curl -X POST http://localhost:8080/api/radio-stations/{stationId}/songs \ -H "Authorization: Bearer {ownerToken}" \ -H "Content-Type: application/json" \ -d '{"title": "Song Title", "artist": "Artist", "duration": 180, "url": "http://example.com/song.mp3"}' ``` ### Joining a Station and Voting 1. **Join a station:** ```bash curl -X POST http://localhost:8080/api/clients/connect \ -H "Content-Type: application/json" \ -d '{"username": "john", "joinCode": "ABC123"}' ``` 2. **Vote on a song:** ```bash curl -X POST http://localhost:8080/api/radio-stations/{stationId}/songs/{songId}/vote \ -H "Authorization: Bearer {clientToken}" \ -H "Content-Type: application/json" \ -d '{"voteType": "UPVOTE"}' ``` ## Notes - Join codes are 6-character alphanumeric strings automatically generated for each station - Songs in the queue are sorted by score (upvotes - downvotes) in descending order - Users can change their vote on a song, but only have one vote per song - Only station owners can control playback (play next song) - Tokens expire after 7 days - The system uses in-memory storage, so data is lost when the server restarts