Bloc A - Code mort: - Suppression Studio (components, views, features) - Suppression gamification + services mock (projectService, storageService, gamificationService) - Mise à jour Sidebar, Navbar, locales Bloc B - Frontend: - Suppression modal.tsx deprecated, Modal.stories (doublon Dialog) - Feature flags: PLAYLIST_SEARCH, PLAYLIST_RECOMMENDATIONS, ROLE_MANAGEMENT = true - Suppression 19 tests orphelins, retrait exclusions vitest.config Bloc C - Backend: - Extraction routes_auth.go depuis router.go Bloc D - Rust: - Suppression security_legacy.rs (code mort, patterns déjà dans security/)
2256 lines
40 KiB
Markdown
2256 lines
40 KiB
Markdown
# Veza Backend API Documentation
|
|
|
|
## Table of Contents
|
|
|
|
1. [Overview](#overview)
|
|
2. [Base URL](#base-url)
|
|
3. [Authentication](#authentication)
|
|
4. [Error Handling](#error-handling)
|
|
5. [Rate Limiting](#rate-limiting)
|
|
6. [Pagination](#pagination)
|
|
7. [Endpoints](#endpoints)
|
|
- [Authentication](#authentication-endpoints)
|
|
- [Users](#user-endpoints)
|
|
- [Tracks](#track-endpoints)
|
|
- [Playlists](#playlist-endpoints)
|
|
- [Marketplace](#marketplace-endpoints)
|
|
- [Analytics](#analytics-endpoints)
|
|
- [Webhooks](#webhook-endpoints)
|
|
- [Chat](#chat-endpoints)
|
|
- [Search](#search-endpoints)
|
|
- [Comments](#comment-endpoints)
|
|
- [Roles](#role-endpoints)
|
|
- [Notifications](#notification-endpoints)
|
|
- [Sessions](#session-endpoints)
|
|
- [Uploads](#upload-endpoints)
|
|
- [Audit](#audit-endpoints)
|
|
- [Admin](#admin-endpoints)
|
|
|
|
## Overview
|
|
|
|
The Veza Backend API is a RESTful API that provides endpoints for managing audio tracks, playlists, users, marketplace, analytics, and more. The API uses JSON for request and response payloads and follows REST conventions.
|
|
|
|
**API Version:** v1
|
|
**Base Path:** `/api/v1`
|
|
**Content-Type:** `application/json`
|
|
|
|
## Base URL
|
|
|
|
- **Production:** `https://api.veza.app`
|
|
- **Staging:** `https://staging-api.veza.app`
|
|
- **Development:** `http://localhost:8080`
|
|
|
|
## Authentication
|
|
|
|
Most endpoints require authentication using JWT (JSON Web Tokens). Include the access token in the `Authorization` header:
|
|
|
|
```
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
### Getting an Access Token
|
|
|
|
1. Register a new user or login
|
|
2. Receive `access_token` in the response body
|
|
3. Receive `refresh_token` in an httpOnly cookie (automatically sent by browser)
|
|
4. Use `access_token` for authenticated requests
|
|
5. Use the refresh token cookie to get a new `access_token` when it expires
|
|
|
|
### Token Expiration
|
|
|
|
- **Access Token:** Valid for 24 hours
|
|
- **Refresh Token:** Valid for 30 days (or 90 days if "remember me" is selected)
|
|
|
|
### Authentication Cookies
|
|
|
|
#### Refresh Token Cookie
|
|
|
|
After successful login or token refresh, a `refresh_token` cookie is set with the following properties:
|
|
|
|
- **Name:** `refresh_token`
|
|
- **HttpOnly:** `true` (not accessible via JavaScript - prevents XSS attacks)
|
|
- **Secure:** `true` in production, `false` in development (HTTPS only in production)
|
|
- **SameSite:** `strict` in production, `lax` in development (prevents CSRF attacks)
|
|
- **Path:** `/`
|
|
- **Max-Age:** 30 days (or 90 days if "remember me" is selected)
|
|
|
|
**Important:** The refresh token is NOT returned in the JSON response body for security reasons. It is only available as an httpOnly cookie that is automatically sent by the browser with each request.
|
|
|
|
#### Using Refresh Token
|
|
|
|
To refresh your access token, make a POST request to `/auth/refresh`:
|
|
|
|
```bash
|
|
# The refresh token cookie is automatically sent by the browser
|
|
curl -X POST http://localhost:8080/api/v1/auth/refresh \
|
|
-H "Content-Type: application/json" \
|
|
--cookie "refresh_token=<token>" \
|
|
-b cookies.txt -c cookies.txt
|
|
```
|
|
|
|
The new access token will be returned in the response body, and a new refresh token cookie will be set automatically.
|
|
|
|
#### Cookie Configuration
|
|
|
|
The cookie security settings can be configured via environment variables:
|
|
|
|
- `COOKIE_SECURE`: `true` in production (HTTPS only), `false` in development
|
|
- `COOKIE_SAME_SITE`: `strict` (production), `lax` (development)
|
|
- `COOKIE_DOMAIN`: Domain for the cookie (empty for current domain)
|
|
- `COOKIE_HTTP_ONLY`: Always `true` for refresh tokens
|
|
- `COOKIE_PATH`: Cookie path (default: `/`)
|
|
|
|
**Note:** In development, cookies work with `http://localhost` when `COOKIE_SECURE=false` and `COOKIE_SAME_SITE=lax`.
|
|
|
|
## Error Handling
|
|
|
|
All errors follow a consistent format:
|
|
|
|
```json
|
|
{
|
|
"success": false,
|
|
"error": {
|
|
"code": "ERROR_CODE",
|
|
"message": "Human-readable error message",
|
|
"details": []
|
|
}
|
|
}
|
|
```
|
|
|
|
### HTTP Status Codes
|
|
|
|
- `200 OK` - Request successful
|
|
- `201 Created` - Resource created successfully
|
|
- `400 Bad Request` - Invalid request parameters
|
|
- `401 Unauthorized` - Missing or invalid authentication
|
|
- `403 Forbidden` - Insufficient permissions
|
|
- `404 Not Found` - Resource not found
|
|
- `409 Conflict` - Resource conflict (e.g., duplicate)
|
|
- `422 Unprocessable Entity` - Validation error
|
|
- `429 Too Many Requests` - Rate limit exceeded
|
|
- `500 Internal Server Error` - Server error
|
|
|
|
## Rate Limiting
|
|
|
|
Rate limiting is applied to prevent abuse. Limits vary by endpoint:
|
|
|
|
- **Global:** 100 requests per minute per IP
|
|
- **Login/Register:** 5 requests per minute per IP
|
|
- **Email Verification:** 3 requests per hour per email
|
|
- **Upload:** 10 uploads per hour per user
|
|
|
|
Rate limit headers are included in responses:
|
|
|
|
```
|
|
X-RateLimit-Limit: 100
|
|
X-RateLimit-Remaining: 95
|
|
X-RateLimit-Reset: 1640995200
|
|
```
|
|
|
|
## Pagination
|
|
|
|
List endpoints support pagination using query parameters:
|
|
|
|
- `page` - Page number (default: 1)
|
|
- `limit` - Items per page (default: 20, max: 100)
|
|
|
|
Response includes pagination metadata:
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"items": [...],
|
|
"pagination": {
|
|
"page": 1,
|
|
"limit": 20,
|
|
"total": 150,
|
|
"total_pages": 8
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Endpoints
|
|
|
|
### Authentication Endpoints
|
|
|
|
#### Register User
|
|
|
|
Create a new user account.
|
|
|
|
**Endpoint:** `POST /api/v1/auth/register`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"username": "johndoe",
|
|
"email": "john@example.com",
|
|
"password": "SecurePassword123!",
|
|
"password_confirm": "SecurePassword123!"
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"user": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"username": "johndoe",
|
|
"email": "john@example.com"
|
|
},
|
|
"token": {
|
|
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"expires_in": 86400
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Login
|
|
|
|
Authenticate and receive tokens.
|
|
|
|
**Endpoint:** `POST /api/v1/auth/login`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "john@example.com",
|
|
"password": "SecurePassword123!",
|
|
"remember_me": false
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"user": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"username": "johndoe",
|
|
"email": "john@example.com"
|
|
},
|
|
"token": {
|
|
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"expires_in": 86400
|
|
},
|
|
"requires_2fa": false
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Refresh Token
|
|
|
|
Get a new access token using refresh token.
|
|
|
|
**Endpoint:** `POST /api/v1/auth/refresh`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"expires_in": 86400
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Logout
|
|
|
|
Revoke refresh token and current session.
|
|
|
|
**Endpoint:** `POST /api/v1/auth/logout`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Logged out successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Current User
|
|
|
|
Get profile information of the currently logged-in user.
|
|
|
|
**Endpoint:** `GET /api/v1/auth/me`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"username": "johndoe",
|
|
"email": "john@example.com",
|
|
"role": "user"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Check Username Availability
|
|
|
|
Check if a username is available.
|
|
|
|
**Endpoint:** `GET /api/v1/auth/check-username?username=johndoe`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"username": "johndoe",
|
|
"available": true
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Verify Email
|
|
|
|
Verify user email address using a token.
|
|
|
|
**Endpoint:** `POST /api/v1/auth/verify-email?token=verification_token_here`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Email verified successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Resend Verification Email
|
|
|
|
Resend the email verification link.
|
|
|
|
**Endpoint:** `POST /api/v1/auth/resend-verification`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "john@example.com"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Verification email sent"
|
|
}
|
|
}
|
|
```
|
|
|
|
### User Endpoints
|
|
|
|
#### Get User Profile
|
|
|
|
Get public profile information for a user.
|
|
|
|
**Endpoint:** `GET /api/v1/users/{id}`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"profile": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"username": "johndoe",
|
|
"email": "john@example.com",
|
|
"bio": "Music producer",
|
|
"avatar": "https://cdn.veza.app/avatars/user123.jpg",
|
|
"location": "Paris, France",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get User Profile by Username
|
|
|
|
Get public profile information by username.
|
|
|
|
**Endpoint:** `GET /api/v1/users/by-username/{username}`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"profile": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"username": "johndoe",
|
|
"bio": "Music producer",
|
|
"avatar": "https://cdn.veza.app/avatars/user123.jpg"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Update Profile
|
|
|
|
Update user profile details.
|
|
|
|
**Endpoint:** `PUT /api/v1/users/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"username": "johndoe",
|
|
"bio": "Updated bio",
|
|
"first_name": "John",
|
|
"last_name": "Doe",
|
|
"location": "New York, USA",
|
|
"gender": "Male"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"profile": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"username": "johndoe",
|
|
"bio": "Updated bio",
|
|
"first_name": "John",
|
|
"last_name": "Doe"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Profile Completion
|
|
|
|
Get profile completion percentage and missing fields.
|
|
|
|
**Endpoint:** `GET /api/v1/users/{id}/completion`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"completion_percentage": 75,
|
|
"missing_fields": ["bio", "avatar"]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Track Endpoints
|
|
|
|
#### List Tracks
|
|
|
|
Get a paginated list of tracks with filters.
|
|
|
|
**Endpoint:** `GET /api/v1/tracks`
|
|
|
|
**Query Parameters:**
|
|
- `page` (optional) - Page number (default: 1)
|
|
- `limit` (optional) - Items per page (default: 20, max: 100)
|
|
- `user_id` (optional) - Filter by user ID
|
|
- `genre` (optional) - Filter by genre
|
|
- `format` (optional) - Filter by format (mp3, flac, wav)
|
|
- `sort_by` (optional) - Sort field (default: created_at)
|
|
- `sort_order` (optional) - Sort order: asc/desc (default: desc)
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"tracks": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "My Track",
|
|
"artist": "John Doe",
|
|
"duration": 180,
|
|
"format": "mp3",
|
|
"genre": "Electronic",
|
|
"is_public": true,
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
],
|
|
"pagination": {
|
|
"page": 1,
|
|
"limit": 20,
|
|
"total": 150,
|
|
"total_pages": 8
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Search Tracks
|
|
|
|
Search tracks with advanced filters.
|
|
|
|
**Endpoint:** `GET /api/v1/tracks/search`
|
|
|
|
**Query Parameters:**
|
|
- `q` (optional) - Search query
|
|
- `genre` (optional) - Filter by genre
|
|
- `format` (optional) - Filter by format
|
|
- `min_duration` (optional) - Minimum duration in seconds
|
|
- `max_duration` (optional) - Maximum duration in seconds
|
|
- `start_date` (optional) - Start date (RFC3339)
|
|
- `end_date` (optional) - End date (RFC3339)
|
|
- `sort_by` (optional) - Sort field (title, popularity, created_at)
|
|
- `sort_order` (optional) - Sort order (asc/desc)
|
|
- `page` (optional) - Page number
|
|
- `limit` (optional) - Items per page
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"tracks": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "My Track",
|
|
"artist": "John Doe",
|
|
"duration": 180
|
|
}
|
|
],
|
|
"pagination": {
|
|
"page": 1,
|
|
"limit": 20,
|
|
"total": 50,
|
|
"total_pages": 3
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Track
|
|
|
|
Get detailed information about a track.
|
|
|
|
**Endpoint:** `GET /api/v1/tracks/{id}`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"track": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "My Track",
|
|
"artist": "John Doe",
|
|
"album": "My Album",
|
|
"duration": 180,
|
|
"format": "mp3",
|
|
"file_size": 5242880,
|
|
"genre": "Electronic",
|
|
"year": 2025,
|
|
"is_public": true,
|
|
"like_count": 42,
|
|
"play_count": 150,
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Upload Track
|
|
|
|
Upload a new track (audio file).
|
|
|
|
**Endpoint:** `POST /api/v1/tracks`
|
|
|
|
**Headers:**
|
|
- `Authorization: Bearer <token>`
|
|
- `Content-Type: multipart/form-data`
|
|
|
|
**Form Data:**
|
|
- `file` (required) - Audio file (MP3, WAV, FLAC, OGG)
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"track": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "My Track",
|
|
"status": "processing",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Update Track
|
|
|
|
Update track metadata.
|
|
|
|
**Endpoint:** `PUT /api/v1/tracks/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"title": "Updated Title",
|
|
"artist": "Updated Artist",
|
|
"album": "Updated Album",
|
|
"genre": "Rock",
|
|
"year": 2025,
|
|
"is_public": true
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"track": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "Updated Title",
|
|
"artist": "Updated Artist"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Delete Track
|
|
|
|
Permanently delete a track.
|
|
|
|
**Endpoint:** `DELETE /api/v1/tracks/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Track deleted successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Track Stats
|
|
|
|
Get statistics for a track.
|
|
|
|
**Endpoint:** `GET /api/v1/tracks/{id}/stats`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"stats": {
|
|
"total_plays": 150,
|
|
"unique_listeners": 45,
|
|
"average_duration": 165.5,
|
|
"completion_rate": 78.5
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Download Track
|
|
|
|
Download a track file.
|
|
|
|
**Endpoint:** `GET /api/v1/tracks/{id}/download`
|
|
|
|
**Response (200 OK):**
|
|
- Binary file download with appropriate `Content-Type` header
|
|
|
|
#### Like Track
|
|
|
|
Like a track.
|
|
|
|
**Endpoint:** `POST /api/v1/tracks/{id}/like`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Track liked"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Unlike Track
|
|
|
|
Remove like from a track.
|
|
|
|
**Endpoint:** `DELETE /api/v1/tracks/{id}/like`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Track unliked"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Track Likes
|
|
|
|
Get list of users who liked a track.
|
|
|
|
**Endpoint:** `GET /api/v1/tracks/{id}/likes`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"likes": [
|
|
{
|
|
"user_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"username": "johndoe",
|
|
"liked_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
],
|
|
"total": 42
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Initiate Chunked Upload
|
|
|
|
Start a new chunked upload session.
|
|
|
|
**Endpoint:** `POST /api/v1/tracks/initiate`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"filename": "my-track.mp3",
|
|
"total_chunks": 10,
|
|
"total_size": 52428800
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"upload_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"message": "Upload session initiated"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Upload Chunk
|
|
|
|
Upload a single chunk of a file.
|
|
|
|
**Endpoint:** `POST /api/v1/tracks/chunk`
|
|
|
|
**Headers:**
|
|
- `Authorization: Bearer <token>`
|
|
- `Content-Type: multipart/form-data`
|
|
|
|
**Form Data:**
|
|
- `chunk` (required) - Chunk file data
|
|
- `upload_id` (required) - Upload session ID
|
|
- `chunk_number` (required) - Chunk number (1-based)
|
|
- `total_chunks` (required) - Total number of chunks
|
|
- `total_size` (required) - Total file size in bytes
|
|
- `filename` (required) - Original filename
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"upload_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"received_chunks": 5,
|
|
"progress": 50.0,
|
|
"message": "Chunk uploaded successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Complete Chunked Upload
|
|
|
|
Finish upload session and assemble file.
|
|
|
|
**Endpoint:** `POST /api/v1/tracks/complete`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"upload_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"track": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "my-track",
|
|
"status": "processing"
|
|
},
|
|
"md5": "d41d8cd98f00b204e9800998ecf8427e",
|
|
"message": "Upload completed"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Upload Status
|
|
|
|
Get the processing status of an uploaded track.
|
|
|
|
**Endpoint:** `GET /api/v1/tracks/{id}/status`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"status": "processing",
|
|
"progress": 75
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Upload Quota
|
|
|
|
Get remaining upload quota for the user.
|
|
|
|
**Endpoint:** `GET /api/v1/tracks/quota/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"quota": {
|
|
"used": 524288000,
|
|
"limit": 1073741824,
|
|
"remaining": 549453824,
|
|
"percentage_used": 48.8
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Resume Upload
|
|
|
|
Get state of an interrupted upload.
|
|
|
|
**Endpoint:** `GET /api/v1/tracks/resume/{uploadId}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"upload_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"chunks_received": 7,
|
|
"total_chunks": 10
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Batch Delete Tracks
|
|
|
|
Delete multiple tracks at once.
|
|
|
|
**Endpoint:** `POST /api/v1/tracks/batch/delete`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"track_ids": [
|
|
"550e8400-e29b-41d4-a716-446655440000",
|
|
"660e8400-e29b-41d4-a716-446655440001"
|
|
]
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"deleted": [
|
|
"550e8400-e29b-41d4-a716-446655440000",
|
|
"660e8400-e29b-41d4-a716-446655440001"
|
|
],
|
|
"failed": {}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Record Play
|
|
|
|
Record a track play event.
|
|
|
|
**Endpoint:** `POST /api/v1/tracks/{id}/play`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"duration": 120,
|
|
"device": "Chrome Browser"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Play event recorded",
|
|
"id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Playlist Endpoints
|
|
|
|
#### List Playlists
|
|
|
|
Get a paginated list of playlists.
|
|
|
|
**Endpoint:** `GET /api/v1/playlists`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Query Parameters:**
|
|
- `page` (optional) - Page number (default: 1)
|
|
- `limit` (optional) - Items per page (default: 20)
|
|
- `user_id` (optional) - Filter by user ID
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"playlists": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "My Playlist",
|
|
"description": "A great playlist",
|
|
"is_public": true,
|
|
"track_count": 10,
|
|
"follower_count": 5,
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
],
|
|
"pagination": {
|
|
"page": 1,
|
|
"limit": 20,
|
|
"total": 50,
|
|
"total_pages": 3
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Search Playlists
|
|
|
|
Search playlists with filters.
|
|
|
|
**Endpoint:** `GET /api/v1/playlists/search`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Query Parameters:**
|
|
- `q` (optional) - Search query
|
|
- `user_id` (optional) - Filter by user ID
|
|
- `is_public` (optional) - Filter by public status (true/false)
|
|
- `page` (optional) - Page number
|
|
- `limit` (optional) - Items per page
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"playlists": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "My Playlist",
|
|
"is_public": true
|
|
}
|
|
],
|
|
"total": 25,
|
|
"page": 1,
|
|
"limit": 20
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Playlist
|
|
|
|
Get detailed information about a playlist.
|
|
|
|
**Endpoint:** `GET /api/v1/playlists/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"playlist": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "My Playlist",
|
|
"description": "A great playlist",
|
|
"is_public": true,
|
|
"track_count": 10,
|
|
"tracks": [
|
|
{
|
|
"id": "660e8400-e29b-41d4-a716-446655440001",
|
|
"title": "Track 1",
|
|
"position": 1
|
|
}
|
|
],
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Create Playlist
|
|
|
|
Create a new playlist.
|
|
|
|
**Endpoint:** `POST /api/v1/playlists`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"title": "My New Playlist",
|
|
"description": "A great playlist",
|
|
"is_public": true
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"playlist": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "My New Playlist",
|
|
"description": "A great playlist",
|
|
"is_public": true,
|
|
"track_count": 0,
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Update Playlist
|
|
|
|
Update playlist metadata.
|
|
|
|
**Endpoint:** `PUT /api/v1/playlists/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"title": "Updated Playlist Title",
|
|
"description": "Updated description",
|
|
"is_public": false
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"playlist": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "Updated Playlist Title",
|
|
"description": "Updated description"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Delete Playlist
|
|
|
|
Permanently delete a playlist.
|
|
|
|
**Endpoint:** `DELETE /api/v1/playlists/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Playlist deleted successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Add Track to Playlist
|
|
|
|
Add a track to the playlist.
|
|
|
|
**Endpoint:** `POST /api/v1/playlists/{id}/tracks`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"track_id": "660e8400-e29b-41d4-a716-446655440001"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Track added to playlist"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Remove Track from Playlist
|
|
|
|
Remove a track from the playlist.
|
|
|
|
**Endpoint:** `DELETE /api/v1/playlists/{id}/tracks/{track_id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Track removed from playlist"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Reorder Tracks
|
|
|
|
Reorder tracks in the playlist.
|
|
|
|
**Endpoint:** `PUT /api/v1/playlists/{id}/tracks/reorder`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"track_ids": [
|
|
"660e8400-e29b-41d4-a716-446655440001",
|
|
"770e8400-e29b-41d4-a716-446655440002",
|
|
"880e8400-e29b-41d4-a716-446655440003"
|
|
]
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Tracks reordered successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Playlist Recommendations
|
|
|
|
Get playlist recommendations.
|
|
|
|
**Endpoint:** `GET /api/v1/playlists/recommendations`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Query Parameters:**
|
|
- `limit` (optional) - Number of recommendations (default: 10)
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"playlists": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "Recommended Playlist",
|
|
"is_public": true
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Add Collaborator
|
|
|
|
Add a collaborator to a playlist.
|
|
|
|
**Endpoint:** `POST /api/v1/playlists/{id}/collaborators`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"user_id": "990e8400-e29b-41d4-a716-446655440004",
|
|
"permission": "write"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Collaborator added successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Collaborators
|
|
|
|
Get list of collaborators for a playlist.
|
|
|
|
**Endpoint:** `GET /api/v1/playlists/{id}/collaborators`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"collaborators": [
|
|
{
|
|
"id": "990e8400-e29b-41d4-a716-446655440004",
|
|
"username": "collaborator",
|
|
"permission": "write",
|
|
"added_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Update Collaborator Permission
|
|
|
|
Update collaborator permission.
|
|
|
|
**Endpoint:** `PUT /api/v1/playlists/{id}/collaborators/{userId}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"permission": "admin"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Collaborator permission updated"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Remove Collaborator
|
|
|
|
Remove a collaborator from a playlist.
|
|
|
|
**Endpoint:** `DELETE /api/v1/playlists/{id}/collaborators/{userId}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Collaborator removed successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Create Share Link
|
|
|
|
Create a share link for a playlist.
|
|
|
|
**Endpoint:** `POST /api/v1/playlists/{id}/share`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"share_token": "abc123def456",
|
|
"share_url": "https://veza.app/playlists/shared/abc123def456",
|
|
"expires_at": "2025-12-31T23:59:59Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Marketplace Endpoints
|
|
|
|
#### List Products
|
|
|
|
List marketplace products with filters.
|
|
|
|
**Endpoint:** `GET /api/v1/marketplace/products`
|
|
|
|
**Query Parameters:**
|
|
- `status` (optional) - Product status (draft, active, archived)
|
|
- `seller_id` (optional) - Filter by seller ID
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "My Product",
|
|
"description": "A great track for sale",
|
|
"price": 9.99,
|
|
"currency": "EUR",
|
|
"status": "active",
|
|
"product_type": "track",
|
|
"seller_id": "660e8400-e29b-41d4-a716-446655440001",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Create Product
|
|
|
|
Create a product (Track, Pack, Service) for sale.
|
|
|
|
**Endpoint:** `POST /api/v1/marketplace/products`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"title": "My Product",
|
|
"description": "A great track for sale",
|
|
"price": 9.99,
|
|
"product_type": "track",
|
|
"track_id": "770e8400-e29b-41d4-a716-446655440002",
|
|
"license_type": "standard"
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "My Product",
|
|
"price": 9.99,
|
|
"status": "active",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Update Product
|
|
|
|
Update product details (only seller can update).
|
|
|
|
**Endpoint:** `PUT /api/v1/marketplace/products/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"title": "Updated Product Title",
|
|
"price": 12.99,
|
|
"status": "active"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"title": "Updated Product Title",
|
|
"price": 12.99
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Create Order
|
|
|
|
Purchase products.
|
|
|
|
**Endpoint:** `POST /api/v1/marketplace/orders`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"items": [
|
|
{
|
|
"product_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": "880e8400-e29b-41d4-a716-446655440003",
|
|
"buyer_id": "990e8400-e29b-41d4-a716-446655440004",
|
|
"total_amount": 9.99,
|
|
"currency": "EUR",
|
|
"status": "completed",
|
|
"items": [
|
|
{
|
|
"product_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"price": 9.99
|
|
}
|
|
],
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### List Orders
|
|
|
|
Get all orders for the authenticated user.
|
|
|
|
**Endpoint:** `GET /api/v1/marketplace/orders`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"id": "880e8400-e29b-41d4-a716-446655440003",
|
|
"total_amount": 9.99,
|
|
"status": "completed",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Get Order
|
|
|
|
Get details of a specific order.
|
|
|
|
**Endpoint:** `GET /api/v1/marketplace/orders/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": "880e8400-e29b-41d4-a716-446655440003",
|
|
"buyer_id": "990e8400-e29b-41d4-a716-446655440004",
|
|
"total_amount": 9.99,
|
|
"currency": "EUR",
|
|
"status": "completed",
|
|
"items": [
|
|
{
|
|
"product_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"price": 9.99
|
|
}
|
|
],
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Download URL
|
|
|
|
Get a secure download URL for a purchased product.
|
|
|
|
**Endpoint:** `GET /api/v1/marketplace/download/{product_id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"url": "https://storage.example.com/download/track123.mp3?token=abc123"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Analytics Endpoints
|
|
|
|
#### Record Analytics Event
|
|
|
|
Record a custom analytics event.
|
|
|
|
**Endpoint:** `POST /api/v1/analytics/events`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"event_name": "user_interaction",
|
|
"payload": {
|
|
"action": "button_click",
|
|
"page": "home"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "event recorded",
|
|
"event_name": "user_interaction"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Track Analytics Dashboard
|
|
|
|
Get comprehensive analytics dashboard for a track.
|
|
|
|
**Endpoint:** `GET /api/v1/analytics/tracks/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"dashboard": {
|
|
"track_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"stats": {
|
|
"total_plays": 150,
|
|
"unique_listeners": 45,
|
|
"average_duration": 165.5,
|
|
"completion_rate": 78.5
|
|
},
|
|
"plays_over_time": [
|
|
{
|
|
"date": "2025-01-01T00:00:00Z",
|
|
"count": 10
|
|
}
|
|
],
|
|
"period": {
|
|
"start_date": "2024-12-01T00:00:00Z",
|
|
"end_date": "2025-01-01T00:00:00Z",
|
|
"days": 30
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Webhook Endpoints
|
|
|
|
#### Register Webhook
|
|
|
|
Register a new webhook.
|
|
|
|
**Endpoint:** `POST /api/v1/webhooks`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"url": "https://example.com/webhook",
|
|
"events": ["track.uploaded", "playlist.created"],
|
|
"secret": "webhook_secret_key"
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"url": "https://example.com/webhook",
|
|
"api_key": "wh_abc123def456",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### List Webhooks
|
|
|
|
Get all webhooks for the authenticated user.
|
|
|
|
**Endpoint:** `GET /api/v1/webhooks`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"url": "https://example.com/webhook",
|
|
"events": ["track.uploaded"],
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Delete Webhook
|
|
|
|
Delete a webhook.
|
|
|
|
**Endpoint:** `DELETE /api/v1/webhooks/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Webhook deleted successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Test Webhook
|
|
|
|
Test a webhook by sending a test event.
|
|
|
|
**Endpoint:** `POST /api/v1/webhooks/{id}/test`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Test event sent",
|
|
"status": "delivered"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Webhook Stats
|
|
|
|
Get statistics for webhooks.
|
|
|
|
**Endpoint:** `GET /api/v1/webhooks/stats`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"total_webhooks": 5,
|
|
"total_events": 150,
|
|
"successful_deliveries": 145,
|
|
"failed_deliveries": 5
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Regenerate API Key
|
|
|
|
Regenerate API key for a webhook.
|
|
|
|
**Endpoint:** `POST /api/v1/webhooks/{id}/regenerate-key`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"api_key": "wh_new_abc123def456"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Chat Endpoints
|
|
|
|
#### Get Chat Token
|
|
|
|
Generate a short-lived token for chat authentication.
|
|
|
|
**Endpoint:** `GET /api/v1/chat/token`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"token": "chat_token_abc123"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Chat Stats
|
|
|
|
Get chat statistics.
|
|
|
|
**Endpoint:** `GET /api/v1/chat/stats`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"total_rooms": 10,
|
|
"total_messages": 500,
|
|
"active_users": 25
|
|
}
|
|
}
|
|
```
|
|
|
|
### Search Endpoints
|
|
|
|
Search is **resource-specific**; there is no unified `GET /api/v1/search` endpoint. Use the following:
|
|
|
|
- **Tracks:** `GET /api/v1/tracks/search` — see [Search Tracks](#search-tracks) (query `q`, `page`, `limit`, etc.).
|
|
- **Playlists:** `GET /api/v1/playlists/search` — see [Search Playlists](#search-playlists) (query `q`, `user_id`, `is_public`, `page`, `limit`).
|
|
- **Users:** `GET /api/v1/users/search` — query `q`, `page`, `limit`.
|
|
|
|
Pagination: `page` must be >= 1, `limit` between 1 and 100; otherwise the API returns 400 with a clear message.
|
|
|
|
### Comment Endpoints
|
|
|
|
#### Get Comments
|
|
|
|
Get comments for a track.
|
|
|
|
**Endpoint:** `GET /api/v1/tracks/{id}/comments`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"comments": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"user_id": "660e8400-e29b-41d4-a716-446655440001",
|
|
"username": "johndoe",
|
|
"content": "Great track!",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Create Comment
|
|
|
|
Create a comment on a track.
|
|
|
|
**Endpoint:** `POST /api/v1/tracks/{id}/comments`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"content": "Great track!"
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"comment": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"content": "Great track!",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Delete Comment
|
|
|
|
Delete a comment.
|
|
|
|
**Endpoint:** `DELETE /api/v1/comments/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Comment deleted successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Role Endpoints
|
|
|
|
#### Get Roles
|
|
|
|
Get all available roles.
|
|
|
|
**Endpoint:** `GET /api/v1/roles`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"roles": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"name": "admin",
|
|
"permissions": ["all"]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Role
|
|
|
|
Get details of a specific role.
|
|
|
|
**Endpoint:** `GET /api/v1/roles/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"role": {
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"name": "admin",
|
|
"permissions": ["all"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Notification Endpoints
|
|
|
|
#### Get Notifications
|
|
|
|
Get notifications for the authenticated user.
|
|
|
|
**Endpoint:** `GET /api/v1/notifications`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Query Parameters:**
|
|
- `page` (optional) - Page number
|
|
- `limit` (optional) - Items per page
|
|
- `unread_only` (optional) - Filter unread only (true/false)
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"notifications": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"type": "track_liked",
|
|
"message": "Your track was liked",
|
|
"read": false,
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Mark Notification as Read
|
|
|
|
Mark a notification as read.
|
|
|
|
**Endpoint:** `POST /api/v1/notifications/{id}/read`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Notification marked as read"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Mark All Notifications as Read
|
|
|
|
Mark all notifications as read.
|
|
|
|
**Endpoint:** `POST /api/v1/notifications/read-all`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "All notifications marked as read"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Session Endpoints
|
|
|
|
#### Get Sessions
|
|
|
|
Get all active sessions for the authenticated user.
|
|
|
|
**Endpoint:** `GET /api/v1/sessions`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"sessions": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"ip_address": "192.168.1.1",
|
|
"user_agent": "Mozilla/5.0...",
|
|
"created_at": "2025-01-01T00:00:00Z",
|
|
"last_activity": "2025-01-01T12:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Logout Session
|
|
|
|
Logout from a specific session.
|
|
|
|
**Endpoint:** `POST /api/v1/sessions/logout`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Logged out successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Logout All Sessions
|
|
|
|
Logout from all sessions.
|
|
|
|
**Endpoint:** `POST /api/v1/sessions/logout-all`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Logged out from all sessions"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Revoke Session
|
|
|
|
Revoke a specific session.
|
|
|
|
**Endpoint:** `DELETE /api/v1/sessions/{session_id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"message": "Session revoked successfully"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Session Stats
|
|
|
|
Get session statistics.
|
|
|
|
**Endpoint:** `GET /api/v1/sessions/stats`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"total_sessions": 5,
|
|
"active_sessions": 3
|
|
}
|
|
}
|
|
```
|
|
|
|
### Upload Endpoints
|
|
|
|
#### Upload File
|
|
|
|
Upload a file.
|
|
|
|
**Endpoint:** `POST /api/v1/uploads`
|
|
|
|
**Headers:**
|
|
- `Authorization: Bearer <token>`
|
|
- `Content-Type: multipart/form-data`
|
|
|
|
**Form Data:**
|
|
- `file` (required) - File to upload
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"upload_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"status": "processing"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Upload Status
|
|
|
|
Get upload status.
|
|
|
|
**Endpoint:** `GET /api/v1/uploads/{id}/status`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"status": "completed",
|
|
"progress": 100
|
|
}
|
|
}
|
|
```
|
|
|
|
### Audit Endpoints
|
|
|
|
#### Search Audit Logs
|
|
|
|
Search audit logs.
|
|
|
|
**Endpoint:** `GET /api/v1/audit/logs`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Query Parameters:**
|
|
- `user_id` (optional) - Filter by user ID
|
|
- `action` (optional) - Filter by action
|
|
- `start_date` (optional) - Start date (RFC3339)
|
|
- `end_date` (optional) - End date (RFC3339)
|
|
- `page` (optional) - Page number
|
|
- `limit` (optional) - Items per page
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"logs": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"user_id": "660e8400-e29b-41d4-a716-446655440001",
|
|
"action": "track.uploaded",
|
|
"ip_address": "192.168.1.1",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Audit Stats
|
|
|
|
Get audit statistics.
|
|
|
|
**Endpoint:** `GET /api/v1/audit/stats`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"total_logs": 1000,
|
|
"actions_count": {
|
|
"track.uploaded": 500,
|
|
"playlist.created": 300
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Admin Endpoints
|
|
|
|
All admin endpoints require admin role.
|
|
|
|
#### Get Audit Logs (Admin)
|
|
|
|
**Endpoint:** `GET /api/v1/admin/audit/logs`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
#### Get Audit Stats (Admin)
|
|
|
|
**Endpoint:** `GET /api/v1/admin/audit/stats`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
#### Detect Suspicious Activity (Admin)
|
|
|
|
**Endpoint:** `GET /api/v1/admin/audit/suspicious`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
## Additional Resources
|
|
|
|
- **Swagger UI:** `/swagger/index.html` - Interactive API documentation
|
|
- **ReDoc:** `/redoc` - Alternative API documentation
|
|
- **OpenAPI Spec:** `/swagger/doc.json` - OpenAPI 3.0 specification
|
|
|
|
## Support
|
|
|
|
For API support, please contact:
|
|
- **Email:** support@veza.app
|
|
- **Documentation:** https://docs.veza.app
|
|
- **Issues:** https://github.com/veza/veza-backend-api/issues
|
|
|