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:
- Session Cookie: For browser-based applications
- API Key: For programmatic access
API Key Authentication¶
To use API key authentication:
- Generate an API key in your profile settings
- Include the key in the
X-API-Keyheader 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:
{
"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:
{
"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:
{
"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:
{
"username": "new_username",
"email": "new_email@example.com"
}
Response:
{
"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:
{
"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:
{
"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:
{
"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:
{
"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:
{
"title": "Updated Title",
"artist": "Updated Artist",
"album": "Updated Album",
"year": 2020,
"genre": "Electronic"
}
Response:
{
"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:
{
"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:
{
"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:
{
"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:
{
"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:
{
"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:
{
"name": "Updated Round Name",
"description": "Updated description",
"is_public": false,
"song_ids": [101, 102, 105, 106],
"tag_ids": [123, 789]
}
Response:
{
"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:
{
"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:
{
"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:
{
"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:
{
"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:
{
"parent_path": "/path/to/parent",
"folder_name": "New Folder"
}
Response:
{
"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:
{
"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:
{
"playlist_id": "spotify:playlist:abcdef123456",
"limit": 20
}
Response:
{
"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:
{
"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:
- Go to Admin > System > Webhooks
- Add a new webhook URL
- Select which events to receive notifications for
Webhook Events¶
round.created: A new round was createdround.exported: A round was exportedimport.completed: A Spotify import was completedbackup.completed: A system backup was completed
Webhook Payload¶
{
"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.