204941a1dc
- Created a detailed database schema document outlining tables, relationships, and key fields. - Added OAuth integration documentation covering Spotify and Dropbox authentication processes. - Introduced a FAQ section addressing common user inquiries about the application. - Developed a user-friendly index page for easy navigation of the documentation. - Specified documentation dependencies in requirements.txt for building the documentation site. - Expanded user guide with sections on account management, creating rounds, exporting rounds, getting started, importing songs, and user interface navigation. - Updated mkdocs.yml for improved site structure and navigation.
787 lines
14 KiB
Markdown
787 lines
14 KiB
Markdown
# API Reference
|
|
|
|
This document provides a comprehensive reference for the Quizzical Beats API endpoints.
|
|
|
|
## Authentication
|
|
|
|
All API endpoints require authentication unless specified otherwise.
|
|
|
|
### Authentication Methods
|
|
|
|
The API supports two authentication methods:
|
|
|
|
1. **Session Cookie**: For browser-based applications
|
|
2. **API Key**: For programmatic access
|
|
|
|
#### API Key Authentication
|
|
|
|
To use API key authentication:
|
|
|
|
1. Generate an API key in your profile settings
|
|
2. Include the key in the `X-API-Key` header with each request:
|
|
```
|
|
X-API-Key: your-api-key-here
|
|
```
|
|
|
|
### Rate Limiting
|
|
|
|
API requests are rate-limited to prevent abuse:
|
|
|
|
- 100 requests per hour for standard users
|
|
- 300 requests per hour for admin users
|
|
|
|
Rate limit headers are included in all responses:
|
|
```
|
|
X-RateLimit-Limit: 100
|
|
X-RateLimit-Remaining: 95
|
|
X-RateLimit-Reset: 1620567890
|
|
```
|
|
|
|
## Response Format
|
|
|
|
All API responses are in JSON format with a consistent structure:
|
|
|
|
```json
|
|
{
|
|
"status": "success|error",
|
|
"data": { ... },
|
|
"message": "Optional message",
|
|
"pagination": {
|
|
"page": 1,
|
|
"per_page": 20,
|
|
"total": 42,
|
|
"pages": 3
|
|
}
|
|
}
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
When an error occurs, the response will have status code 4xx or 5xx and include an error message:
|
|
|
|
```json
|
|
{
|
|
"status": "error",
|
|
"message": "Descriptive error message",
|
|
"code": "ERROR_CODE"
|
|
}
|
|
```
|
|
|
|
Common error codes:
|
|
- `UNAUTHORIZED`: Authentication failed
|
|
- `FORBIDDEN`: Permission denied
|
|
- `NOT_FOUND`: Resource not found
|
|
- `VALIDATION_ERROR`: Invalid input data
|
|
- `RATE_LIMITED`: Rate limit exceeded
|
|
|
|
## API Endpoints
|
|
|
|
### User Endpoints
|
|
|
|
#### Get Current User
|
|
|
|
```
|
|
GET /api/user
|
|
```
|
|
|
|
Returns information about the currently authenticated user.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": {
|
|
"id": 123,
|
|
"username": "john_doe",
|
|
"email": "john@example.com",
|
|
"is_admin": false,
|
|
"created_at": "2025-01-15T12:34:56Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Update User Profile
|
|
|
|
```
|
|
PUT /api/user
|
|
```
|
|
|
|
Update the current user's profile information.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"username": "new_username",
|
|
"email": "new_email@example.com"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": {
|
|
"id": 123,
|
|
"username": "new_username",
|
|
"email": "new_email@example.com",
|
|
"is_admin": false,
|
|
"created_at": "2025-01-15T12:34:56Z"
|
|
},
|
|
"message": "Profile updated successfully"
|
|
}
|
|
```
|
|
|
|
### Song Endpoints
|
|
|
|
#### List Songs
|
|
|
|
```
|
|
GET /api/songs
|
|
```
|
|
|
|
Returns a paginated list of songs in the user's library.
|
|
|
|
**Query Parameters:**
|
|
- `page`: Page number (default: 1)
|
|
- `per_page`: Items per page (default: 20, max: 100)
|
|
- `search`: Search term
|
|
- `sort`: Sort field (title, artist, album, year)
|
|
- `order`: Sort order (asc, desc)
|
|
- `genre`: Filter by genre
|
|
- `year`: Filter by year
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": [
|
|
{
|
|
"id": 456,
|
|
"title": "Song Title",
|
|
"artist": "Artist Name",
|
|
"album": "Album Name",
|
|
"year": 2010,
|
|
"genre": "Rock",
|
|
"preview_url": "https://example.com/preview.mp3",
|
|
"spotify_id": "spotify:track:abcdef123456",
|
|
"duration_ms": 240000
|
|
},
|
|
// More songs...
|
|
],
|
|
"pagination": {
|
|
"page": 1,
|
|
"per_page": 20,
|
|
"total": 42,
|
|
"pages": 3
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Song
|
|
|
|
```
|
|
GET /api/songs/{id}
|
|
```
|
|
|
|
Returns detailed information about a specific song.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": {
|
|
"id": 456,
|
|
"title": "Song Title",
|
|
"artist": "Artist Name",
|
|
"album": "Album Name",
|
|
"year": 2010,
|
|
"genre": "Rock",
|
|
"preview_url": "https://example.com/preview.mp3",
|
|
"spotify_id": "spotify:track:abcdef123456",
|
|
"duration_ms": 240000,
|
|
"added_by": 123,
|
|
"created_at": "2025-02-10T15:30:45Z",
|
|
"popularity": 75,
|
|
"tags": [
|
|
{
|
|
"id": 789,
|
|
"name": "Summer Hits",
|
|
"color": "#ff5500"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Create Song
|
|
|
|
```
|
|
POST /api/songs
|
|
```
|
|
|
|
Add a new song to the user's library.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"title": "New Song",
|
|
"artist": "New Artist",
|
|
"album": "New Album",
|
|
"year": 2025,
|
|
"genre": "Pop",
|
|
"spotify_id": "spotify:track:xyz789",
|
|
"preview_url": "https://example.com/preview.mp3"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": {
|
|
"id": 457,
|
|
"title": "New Song",
|
|
"artist": "New Artist",
|
|
"album": "New Album",
|
|
"year": 2025,
|
|
"genre": "Pop",
|
|
"preview_url": "https://example.com/preview.mp3",
|
|
"spotify_id": "spotify:track:xyz789",
|
|
"added_by": 123,
|
|
"created_at": "2025-05-11T09:12:34Z"
|
|
},
|
|
"message": "Song added successfully"
|
|
}
|
|
```
|
|
|
|
#### Update Song
|
|
|
|
```
|
|
PUT /api/songs/{id}
|
|
```
|
|
|
|
Update an existing song.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"title": "Updated Title",
|
|
"artist": "Updated Artist",
|
|
"album": "Updated Album",
|
|
"year": 2020,
|
|
"genre": "Electronic"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": {
|
|
"id": 456,
|
|
"title": "Updated Title",
|
|
"artist": "Updated Artist",
|
|
"album": "Updated Album",
|
|
"year": 2020,
|
|
"genre": "Electronic",
|
|
"preview_url": "https://example.com/preview.mp3",
|
|
"spotify_id": "spotify:track:abcdef123456"
|
|
},
|
|
"message": "Song updated successfully"
|
|
}
|
|
```
|
|
|
|
#### Delete Song
|
|
|
|
```
|
|
DELETE /api/songs/{id}
|
|
```
|
|
|
|
Remove a song from the user's library.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"message": "Song deleted successfully"
|
|
}
|
|
```
|
|
|
|
### Round Endpoints
|
|
|
|
#### List Rounds
|
|
|
|
```
|
|
GET /api/rounds
|
|
```
|
|
|
|
Returns a paginated list of the user's quiz rounds.
|
|
|
|
**Query Parameters:**
|
|
- `page`: Page number (default: 1)
|
|
- `per_page`: Items per page (default: 20, max: 100)
|
|
- `search`: Search term
|
|
- `sort`: Sort field (name, created_at)
|
|
- `order`: Sort order (asc, desc)
|
|
- `tag`: Filter by tag ID
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": [
|
|
{
|
|
"id": 789,
|
|
"name": "80s Rock Classics",
|
|
"description": "Classic rock hits from the 1980s",
|
|
"created_at": "2025-03-20T14:25:36Z",
|
|
"song_count": 10,
|
|
"round_type": "decade",
|
|
"tags": [
|
|
{
|
|
"id": 123,
|
|
"name": "80s",
|
|
"color": "#3366ff"
|
|
},
|
|
{
|
|
"id": 456,
|
|
"name": "Rock",
|
|
"color": "#cc0000"
|
|
}
|
|
]
|
|
},
|
|
// More rounds...
|
|
],
|
|
"pagination": {
|
|
"page": 1,
|
|
"per_page": 20,
|
|
"total": 15,
|
|
"pages": 1
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Round
|
|
|
|
```
|
|
GET /api/rounds/{id}
|
|
```
|
|
|
|
Returns detailed information about a specific round, including its songs.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": {
|
|
"id": 789,
|
|
"name": "80s Rock Classics",
|
|
"description": "Classic rock hits from the 1980s",
|
|
"created_at": "2025-03-20T14:25:36Z",
|
|
"user_id": 123,
|
|
"is_public": true,
|
|
"round_type": "decade",
|
|
"intro_file": "/mp3/intros/80s_intro.mp3",
|
|
"outro_file": "/mp3/outros/rock_outro.mp3",
|
|
"songs": [
|
|
{
|
|
"id": 101,
|
|
"title": "Sweet Child O' Mine",
|
|
"artist": "Guns N' Roses",
|
|
"year": 1987,
|
|
"position": 1,
|
|
"question": "Name this iconic 80s rock song",
|
|
"answer": "Sweet Child O' Mine by Guns N' Roses",
|
|
"points": 10,
|
|
"preview_url": "https://example.com/preview1.mp3"
|
|
},
|
|
// More songs...
|
|
],
|
|
"tags": [
|
|
{
|
|
"id": 123,
|
|
"name": "80s",
|
|
"color": "#3366ff"
|
|
},
|
|
{
|
|
"id": 456,
|
|
"name": "Rock",
|
|
"color": "#cc0000"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Create Round
|
|
|
|
```
|
|
POST /api/rounds
|
|
```
|
|
|
|
Create a new quiz round.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"name": "New Quiz Round",
|
|
"description": "A fresh music quiz round",
|
|
"round_type": "mixed",
|
|
"is_public": true,
|
|
"song_ids": [101, 102, 103, 104],
|
|
"tag_ids": [123, 456]
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": {
|
|
"id": 790,
|
|
"name": "New Quiz Round",
|
|
"description": "A fresh music quiz round",
|
|
"created_at": "2025-05-11T10:15:20Z",
|
|
"user_id": 123,
|
|
"is_public": true,
|
|
"round_type": "mixed",
|
|
"song_count": 4
|
|
},
|
|
"message": "Round created successfully"
|
|
}
|
|
```
|
|
|
|
#### Update Round
|
|
|
|
```
|
|
PUT /api/rounds/{id}
|
|
```
|
|
|
|
Update an existing round.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"name": "Updated Round Name",
|
|
"description": "Updated description",
|
|
"is_public": false,
|
|
"song_ids": [101, 102, 105, 106],
|
|
"tag_ids": [123, 789]
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": {
|
|
"id": 789,
|
|
"name": "Updated Round Name",
|
|
"description": "Updated description",
|
|
"is_public": false,
|
|
"song_count": 4
|
|
},
|
|
"message": "Round updated successfully"
|
|
}
|
|
```
|
|
|
|
#### Delete Round
|
|
|
|
```
|
|
DELETE /api/rounds/{id}
|
|
```
|
|
|
|
Delete a quiz round.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"message": "Round deleted successfully"
|
|
}
|
|
```
|
|
|
|
### Export Endpoints
|
|
|
|
#### Export Round to Dropbox
|
|
|
|
```
|
|
POST /rounds/{round_id}/export-to-dropbox
|
|
```
|
|
|
|
Export a round to the user's connected Dropbox account.
|
|
|
|
**Request Body Parameters:**
|
|
```
|
|
include_mp3s: boolean (default: true) - Whether to include MP3 files in the export
|
|
include_pdf: boolean (default: true) - Whether to include PDF in the export
|
|
custom_folder: string (optional) - Additional subfolder path within the user's configured export path
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Round exported to Dropbox successfully",
|
|
"shared_links": {
|
|
"text": "https://www.dropbox.com/s/abc123/round_123_metadata.json?dl=0",
|
|
"pdf": "https://www.dropbox.com/s/def456/round_123.pdf?dl=0",
|
|
"mp3": "https://www.dropbox.com/s/ghi789/round_123.mp3?dl=0"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Response:**
|
|
```json
|
|
{
|
|
"success": false,
|
|
"message": "Error exporting to Dropbox: <error details>",
|
|
"redirect": "URL for MP3 generation if needed"
|
|
}
|
|
```
|
|
|
|
#### List Dropbox Folders
|
|
|
|
```
|
|
GET /api/dropbox/folders
|
|
```
|
|
|
|
List folders from the user's Dropbox account.
|
|
|
|
**Query Parameters:**
|
|
```
|
|
path: string - The path to list folders from (default: root)
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"folders": [
|
|
{
|
|
"name": "Folder Name",
|
|
"path": "/Folder Name",
|
|
"is_dir": true
|
|
},
|
|
{
|
|
"name": "Documents",
|
|
"path": "/Documents",
|
|
"is_dir": true
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Create Dropbox Folder
|
|
|
|
```
|
|
POST /api/dropbox/create-folder
|
|
```
|
|
|
|
Create a new folder in the user's Dropbox account.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"parent_path": "/path/to/parent",
|
|
"folder_name": "New Folder"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Folder created successfully",
|
|
"folder": {
|
|
"name": "New Folder",
|
|
"path": "/path/to/parent/New Folder",
|
|
"is_dir": true
|
|
}
|
|
}
|
|
```
|
|
|
|
### Dropbox OAuth Endpoints
|
|
|
|
#### Connect Dropbox Account
|
|
|
|
```
|
|
GET /users/dropbox/connect
|
|
```
|
|
|
|
Initiates the OAuth flow for connecting a Dropbox account.
|
|
|
|
**Response:**
|
|
Redirects to Dropbox OAuth authorization page
|
|
|
|
#### Dropbox OAuth Callback
|
|
|
|
```
|
|
GET /users/dropbox/callback
|
|
```
|
|
|
|
Handles the OAuth callback from Dropbox.
|
|
|
|
**Query Parameters:**
|
|
```
|
|
code: string - The authorization code from Dropbox
|
|
error: string - Error message if authorization failed
|
|
```
|
|
|
|
**Response:**
|
|
Redirects back to user profile page with a success or error message
|
|
|
|
#### Disconnect Dropbox Account
|
|
|
|
```
|
|
POST /users/dropbox/disconnect
|
|
```
|
|
|
|
Disconnects the user's Dropbox account.
|
|
|
|
**Response:**
|
|
Redirects back to user profile page with a success message
|
|
|
|
### Spotify Integration Endpoints
|
|
|
|
#### Get User Playlists
|
|
|
|
```
|
|
GET /api/spotify/playlists
|
|
```
|
|
|
|
Get the current user's Spotify playlists.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": [
|
|
{
|
|
"id": "spotify:playlist:abcdef123456",
|
|
"name": "My Awesome Playlist",
|
|
"owner": "spotify_user123",
|
|
"track_count": 42,
|
|
"image_url": "https://example.com/playlist_cover.jpg"
|
|
},
|
|
// More playlists...
|
|
],
|
|
"pagination": {
|
|
"page": 1,
|
|
"per_page": 20,
|
|
"total": 35,
|
|
"pages": 2
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Import Playlist
|
|
|
|
```
|
|
POST /api/spotify/import/playlist
|
|
```
|
|
|
|
Import songs from a Spotify playlist.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"playlist_id": "spotify:playlist:abcdef123456",
|
|
"limit": 20
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": {
|
|
"import_id": "imp_789012",
|
|
"playlist_name": "My Awesome Playlist",
|
|
"status": "processing",
|
|
"songs_found": 42,
|
|
"songs_to_import": 20,
|
|
"estimated_completion": "45 seconds"
|
|
},
|
|
"message": "Import started"
|
|
}
|
|
```
|
|
|
|
### Health Check Endpoint
|
|
|
|
```
|
|
GET /api/health
|
|
```
|
|
|
|
Get system health information (admin only).
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"data": {
|
|
"version": "1.0.0",
|
|
"uptime": "5d 12h 37m",
|
|
"database": {
|
|
"status": "connected",
|
|
"size": "42MB",
|
|
"migrations": "up-to-date"
|
|
},
|
|
"storage": {
|
|
"available": "1.2GB",
|
|
"used": "345MB"
|
|
},
|
|
"services": {
|
|
"spotify": "connected",
|
|
"dropbox": "connected",
|
|
"email": "connected"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Webhook Notifications
|
|
|
|
Quizzical Beats can send webhook notifications for certain events.
|
|
|
|
### Configuring Webhooks
|
|
|
|
Webhooks are configured in the admin settings:
|
|
|
|
1. Go to Admin > System > Webhooks
|
|
2. Add a new webhook URL
|
|
3. Select which events to receive notifications for
|
|
|
|
### Webhook Events
|
|
|
|
- `round.created`: A new round was created
|
|
- `round.exported`: A round was exported
|
|
- `import.completed`: A Spotify import was completed
|
|
- `backup.completed`: A system backup was completed
|
|
|
|
### Webhook Payload
|
|
|
|
```json
|
|
{
|
|
"event": "round.exported",
|
|
"timestamp": "2025-05-11T10:30:45Z",
|
|
"data": {
|
|
"round_id": 789,
|
|
"round_name": "80s Rock Classics",
|
|
"user_id": 123,
|
|
"username": "john_doe",
|
|
"export_format": "zip",
|
|
"destination": "dropbox"
|
|
}
|
|
}
|
|
```
|
|
|
|
## API Versioning
|
|
|
|
The current API version is v1. The version is specified in the URL path:
|
|
|
|
```
|
|
/api/v1/resource
|
|
```
|
|
|
|
For backward compatibility, requests to `/api/resource` will be directed to the latest stable API version. |