project-standalo-sonic-cloud/docs/API_REFERENCE.md

2001 lines
40 KiB
Markdown

# API Reference
Comprehensive API documentation for Sonic Cloud platform endpoints.
---
## Authentication Endpoints
API endpoints for user registration, login, and password recovery.
### POST /api/auth/register
**Description**: Register a new user account on the platform.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**Request Body**:
```json
{
"email": "user@example.com",
"password": "securePassword123",
"username": "username",
"displayName": "Display Name" // Optional
}
```
**Response** (201 Created):
```json
{
"user": {
"id": "uuid",
"email": "user@example.com",
"username": "username",
"displayName": "Display Name",
"role": "USER"
},
"token": "jwt_token_string"
}
```
**Error Responses**:
- 400 Bad Request: Missing required fields or invalid email format
- 409 Conflict: Email or username already exists
**Implementation**: `app/api/auth/register/route.ts`
</details>
---
### POST /api/auth/login
**Description**: Authenticate user credentials and receive a session token.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**Request Body**:
```json
{
"email": "user@example.com",
"password": "securePassword123"
}
```
**Response** (200 OK):
```json
{
"user": {
"id": "uuid",
"email": "user@example.com",
"username": "username",
"displayName": "Display Name",
"role": "USER"
},
"token": "jwt_token_string"
}
```
**Error Responses**:
- 400 Bad Request: Missing email or password
- 401 Unauthorized: Invalid credentials
**Implementation**: `app/api/auth/login/route.ts`
</details>
---
### POST /api/auth/forgot-password
**Description**: Initiate password reset process by sending reset token via email.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**Request Body**:
```json
{
"email": "user@example.com"
}
```
**Response** (200 OK):
```json
{
"message": "Password reset email sent"
}
```
**Error Responses**:
- 400 Bad Request: Missing email
- 404 Not Found: User with email not found
**Implementation**: `app/api/auth/forgot-password/route.ts`
**Note**: Reset token is generated and stored with expiration timestamp. Token is sent via email (email service integration required).
</details>
---
### POST /api/auth/reset-password
**Description**: Reset user password using a valid reset token from email.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**Request Body**:
```json
{
"token": "reset_token_from_email",
"newPassword": "newSecurePassword123"
}
```
**Response** (200 OK):
```json
{
"message": "Password reset successful"
}
```
**Error Responses**:
- 400 Bad Request: Missing token or newPassword
- 401 Unauthorized: Invalid or expired token
- 404 Not Found: User not found
**Implementation**: `app/api/auth/reset-password/route.ts`
</details>
---
## User Endpoints
API endpoints for managing user profile information.
### GET /api/users/me
**Description**: Retrieve the current authenticated user's profile information.
**Authentication**: Required (JWT token)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**Response** (200 OK):
```json
{
"id": "uuid",
"email": "user@example.com",
"username": "username",
"displayName": "Display Name",
"bio": "User biography text",
"avatarUrl": "https://example.com/avatar.jpg",
"websiteUrl": "https://example.com",
"role": "USER",
"createdAt": "2025-01-01T00:00:00.000Z",
"artist": {
"id": "uuid",
"name": "Artist Name"
} // If user is an artist
}
```
**Error Responses**:
- 401 Unauthorized: Missing or invalid token
- 404 Not Found: User not found
**Implementation**: `app/api/users/me/route.ts`
</details>
---
### PUT /api/users/me
**Description**: Update the current authenticated user's profile information.
**Authentication**: Required (JWT token)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**Request Body** (all fields optional):
```json
{
"displayName": "New Display Name",
"bio": "Updated biography",
"avatarUrl": "https://example.com/new-avatar.jpg",
"websiteUrl": "https://example.com"
}
```
**Response** (200 OK):
```json
{
"id": "uuid",
"email": "user@example.com",
"username": "username",
"displayName": "New Display Name",
"bio": "Updated biography",
"avatarUrl": "https://example.com/new-avatar.jpg",
"websiteUrl": "https://example.com",
"role": "USER"
}
```
**Error Responses**:
- 401 Unauthorized: Missing or invalid token
- 404 Not Found: User not found
**Implementation**: `app/api/users/me/route.ts`
</details>
---
## Artist Endpoints
API endpoints for managing artist profiles, songs, and albums.
### POST /api/artists
**Description**: Create a new artist profile for the authenticated user.
**Authentication**: Required (JWT token)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**Request Body**:
```json
{
"name": "Artist Name",
"bio": "Artist biography",
"avatarUrl": "https://example.com/avatar.jpg",
"bannerUrl": "https://example.com/banner.jpg",
"websiteUrl": "https://example.com",
"spotifyUrl": "https://open.spotify.com/artist/...",
"instagramUrl": "https://instagram.com/artist"
}
```
**Response** (201 Created):
```json
{
"id": "uuid",
"userId": "uuid",
"name": "Artist Name",
"slug": "artist-name",
"bio": "Artist biography",
"verified": false,
"createdAt": "2025-01-01T00:00:00.000Z"
}
```
**Error Responses**:
- 400 Bad Request: Missing required fields or user already has artist profile
- 401 Unauthorized: Missing or invalid token
**Implementation**: `app/api/artists/route.ts`
**Note**: Slug is auto-generated from artist name for URL-friendly identifiers.
</details>
---
### GET /api/artists/{id}
**Description**: Retrieve detailed information about a specific artist including statistics and relationships.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Artist UUID
**Response** (200 OK):
```json
{
"id": "uuid",
"name": "Artist Name",
"slug": "artist-name",
"bio": "Artist biography",
"avatarUrl": "https://example.com/avatar.jpg",
"bannerUrl": "https://example.com/banner.jpg",
"verified": true,
"websiteUrl": "https://example.com",
"spotifyUrl": "https://open.spotify.com/artist/...",
"instagramUrl": "https://instagram.com/artist",
"createdAt": "2025-01-01T00:00:00.000Z",
"_count": {
"songs": 42,
"albums": 5
},
"label": {
"id": "uuid",
"name": "Label Name"
} // If artist is signed to label
}
```
**Error Responses**:
- 404 Not Found: Artist not found
**Implementation**: `app/api/artists/[id]/route.ts`
</details>
---
### PUT /api/artists/{id}
**Description**: Update artist profile information. Only the artist owner can perform this action.
**Authentication**: Required (JWT token, owner only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**URL Parameters**:
- `id` (string): Artist UUID
**Request Body** (all fields optional):
```json
{
"name": "Updated Artist Name",
"bio": "Updated biography",
"avatarUrl": "https://example.com/new-avatar.jpg",
"bannerUrl": "https://example.com/new-banner.jpg",
"websiteUrl": "https://example.com",
"spotifyUrl": "https://open.spotify.com/artist/...",
"instagramUrl": "https://instagram.com/artist"
}
```
**Response** (200 OK):
```json
{
"id": "uuid",
"name": "Updated Artist Name",
"slug": "updated-artist-name",
"bio": "Updated biography",
"verified": true
}
```
**Error Responses**:
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not the artist owner
- 404 Not Found: Artist not found
**Implementation**: `app/api/artists/[id]/route.ts`
</details>
---
### GET /api/artists/{id}/songs
**Description**: Retrieve all public songs by a specific artist.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Artist UUID
**Response** (200 OK):
```json
[
{
"id": "uuid",
"title": "Song Title",
"duration": 240,
"audioUrl": "https://example.com/audio.mp3",
"coverUrl": "https://example.com/cover.jpg",
"playCount": 1234,
"isPublic": true,
"createdAt": "2025-01-01T00:00:00.000Z",
"album": {
"id": "uuid",
"title": "Album Title"
},
"genres": [
{ "name": "Rock", "slug": "rock" }
]
}
]
```
**Error Responses**:
- 404 Not Found: Artist not found
**Implementation**: `app/api/artists/[id]/songs/route.ts`
**Note**: Only returns songs where `isPublic = true`.
</details>
---
### GET /api/artists/{id}/albums
**Description**: Retrieve all albums by a specific artist, sorted by release date (newest first).
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Artist UUID
**Response** (200 OK):
```json
[
{
"id": "uuid",
"title": "Album Title",
"coverUrl": "https://example.com/cover.jpg",
"releaseDate": "2025-01-01T00:00:00.000Z",
"albumType": "ALBUM", // or "EP", "SINGLE"
"_count": {
"songs": 12
}
}
]
```
**Error Responses**:
- 404 Not Found: Artist not found
**Implementation**: `app/api/artists/[id]/albums/route.ts`
</details>
---
## Song Endpoints
API endpoints for uploading, managing, and tracking song playback.
### POST /api/songs/upload
**Description**: Upload a new song to the platform. Only users with artist profiles can upload songs.
**Authentication**: Required (JWT token, artist only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**Request Body**:
```json
{
"title": "Song Title",
"audioUrl": "https://example.com/audio.mp3",
"coverUrl": "https://example.com/cover.jpg",
"duration": 240, // in seconds
"albumId": "uuid", // Optional
"isPublic": true,
"genres": ["rock", "indie"] // Array of genre slugs
}
```
**Response** (201 Created):
```json
{
"id": "uuid",
"artistId": "uuid",
"title": "Song Title",
"audioUrl": "https://example.com/audio.mp3",
"coverUrl": "https://example.com/cover.jpg",
"duration": 240,
"playCount": 0,
"isPublic": true,
"createdAt": "2025-01-01T00:00:00.000Z"
}
```
**Error Responses**:
- 400 Bad Request: Missing required fields
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not an artist
**Implementation**: `app/api/songs/upload/route.ts`
</details>
---
### GET /api/songs/{id}
**Description**: Retrieve detailed information about a specific song. Public songs are always accessible, private songs only accessible to owner.
**Authentication**: Optional (required for private songs)
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Song UUID
**Request Headers** (optional for public songs):
```
Authorization: Bearer jwt_token_string
```
**Response** (200 OK):
```json
{
"id": "uuid",
"title": "Song Title",
"audioUrl": "https://example.com/audio.mp3",
"coverUrl": "https://example.com/cover.jpg",
"duration": 240,
"playCount": 1234,
"isPublic": true,
"createdAt": "2025-01-01T00:00:00.000Z",
"artist": {
"id": "uuid",
"name": "Artist Name",
"slug": "artist-name",
"verified": true
},
"album": {
"id": "uuid",
"title": "Album Title",
"coverUrl": "https://example.com/album-cover.jpg"
},
"genres": [
{
"id": "uuid",
"name": "Rock",
"slug": "rock",
"color": "#FF0000"
}
]
}
```
**Error Responses**:
- 403 Forbidden: Song is private and user is not owner
- 404 Not Found: Song not found
**Implementation**: `app/api/songs/[id]/route.ts`
</details>
---
### PUT /api/songs/{id}
**Description**: Update song information. Only the song owner (artist) can perform this action.
**Authentication**: Required (JWT token, owner only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**URL Parameters**:
- `id` (string): Song UUID
**Request Body** (all fields optional):
```json
{
"title": "Updated Song Title",
"coverUrl": "https://example.com/new-cover.jpg",
"isPublic": false,
"albumId": "uuid",
"genres": ["rock", "pop"]
}
```
**Response** (200 OK):
```json
{
"id": "uuid",
"title": "Updated Song Title",
"coverUrl": "https://example.com/new-cover.jpg",
"isPublic": false,
"updatedAt": "2025-01-01T00:00:00.000Z"
}
```
**Error Responses**:
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not the song owner
- 404 Not Found: Song not found
**Implementation**: `app/api/songs/[id]/route.ts`
</details>
---
### DELETE /api/songs/{id}
**Description**: Delete a song from the platform. Only the song owner (artist) can perform this action.
**Authentication**: Required (JWT token, owner only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**URL Parameters**:
- `id` (string): Song UUID
**Response** (204 No Content)
**Error Responses**:
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not the song owner
- 404 Not Found: Song not found
**Implementation**: `app/api/songs/[id]/route.ts`
**Note**: Deleting a song also removes it from all playlists and deletes associated share links.
</details>
---
### POST /api/songs/{id}/play
**Description**: Increment the play count for a song. Used for tracking song popularity.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Song UUID
**Response** (200 OK):
```json
{
"playCount": 1235
}
```
**Error Responses**:
- 404 Not Found: Song not found
**Implementation**: `app/api/songs/[id]/play/route.ts`
**Note**: This endpoint is called each time a song starts playing. It's rate-limited per user to prevent abuse.
</details>
---
## Album Endpoints
API endpoints for creating and managing music albums.
### POST /api/albums
**Description**: Create a new album. Only users with artist profiles can create albums.
**Authentication**: Required (JWT token, artist only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**Request Body**:
```json
{
"title": "Album Title",
"coverUrl": "https://example.com/cover.jpg",
"releaseDate": "2025-01-01",
"albumType": "ALBUM", // or "EP", "SINGLE"
"description": "Album description text"
}
```
**Response** (201 Created):
```json
{
"id": "uuid",
"artistId": "uuid",
"title": "Album Title",
"coverUrl": "https://example.com/cover.jpg",
"releaseDate": "2025-01-01T00:00:00.000Z",
"albumType": "ALBUM",
"description": "Album description text",
"createdAt": "2025-01-01T00:00:00.000Z"
}
```
**Error Responses**:
- 400 Bad Request: Missing required fields
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not an artist
**Implementation**: `app/api/albums/route.ts`
</details>
---
### GET /api/albums/{id}
**Description**: Retrieve album details including all songs in the album.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Album UUID
**Response** (200 OK):
```json
{
"id": "uuid",
"title": "Album Title",
"coverUrl": "https://example.com/cover.jpg",
"releaseDate": "2025-01-01T00:00:00.000Z",
"albumType": "ALBUM",
"description": "Album description text",
"artist": {
"id": "uuid",
"name": "Artist Name",
"slug": "artist-name",
"verified": true
},
"songs": [
{
"id": "uuid",
"title": "Song Title",
"duration": 240,
"trackNumber": 1,
"audioUrl": "https://example.com/audio.mp3",
"playCount": 1234
}
]
}
```
**Error Responses**:
- 404 Not Found: Album not found
**Implementation**: `app/api/albums/[id]/route.ts`
</details>
---
### PUT /api/albums/{id}
**Description**: Update album information. Only the album owner (artist) can perform this action.
**Authentication**: Required (JWT token, owner only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**URL Parameters**:
- `id` (string): Album UUID
**Request Body** (all fields optional):
```json
{
"title": "Updated Album Title",
"coverUrl": "https://example.com/new-cover.jpg",
"description": "Updated description",
"albumType": "EP"
}
```
**Response** (200 OK):
```json
{
"id": "uuid",
"title": "Updated Album Title",
"coverUrl": "https://example.com/new-cover.jpg",
"description": "Updated description",
"albumType": "EP",
"updatedAt": "2025-01-01T00:00:00.000Z"
}
```
**Error Responses**:
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not the album owner
- 404 Not Found: Album not found
**Implementation**: `app/api/albums/[id]/route.ts`
</details>
---
### DELETE /api/albums/{id}
**Description**: Delete an album from the platform. Only the album owner (artist) can perform this action.
**Authentication**: Required (JWT token, owner only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**URL Parameters**:
- `id` (string): Album UUID
**Response** (204 No Content)
**Error Responses**:
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not the album owner
- 404 Not Found: Album not found
**Implementation**: `app/api/albums/[id]/route.ts`
**Note**: Deleting an album does NOT delete the songs in the album. Songs become album-less but remain on the platform.
</details>
---
## Playlist Endpoints
API endpoints for creating and managing user playlists.
### GET /api/playlists
**Description**: Retrieve all playlists created by the authenticated user.
**Authentication**: Required (JWT token)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**Response** (200 OK):
```json
[
{
"id": "uuid",
"title": "Playlist Title",
"description": "Playlist description",
"coverUrl": "https://example.com/cover.jpg",
"isPublic": true,
"createdAt": "2025-01-01T00:00:00.000Z",
"_count": {
"songs": 24
}
}
]
```
**Error Responses**:
- 401 Unauthorized: Missing or invalid token
**Implementation**: `app/api/playlists/route.ts`
</details>
---
### POST /api/playlists
**Description**: Create a new playlist for the authenticated user.
**Authentication**: Required (JWT token)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**Request Body**:
```json
{
"title": "Playlist Title",
"description": "Playlist description",
"coverUrl": "https://example.com/cover.jpg",
"isPublic": true
}
```
**Response** (201 Created):
```json
{
"id": "uuid",
"userId": "uuid",
"title": "Playlist Title",
"description": "Playlist description",
"coverUrl": "https://example.com/cover.jpg",
"isPublic": true,
"createdAt": "2025-01-01T00:00:00.000Z"
}
```
**Error Responses**:
- 400 Bad Request: Missing title
- 401 Unauthorized: Missing or invalid token
**Implementation**: `app/api/playlists/route.ts`
</details>
---
### GET /api/playlists/{id}
**Description**: Retrieve playlist details with all songs. Public playlists are accessible to everyone, private playlists only to owner.
**Authentication**: Optional (required for private playlists)
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Playlist UUID
**Request Headers** (optional for public playlists):
```
Authorization: Bearer jwt_token_string
```
**Response** (200 OK):
```json
{
"id": "uuid",
"title": "Playlist Title",
"description": "Playlist description",
"coverUrl": "https://example.com/cover.jpg",
"isPublic": true,
"createdAt": "2025-01-01T00:00:00.000Z",
"user": {
"id": "uuid",
"username": "username",
"displayName": "Display Name"
},
"songs": [
{
"id": "uuid",
"song": {
"id": "uuid",
"title": "Song Title",
"duration": 240,
"audioUrl": "https://example.com/audio.mp3",
"coverUrl": "https://example.com/cover.jpg",
"artist": {
"id": "uuid",
"name": "Artist Name"
}
},
"position": 1,
"addedAt": "2025-01-01T00:00:00.000Z"
}
]
}
```
**Error Responses**:
- 403 Forbidden: Playlist is private and user is not owner
- 404 Not Found: Playlist not found
**Implementation**: `app/api/playlists/[id]/route.ts`
</details>
---
### PUT /api/playlists/{id}
**Description**: Update playlist information. Only the playlist owner can perform this action.
**Authentication**: Required (JWT token, owner only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**URL Parameters**:
- `id` (string): Playlist UUID
**Request Body** (all fields optional):
```json
{
"title": "Updated Playlist Title",
"description": "Updated description",
"coverUrl": "https://example.com/new-cover.jpg",
"isPublic": false
}
```
**Response** (200 OK):
```json
{
"id": "uuid",
"title": "Updated Playlist Title",
"description": "Updated description",
"coverUrl": "https://example.com/new-cover.jpg",
"isPublic": false,
"updatedAt": "2025-01-01T00:00:00.000Z"
}
```
**Error Responses**:
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not the playlist owner
- 404 Not Found: Playlist not found
**Implementation**: `app/api/playlists/[id]/route.ts`
</details>
---
### DELETE /api/playlists/{id}
**Description**: Delete a playlist. Only the playlist owner can perform this action.
**Authentication**: Required (JWT token, owner only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**URL Parameters**:
- `id` (string): Playlist UUID
**Response** (204 No Content)
**Error Responses**:
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not the playlist owner
- 404 Not Found: Playlist not found
**Implementation**: `app/api/playlists/[id]/route.ts`
**Note**: Deleting a playlist does NOT delete the songs in it, only the playlist container.
</details>
---
### POST /api/playlists/{id}/songs
**Description**: Add a song to a playlist. Only the playlist owner can add songs.
**Authentication**: Required (JWT token, owner only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**URL Parameters**:
- `id` (string): Playlist UUID
**Request Body**:
```json
{
"songId": "uuid"
}
```
**Response** (200 OK):
```json
{
"id": "uuid",
"playlistId": "uuid",
"songId": "uuid",
"position": 5,
"addedAt": "2025-01-01T00:00:00.000Z"
}
```
**Error Responses**:
- 400 Bad Request: Missing songId or song already in playlist
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not the playlist owner
- 404 Not Found: Playlist or song not found
**Implementation**: `app/api/playlists/[id]/songs/route.ts`
**Note**: Position is automatically assigned as the last position in the playlist.
</details>
---
### PUT /api/playlists/{id}/reorder
**Description**: Reorder songs within a playlist. Only the playlist owner can reorder songs.
**Authentication**: Required (JWT token, owner only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**URL Parameters**:
- `id` (string): Playlist UUID
**Request Body**:
```json
{
"songIds": ["uuid1", "uuid2", "uuid3"]
}
```
**Response** (200 OK):
```json
{
"message": "Playlist reordered successfully"
}
```
**Error Responses**:
- 400 Bad Request: Missing songIds array or songIds don't match playlist
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not the playlist owner
- 404 Not Found: Playlist not found
**Implementation**: `app/api/playlists/[id]/reorder/route.ts`
**Note**: All songs in the playlist must be included in the songIds array in the desired order.
</details>
---
## Discovery Endpoints
API endpoints for discovering trending music, new releases, and browsing by genre.
### GET /api/discover/trending
**Description**: Retrieve trending public songs sorted by play count.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**Query Parameters**:
- `limit` (number, optional): Number of results to return (default: 20, max: 100)
**Response** (200 OK):
```json
[
{
"id": "uuid",
"title": "Song Title",
"duration": 240,
"audioUrl": "https://example.com/audio.mp3",
"coverUrl": "https://example.com/cover.jpg",
"playCount": 5432,
"artist": {
"id": "uuid",
"name": "Artist Name",
"slug": "artist-name",
"verified": true
},
"genres": [
{ "name": "Rock", "slug": "rock", "color": "#FF0000" }
]
}
]
```
**Implementation**: `app/api/discover/trending/route.ts`
**Note**: Only returns songs where `isPublic = true`, sorted by `playCount` descending.
</details>
---
### GET /api/discover/new-releases
**Description**: Retrieve recently uploaded public songs sorted by creation date.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**Query Parameters**:
- `limit` (number, optional): Number of results to return (default: 20, max: 100)
**Response** (200 OK):
```json
[
{
"id": "uuid",
"title": "Song Title",
"duration": 240,
"audioUrl": "https://example.com/audio.mp3",
"coverUrl": "https://example.com/cover.jpg",
"createdAt": "2025-01-01T00:00:00.000Z",
"artist": {
"id": "uuid",
"name": "Artist Name",
"slug": "artist-name",
"verified": true
},
"genres": [
{ "name": "Pop", "slug": "pop", "color": "#00FF00" }
]
}
]
```
**Implementation**: `app/api/discover/new-releases/route.ts`
**Note**: Only returns songs where `isPublic = true`, sorted by `createdAt` descending.
</details>
---
### GET /api/discover/genres
**Description**: Retrieve all available genres with song counts.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**Response** (200 OK):
```json
[
{
"id": "uuid",
"name": "Rock",
"slug": "rock",
"description": "Rock music genre",
"color": "#FF0000",
"_count": {
"songs": 142
}
},
{
"id": "uuid",
"name": "Pop",
"slug": "pop",
"description": "Pop music genre",
"color": "#00FF00",
"_count": {
"songs": 98
}
}
]
```
**Implementation**: `app/api/discover/genres/route.ts`
</details>
---
### GET /api/discover/genres/{slug}
**Description**: Retrieve all public songs in a specific genre.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `slug` (string): Genre slug (e.g., "rock", "pop", "jazz")
**Query Parameters**:
- `limit` (number, optional): Number of results to return (default: 50, max: 100)
**Response** (200 OK):
```json
{
"genre": {
"id": "uuid",
"name": "Rock",
"slug": "rock",
"description": "Rock music genre",
"color": "#FF0000"
},
"songs": [
{
"id": "uuid",
"title": "Song Title",
"duration": 240,
"audioUrl": "https://example.com/audio.mp3",
"coverUrl": "https://example.com/cover.jpg",
"playCount": 1234,
"artist": {
"id": "uuid",
"name": "Artist Name",
"verified": true
}
}
]
}
```
**Error Responses**:
- 404 Not Found: Genre not found
**Implementation**: `app/api/discover/genres/[slug]/route.ts`
</details>
---
## Label Endpoints
API endpoints for managing record label profiles and artist rosters.
### POST /api/labels
**Description**: Create a new record label profile for the authenticated user.
**Authentication**: Required (JWT token)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**Request Body**:
```json
{
"name": "Label Name",
"description": "Label description",
"logoUrl": "https://example.com/logo.png",
"websiteUrl": "https://example.com",
"contactEmail": "contact@label.com"
}
```
**Response** (201 Created):
```json
{
"id": "uuid",
"userId": "uuid",
"name": "Label Name",
"slug": "label-name",
"description": "Label description",
"logoUrl": "https://example.com/logo.png",
"websiteUrl": "https://example.com",
"contactEmail": "contact@label.com",
"createdAt": "2025-01-01T00:00:00.000Z"
}
```
**Error Responses**:
- 400 Bad Request: Missing required fields or user already has label profile
- 401 Unauthorized: Missing or invalid token
**Implementation**: `app/api/labels/route.ts`
</details>
---
### GET /api/labels/{id}
**Description**: Retrieve label details with artist roster list.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Label UUID
**Response** (200 OK):
```json
{
"id": "uuid",
"name": "Label Name",
"slug": "label-name",
"description": "Label description",
"logoUrl": "https://example.com/logo.png",
"websiteUrl": "https://example.com",
"contactEmail": "contact@label.com",
"createdAt": "2025-01-01T00:00:00.000Z",
"artists": [
{
"id": "uuid",
"name": "Artist Name",
"slug": "artist-name",
"verified": true,
"avatarUrl": "https://example.com/avatar.jpg"
}
]
}
```
**Error Responses**:
- 404 Not Found: Label not found
**Implementation**: `app/api/labels/[id]/route.ts`
</details>
---
### PUT /api/labels/{id}
**Description**: Update label profile information. Only the label owner can perform this action.
**Authentication**: Required (JWT token, owner only)
<details>
<summary>🔧 Technical Details</summary>
**Request Headers**:
```
Authorization: Bearer jwt_token_string
```
**URL Parameters**:
- `id` (string): Label UUID
**Request Body** (all fields optional):
```json
{
"name": "Updated Label Name",
"description": "Updated description",
"logoUrl": "https://example.com/new-logo.png",
"websiteUrl": "https://example.com",
"contactEmail": "newcontact@label.com"
}
```
**Response** (200 OK):
```json
{
"id": "uuid",
"name": "Updated Label Name",
"slug": "updated-label-name",
"description": "Updated description",
"logoUrl": "https://example.com/new-logo.png",
"updatedAt": "2025-01-01T00:00:00.000Z"
}
```
**Error Responses**:
- 401 Unauthorized: Missing or invalid token
- 403 Forbidden: User is not the label owner
- 404 Not Found: Label not found
**Implementation**: `app/api/labels/[id]/route.ts`
</details>
---
### GET /api/labels/{id}/stats
**Description**: Retrieve statistical information about a label including artist count, total songs, albums, and play counts.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Label UUID
**Response** (200 OK):
```json
{
"artistCount": 15,
"totalSongs": 342,
"totalAlbums": 48,
"totalPlays": 123456
}
```
**Error Responses**:
- 404 Not Found: Label not found
**Implementation**: `app/api/labels/[id]/stats/route.ts`
</details>
---
### GET /api/labels/{id}/artists
**Description**: Retrieve all artists signed to a specific label.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Label UUID
**Response** (200 OK):
```json
[
{
"id": "uuid",
"name": "Artist Name",
"slug": "artist-name",
"bio": "Artist biography",
"avatarUrl": "https://example.com/avatar.jpg",
"verified": true,
"_count": {
"songs": 24,
"albums": 3
}
}
]
```
**Error Responses**:
- 404 Not Found: Label not found
**Implementation**: `app/api/labels/[id]/artists/route.ts`
</details>
---
## Search Endpoint
Full-text search across songs, artists, and albums.
### GET /api/search
**Description**: Search for songs, artists, and albums across the platform using full-text search.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**Query Parameters**:
- `q` (string, required): Search query text
- `type` (string, optional): Filter by type ("song", "artist", "album", or omit for all)
- `limit` (number, optional): Max results per type (default: 10, max: 50)
**Response** (200 OK):
```json
{
"songs": [
{
"id": "uuid",
"title": "Song Title",
"duration": 240,
"audioUrl": "https://example.com/audio.mp3",
"coverUrl": "https://example.com/cover.jpg",
"playCount": 1234,
"artist": {
"id": "uuid",
"name": "Artist Name",
"verified": true
}
}
],
"artists": [
{
"id": "uuid",
"name": "Artist Name",
"slug": "artist-name",
"bio": "Artist biography",
"avatarUrl": "https://example.com/avatar.jpg",
"verified": true,
"_count": {
"songs": 24
}
}
],
"albums": [
{
"id": "uuid",
"title": "Album Title",
"coverUrl": "https://example.com/cover.jpg",
"releaseDate": "2025-01-01T00:00:00.000Z",
"albumType": "ALBUM",
"artist": {
"id": "uuid",
"name": "Artist Name"
},
"_count": {
"songs": 12
}
}
]
}
```
**Error Responses**:
- 400 Bad Request: Missing search query parameter
**Implementation**: `app/api/search/route.ts`
**Note**:
- Search is case-insensitive
- Only returns public songs (isPublic = true)
- Searches in song titles, artist names, album titles, and artist bios
- Results are relevance-sorted by database full-text search
</details>
---
## Sharing Endpoints
API endpoints for creating and tracking shareable links for content.
### POST /api/share/song/{id}
**Description**: Create a shareable link for a song that can be distributed on social media or messaging.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Song UUID
**Response** (200 OK):
```json
{
"token": "unique_share_token",
"url": "https://sonic-cloud.com/s/unique_share_token"
}
```
**Error Responses**:
- 404 Not Found: Song not found
**Implementation**: `app/api/share/song/[id]/route.ts`
**Note**: Share tokens are unique 10-character alphanumeric strings. Multiple share links can be created for the same song.
</details>
---
### POST /api/share/playlist/{id}
**Description**: Create a shareable link for a playlist.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Playlist UUID
**Response** (200 OK):
```json
{
"token": "unique_share_token",
"url": "https://sonic-cloud.com/s/unique_share_token"
}
```
**Error Responses**:
- 404 Not Found: Playlist not found
- 403 Forbidden: Playlist is private
**Implementation**: `app/api/share/playlist/[id]/route.ts`
**Note**: Only public playlists can be shared.
</details>
---
### POST /api/share/album/{id}
**Description**: Create a shareable link for an album.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `id` (string): Album UUID
**Response** (200 OK):
```json
{
"token": "unique_share_token",
"url": "https://sonic-cloud.com/s/unique_share_token"
}
```
**Error Responses**:
- 404 Not Found: Album not found
**Implementation**: `app/api/share/album/[id]/route.ts`
</details>
---
### GET /api/share/{token}
**Description**: Resolve a share token and retrieve the shared content details.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `token` (string): Share token from shareable link
**Response** (200 OK):
```json
{
"type": "SONG", // or "PLAYLIST", "ALBUM"
"targetId": "uuid",
"clickCount": 42,
"content": {
"id": "uuid",
"title": "Song/Playlist/Album Title",
"coverUrl": "https://example.com/cover.jpg",
"artist": {
"id": "uuid",
"name": "Artist Name"
}
// Additional fields based on type
}
}
```
**Error Responses**:
- 404 Not Found: Share token not found or expired
**Implementation**: `app/api/share/[token]/route.ts`
</details>
---
### POST /api/share/{token}/click
**Description**: Track when a share link is clicked. Used for analytics.
**Authentication**: Not required
<details>
<summary>🔧 Technical Details</summary>
**URL Parameters**:
- `token` (string): Share token
**Response** (200 OK):
```json
{
"clickCount": 43
}
```
**Error Responses**:
- 404 Not Found: Share token not found
**Implementation**: `app/api/share/[token]/click/route.ts`
**Note**: This endpoint is automatically called when a user opens a share link. It increments the click counter for analytics.
</details>
---
## Authentication & Authorization
### JWT Token Format
All authenticated endpoints require a JWT token in the Authorization header:
```
Authorization: Bearer <jwt_token>
```
Tokens are issued on successful login or registration and contain:
- User ID
- Email
- Role
- Expiration timestamp
### Token Expiration
JWT tokens expire after 7 days by default. After expiration, users must log in again to receive a new token.
### Permission Levels
| Role | Permissions |
|------|-------------|
| **USER** | Create playlists, like songs, follow artists |
| **ARTIST** | USER permissions + upload songs, create albums, manage artist profile |
| **LABEL** | USER permissions + manage label profile, invite artists |
| **ADMIN** | All permissions + verify artists, moderate content |
---
## Rate Limiting
All API endpoints are subject to rate limiting to prevent abuse:
| Endpoint Type | Rate Limit |
|---------------|------------|
| Authentication | 5 requests per minute per IP |
| Song upload | 10 requests per hour per user |
| Play tracking | 1 request per song per user per minute |
| Search | 30 requests per minute per IP |
| General API | 100 requests per minute per user |
Rate limit headers are included in responses:
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1609459200
```
---
## Error Response Format
All error responses follow a consistent format:
```json
{
"error": {
"message": "Human-readable error message",
"code": "ERROR_CODE",
"details": {
"field": "Additional context"
}
}
}
```
### Common HTTP Status Codes
| Code | Meaning |
|------|---------|
| 200 | Success |
| 201 | Created |
| 204 | No Content (successful deletion) |
| 400 | Bad Request (invalid input) |
| 401 | Unauthorized (missing or invalid token) |
| 403 | Forbidden (insufficient permissions) |
| 404 | Not Found (resource doesn't exist) |
| 409 | Conflict (duplicate resource) |
| 429 | Too Many Requests (rate limit exceeded) |
| 500 | Internal Server Error |
---
## Data Types & Formats
### Date/Time Format
All timestamps use ISO 8601 format:
```
2025-01-01T00:00:00.000Z
```
### UUID Format
All entity IDs use UUID v4:
```
123e4567-e89b-12d3-a456-426614174000
```
### Duration Format
Song durations are in seconds (integer):
```json
{
"duration": 240 // 4 minutes
}
```
### URL Format
All URLs must be valid HTTPS URLs:
```
https://example.com/file.mp3
```
---
## API Versioning
Current API version: **v1**
The API is versioned in the URL path. Future versions will be released as:
```
/api/v2/...
```
Version 1 endpoints will be supported for at least 12 months after v2 release.
---
## SDK & Client Libraries
Official client libraries are in development for:
- JavaScript/TypeScript (Browser & Node.js)
- Python
- Swift (iOS)
- Kotlin (Android)
Community-maintained libraries may be available. Check the [GitHub repository](https://github.com/sonic-cloud) for updates.
---
## Support & Resources
- **API Status**: [status.sonic-cloud.com](https://status.sonic-cloud.com)
- **Documentation**: [docs.sonic-cloud.com](https://docs.sonic-cloud.com)
- **GitHub Issues**: [github.com/sonic-cloud/issues](https://github.com/sonic-cloud/issues)
- **Developer Discord**: [discord.gg/sonic-cloud](https://discord.gg/sonic-cloud)
---
**Last Updated**: December 18, 2025
**API Version**: v1.0.0