# ORIGIN_API_SPECIFICATION.md ## 📋 RÉSUMÉ EXÉCUTIF Ce document dĂ©finit la spĂ©cification complĂšte et dĂ©finitive de toutes les APIs de la plateforme Veza. Il documente 500+ endpoints REST, 50+ Ă©vĂ©nements WebSocket, et 20+ services gRPC avec leurs schĂ©mas de requĂȘte/rĂ©ponse, codes d'erreur standardisĂ©s, authentication flows, rate limiting, et versioning. L'API suit les principes REST/RESTful, utilise JSON comme format d'Ă©change, et implĂ©mente OAuth 2.0 + JWT pour l'authentification. ## 🎯 OBJECTIFS ### Objectif Principal DĂ©finir une API complĂšte, cohĂ©rente, documentĂ©e, et immuable qui servira de contrat entre frontend/backend/mobile pendant 24 mois sans breaking changes. ### Objectifs Secondaires - Assurer la cohĂ©rence des schĂ©mas (naming, structure, types) - Standardiser les codes d'erreur et messages - Faciliter l'intĂ©gration (clients, partenaires, dĂ©veloppeurs tiers) - Garantir la scalabilitĂ© (rate limiting, caching, pagination) - Supporter le versioning (v1 stable, v2 pour Ă©volutions) ## 📖 TABLE DES MATIÈRES 1. [Design Principles](#1-design-principles) 2. [Authentication & Authorization](#2-authentication--authorization) 3. [Common Patterns](#3-common-patterns) 4. [Error Handling](#4-error-handling) 5. [Rate Limiting](#5-rate-limiting) 6. [Versioning](#6-versioning) 7. [REST API Endpoints](#7-rest-api-endpoints) 8. [WebSocket APIs](#8-websocket-apis) 9. [gRPC APIs](#9-grpc-apis) 10. [OpenAPI 3.0 Specification](#10-openapi-30-specification) ## 🔒 RÈGLES IMMUABLES 1. **URLs DOIVENT suivre le pattern** `/api/v{version}/{resource}` 2. **HTTP methods DOIVENT respecter REST** (GET=read, POST=create, PUT=replace, PATCH=update, DELETE=delete) 3. **Responses DOIVENT ĂȘtre JSON** avec `Content-Type: application/json` 4. **Dates DOIVENT ĂȘtre ISO 8601** (format: `2025-11-02T14:30:00Z`) 5. **IDs DOIVENT ĂȘtre UUID v4** (format: `550e8400-e29b-41d4-a716-446655440000`) 6. **Pagination OBLIGATOIRE** pour collections (cursor-based par dĂ©faut) 7. **Rate limiting OBLIGATOIRE** (headers: `X-RateLimit-*`) 8. **Authentication JWT** dans header `Authorization: Bearer {token}` 9. **Error codes STANDARDISÉS** (range 1000-9999, voir section 4) 10. **Breaking changes INTERDITS** dans v1 (crĂ©er v2 si nĂ©cessaire) ## 1. DESIGN PRINCIPLES ### 1.1 RESTful Architecture **Resource-Oriented URLs**: ``` ✅ Good: GET /api/v1/tracks/{id} ❌ Bad: GET /api/v1/getTrackById?id={id} ✅ Good: POST /api/v1/tracks/{id}/like ❌ Bad: POST /api/v1/likeTrack ✅ Good: GET /api/v1/users/{id}/tracks ❌ Bad: GET /api/v1/getTracksForUser?userId={id} ``` **HTTP Method Semantics**: ``` GET - Retrieve resource(s) (idempotent, cacheable) POST - Create new resource (non-idempotent) PUT - Replace entire resource (idempotent) PATCH - Partial update resource (idempotent) DELETE - Delete resource (idempotent) ``` ### 1.2 Consistency **Naming Conventions**: - **Resources**: Plural nouns (`tracks`, `users`, `playlists`) - **Fields**: snake_case (`created_at`, `user_id`, `is_active`) - **Enums**: lowercase with underscores (`public`, `unlisted`, `private`) **Common Fields**: ```json { "id": "uuid", "created_at": "ISO 8601 timestamp", "updated_at": "ISO 8601 timestamp", "deleted_at": "ISO 8601 timestamp | null" } ``` ### 1.3 HATEOAS (Optional) **Include links for navigation**: ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "title": "My Track", "_links": { "self": "/api/v1/tracks/550e8400-e29b-41d4-a716-446655440000", "creator": "/api/v1/users/123e4567-e89b-12d3-a456-426614174000", "likes": "/api/v1/tracks/550e8400-e29b-41d4-a716-446655440000/likes" } } ``` ## 2. AUTHENTICATION & AUTHORIZATION ### 2.1 JWT Authentication **Login Flow**: ``` POST /api/v1/auth/login Request: { "email": "user@example.com", "password": "SecurePass123!" } Response: { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "dGhpc2lzYXJlZnJlc2h0b2tlbg...", "expires_in": 900, "token_type": "Bearer", "user": { "id": "uuid", "email": "user@example.com", "username": "johndoe", "role": "user" } } ``` **JWT Claims**: ```json { "sub": "550e8400-e29b-41d4-a716-446655440000", "email": "user@example.com", "role": "user", "token_version": 0, "iat": 1730556000, "exp": 1730559600 } ``` **Using Access Token**: ``` Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` **Refresh Token Flow**: ``` POST /api/v1/auth/refresh Request: { "refresh_token": "dGhpc2lzYXJlZnJlc2h0b2tlbg..." } Response: { "access_token": "new_jwt_token...", "expires_in": 900 } ``` ### 2.2 OAuth 2.0 (Social Login) **Supported Providers**: Google, GitHub, Discord, Spotify **OAuth Flow**: ``` 1. GET /api/v1/auth/oauth/{provider} → Redirect to provider authorization URL 2. Provider redirects back to: /api/v1/auth/oauth/{provider}/callback?code=... 3. Backend exchanges code for tokens and returns JWT ``` ### 2.3 Authorization (RBAC) **Roles**: - `user` - Standard user (default) - `creator` - Content creator (verified) - `premium` - Premium subscriber - `moderator` - Community moderator - `admin` - System administrator **Permission Matrix** (examples): | Action | user | creator | premium | moderator | admin | |--------|------|---------|---------|-----------|-------| | Upload track | ❌ | ✅ | ✅ | ✅ | ✅ | | Delete own track | ❌ | ✅ | ✅ | ✅ | ✅ | | Delete any track | ❌ | ❌ | ❌ | ✅ | ✅ | | Create playlist | ✅ | ✅ | ✅ | ✅ | ✅ | | Ban user | ❌ | ❌ | ❌ | ✅ | ✅ | | Modify system config | ❌ | ❌ | ❌ | ❌ | ✅ | **Checking Permissions** (backend): ```go // Middleware example func RequireRole(allowedRoles ...string) gin.HandlerFunc { return func(c *gin.Context) { user := GetCurrentUser(c) if !contains(allowedRoles, user.Role) { c.JSON(403, ErrorResponse{Code: 1003, Message: "Forbidden"}) c.Abort() return } c.Next() } } // Usage r.POST("/tracks", RequireRole("creator", "premium"), handlers.CreateTrack) ``` ## 3. COMMON PATTERNS ### 3.1 Pagination **Cursor-Based Pagination** (recommended for feeds): ``` GET /api/v1/tracks?limit=20&cursor=eyJpZCI6IjU1MGU4NDAwIn0 Response: { "data": [ /* 20 tracks */ ], "pagination": { "next_cursor": "eyJpZCI6IjY2MWU5NTExIn0", "has_more": true, "limit": 20 } } ``` **Offset-Based Pagination** (for fixed pages): ``` GET /api/v1/tracks?page=2&per_page=20 Response: { "data": [ /* 20 tracks */ ], "pagination": { "current_page": 2, "per_page": 20, "total_pages": 150, "total_count": 3000 } } ``` ### 3.2 Filtering **Query Parameters**: ``` GET /api/v1/tracks?genre=electronic&bpm_min=120&bpm_max=140&visibility=public Supported operators: - Equality: ?genre=electronic - Range: ?bpm_min=120&bpm_max=140 - In: ?genre=electronic,house,techno - Date range: ?created_after=2025-01-01&created_before=2025-12-31 ``` ### 3.3 Sorting ``` GET /api/v1/tracks?sort=-created_at,title Format: - {field} for ascending - -{field} for descending - Multiple fields: comma-separated ``` ### 3.4 Field Selection (Sparse Fieldsets) ``` GET /api/v1/tracks?fields=id,title,artist,duration Response includes only requested fields (reduces payload size) ``` ### 3.5 Embedding Related Resources ``` GET /api/v1/tracks/{id}?include=creator,likes Response: { "id": "uuid", "title": "Track Title", "creator": { "id": "uuid", "username": "johndoe", "avatar_url": "https://..." }, "likes": [ { "user_id": "uuid", "created_at": "2025-11-01T12:00:00Z" } ] } ``` ### 3.6 Bulk Operations **Batch Create**: ``` POST /api/v1/tracks/batch Request: { "tracks": [ { "title": "Track 1", "file_id": "uuid1" }, { "title": "Track 2", "file_id": "uuid2" } ] } Response: { "created": [ { "id": "uuid", "title": "Track 1" }, { "id": "uuid", "title": "Track 2" } ], "failed": [] } ``` **Batch Update**: ``` PATCH /api/v1/tracks/batch Request: { "updates": [ { "id": "uuid1", "visibility": "private" }, { "id": "uuid2", "title": "New Title" } ] } ``` ## 4. ERROR HANDLING ### 4.1 Error Response Format ```json { "error": { "code": 1001, "message": "Validation failed", "details": [ { "field": "email", "message": "Invalid email format" } ], "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-11-02T14:30:00Z" } } ``` ### 4.2 HTTP Status Codes | Status | Usage | |--------|-------| | **200 OK** | Successful GET, PATCH, PUT | | **201 Created** | Successful POST (resource created) | | **204 No Content** | Successful DELETE | | **400 Bad Request** | Invalid request (validation errors) | | **401 Unauthorized** | Missing or invalid authentication | | **403 Forbidden** | Authenticated but insufficient permissions | | **404 Not Found** | Resource not found | | **409 Conflict** | Resource conflict (duplicate, state) | | **422 Unprocessable Entity** | Semantic errors | | **429 Too Many Requests** | Rate limit exceeded | | **500 Internal Server Error** | Server error | | **503 Service Unavailable** | Temporary unavailable | ### 4.3 Error Codes (1000-9999) **Authentication & Authorization (1000-1999)**: ``` 1000 - Invalid credentials 1001 - Token expired 1002 - Token invalid 1003 - Insufficient permissions 1004 - Account not verified 1005 - Account suspended 1006 - Account banned 1007 - Two-factor authentication required 1008 - Invalid two-factor code 1009 - OAuth provider error ``` **Validation Errors (2000-2999)**: ``` 2000 - Validation failed (generic) 2001 - Required field missing 2002 - Invalid field format 2003 - Field value out of range 2004 - Invalid enum value 2005 - Invalid UUID format 2006 - Invalid date format 2007 - Invalid email format 2008 - Invalid URL format 2009 - File too large 2010 - Unsupported file type ``` **Resource Errors (3000-3999)**: ``` 3000 - Resource not found 3001 - Resource already exists 3002 - Resource conflict 3003 - Resource deleted 3004 - Resource locked 3005 - Resource quota exceeded ``` **Business Logic Errors (4000-4999)**: ``` 4000 - Operation not allowed 4001 - Insufficient balance 4002 - Product out of stock 4003 - Order already paid 4004 - Cannot cancel order 4005 - Maximum upload limit reached 4006 - Duplicate track title 4007 - Playlist is full 4008 - Cannot unfollow yourself 4009 - Already following user 4010 - User blocked you ``` **Rate Limiting (5000-5099)**: ``` 5000 - Rate limit exceeded 5001 - Daily quota exceeded 5002 - Monthly quota exceeded 5003 - Concurrent request limit ``` **External Services (6000-6999)**: ``` 6000 - Payment provider error 6001 - File storage error 6002 - Email service error 6003 - SMS service error 6004 - CDN error 6005 - Search service error ``` **Internal Errors (9000-9999)**: ``` 9000 - Internal server error 9001 - Database error 9002 - Cache error 9003 - Message queue error 9004 - Configuration error ``` ## 5. RATE LIMITING ### 5.1 Rate Limits by Endpoint Type | Endpoint Type | Limit | Window | |---------------|-------|--------| | **Authentication** | 10 requests | 1 minute | | **Read (GET)** | 1000 requests | 1 hour | | **Write (POST/PUT/PATCH)** | 100 requests | 1 hour | | **File Upload** | 10 uploads | 1 hour | | **Search** | 500 requests | 1 hour | | **Streaming** | 10,000 plays | 1 day | ### 5.2 Rate Limit Headers **Included in every response**: ``` X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 950 X-RateLimit-Reset: 1730559600 X-RateLimit-Window: 3600 ``` **When rate limit exceeded (429)**: ``` HTTP/1.1 429 Too Many Requests X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1730559600 Retry-After: 1800 { "error": { "code": 5000, "message": "Rate limit exceeded. Try again in 30 minutes." } } ``` ### 5.3 Premium User Limits | Endpoint Type | Standard | Premium | Factor | |---------------|----------|---------|--------| | Read | 1,000/hr | 5,000/hr | 5x | | Write | 100/hr | 500/hr | 5x | | Upload | 10/hr | 50/hr | 5x | | Search | 500/hr | 2,500/hr | 5x | ## 6. VERSIONING ### 6.1 URL Versioning **Current version**: v1 **Format**: `/api/v{major_version}/{resource}` ``` /api/v1/tracks /api/v2/tracks (future) ``` ### 6.2 Version Lifecycle | Version | Status | Support End | |---------|--------|-------------| | **v1** | ✅ Stable | Q4 2026 minimum | | **v2** | 🔄 Planned | TBD | ### 6.3 Breaking vs Non-Breaking Changes **Non-Breaking (allowed in v1)**: - Adding new endpoints - Adding optional query parameters - Adding new fields to responses (clients should ignore unknown fields) - Adding new enum values (if gracefully handled) - Adding new error codes **Breaking (require v2)**: - Removing endpoints - Removing fields from responses - Changing field types - Changing required/optional status of fields - Changing URL structure - Changing authentication method ### 6.4 Deprecation Process 1. **Announce** deprecation (6 months notice minimum) 2. **Add header** `Deprecation: true` to deprecated endpoints 3. **Provide migration guide** in docs 4. **Monitor usage** of deprecated endpoints 5. **Remove** in next major version ## 7. REST API ENDPOINTS ### 7.1 Module: Authentication #### `POST /api/v1/auth/register` **Description**: Register new user account. **Request**: ```json { "email": "user@example.com", "username": "johndoe", "password": "SecurePass123!", "first_name": "John", "last_name": "Doe" } ``` **Response** (201 Created): ```json { "user": { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "user@example.com", "username": "johndoe", "role": "user", "is_active": true, "created_at": "2025-11-02T14:30:00Z" }, "message": "Registration successful. Please verify your email." } ``` **Errors**: - `400` - Validation failed (2000) - `409` - Email/username already exists (3001) --- #### `POST /api/v1/auth/login` **Description**: Login with email/password. **Request**: ```json { "email": "user@example.com", "password": "SecurePass123!" } ``` **Response** (200 OK): ```json { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "dGhpc2lzYXJlZnJlc2h0b2tlbg...", "expires_in": 900, "token_type": "Bearer", "user": { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "user@example.com", "username": "johndoe", "role": "creator" } } ``` **Errors**: - `400` - Invalid credentials (1000) - `403` - Account suspended (1005) --- #### `POST /api/v1/auth/logout` **Description**: Logout (invalidate refresh token). **Headers**: `Authorization: Bearer {token}` **Request**: Empty **Response** (204 No Content) --- #### `POST /api/v1/auth/refresh` **Description**: Refresh access token. **Request**: ```json { "refresh_token": "dGhpc2lzYXJlZnJlc2h0b2tlbg..." } ``` **Response** (200 OK): ```json { "access_token": "new_jwt_token...", "expires_in": 900 } ``` **Errors**: - `401` - Invalid refresh token (1002) --- #### `POST /api/v1/auth/forgot-password` **Description**: Request password reset email. **Request**: ```json { "email": "user@example.com" } ``` **Response** (200 OK): ```json { "message": "Password reset email sent if account exists." } ``` --- #### `POST /api/v1/auth/reset-password` **Description**: Reset password with token. **Request**: ```json { "token": "reset_token_from_email", "new_password": "NewSecurePass456!" } ``` **Response** (200 OK): ```json { "message": "Password reset successful." } ``` **Errors**: - `400` - Invalid or expired token (1002) --- #### `POST /api/v1/auth/verify-email` **Description**: Verify email with token. **Request**: ```json { "token": "email_verification_token" } ``` **Response** (200 OK): ```json { "message": "Email verified successfully." } ``` --- #### `GET /api/v1/auth/me` **Description**: Get current authenticated user. **Headers**: `Authorization: Bearer {token}` **Response** (200 OK): ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "user@example.com", "username": "johndoe", "role": "creator", "is_active": true, "is_verified": true, "profile": { "bio": "Music producer from NYC", "avatar_url": "https://cdn.veza.io/avatars/...", "follower_count": 1250, "following_count": 450 }, "created_at": "2024-01-15T10:00:00Z" } ``` **Errors**: - `401` - Unauthorized (1002) --- ### 7.2 Module: Users #### `GET /api/v1/users/{id}` **Description**: Get user profile by ID. **Parameters**: - `id` (path, required) - User UUID - `include` (query, optional) - Related resources (`profile,stats,badges`) **Response** (200 OK): ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "username": "johndoe", "display_name": "John Doe", "role": "creator", "profile": { "bio": "Music producer from NYC", "avatar_url": "https://cdn.veza.io/avatars/...", "banner_url": "https://cdn.veza.io/banners/...", "location": "New York, USA", "website_url": "https://johndoe.com" }, "stats": { "follower_count": 1250, "following_count": 450, "track_count": 85, "playlist_count": 12 }, "badges": [ { "name": "Verified Creator", "icon_url": "https://cdn.veza.io/badges/verified.svg", "rarity": "rare" } ], "created_at": "2024-01-15T10:00:00Z" } ``` **Errors**: - `404` - User not found (3000) --- #### `PATCH /api/v1/users/{id}` **Description**: Update user profile. **Headers**: `Authorization: Bearer {token}` **Permissions**: Own profile or admin **Request**: ```json { "display_name": "Johnny Doe", "profile": { "bio": "Award-winning music producer", "location": "Los Angeles, USA", "website_url": "https://johnnydoe.com" } } ``` **Response** (200 OK): Same as GET **Errors**: - `403` - Forbidden (1003) --- #### `GET /api/v1/users/{id}/tracks` **Description**: Get user's tracks. **Parameters**: - `id` (path, required) - User UUID - `limit` (query, optional, default=20) - Page size - `cursor` (query, optional) - Pagination cursor - `sort` (query, optional, default=-created_at) - Sort field - `visibility` (query, optional) - Filter by visibility **Response** (200 OK): ```json { "data": [ { "id": "track-uuid", "title": "Summer Vibes", "artist": "johndoe", "duration": 245, "genre": "Electronic", "cover_art_url": "https://...", "play_count": 12500, "like_count": 850, "created_at": "2025-06-15T10:00:00Z" } ], "pagination": { "next_cursor": "eyJpZCI6IjY2MWU5NTExIn0", "has_more": true, "limit": 20 } } ``` --- #### `GET /api/v1/users/{id}/followers` **Description**: Get user's followers. **Response** (200 OK): ```json { "data": [ { "id": "follower-uuid", "username": "jane_smith", "display_name": "Jane Smith", "avatar_url": "https://...", "followed_at": "2025-10-01T12:00:00Z" } ], "pagination": { /* ... */ } } ``` --- #### `GET /api/v1/users/{id}/following` **Description**: Get users followed by user. **Response**: Same format as followers --- #### `POST /api/v1/users/{id}/follow` **Description**: Follow a user. **Headers**: `Authorization: Bearer {token}` **Response** (201 Created): ```json { "message": "Successfully followed user.", "followed_at": "2025-11-02T14:30:00Z" } ``` **Errors**: - `409` - Already following (4009) - `400` - Cannot follow yourself (4008) --- #### `DELETE /api/v1/users/{id}/follow` **Description**: Unfollow a user. **Response** (204 No Content) --- #### `POST /api/v1/users/{id}/block` **Description**: Block a user. **Request**: ```json { "reason": "Spam" } ``` **Response** (201 Created) --- #### `DELETE /api/v1/users/{id}/block` **Description**: Unblock a user. **Response** (204 No Content) --- ### 7.3 Module: Tracks #### `GET /api/v1/tracks` **Description**: List all public tracks (discovery feed). **Parameters**: - `limit` (query, optional, default=20) - Page size - `cursor` (query, optional) - Pagination cursor - `genre` (query, optional) - Filter by genre - `bpm_min`, `bpm_max` (query, optional) - BPM range - `duration_min`, `duration_max` (query, optional) - Duration range (seconds) - `sort` (query, optional, default=-created_at) - Sort field - `search` (query, optional) - Full-text search **Response** (200 OK): ```json { "data": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "title": "Midnight Dreams", "artist": "DJ Nova", "duration": 245, "genre": "Electronic", "bpm": 128, "musical_key": "Am", "cover_art_url": "https://cdn.veza.io/covers/...", "waveform_url": "https://cdn.veza.io/waveforms/...", "creator": { "id": "creator-uuid", "username": "djnova", "avatar_url": "https://..." }, "play_count": 12500, "like_count": 850, "comment_count": 42, "visibility": "public", "is_downloadable": false, "published_at": "2025-10-15T10:00:00Z", "created_at": "2025-10-15T09:45:00Z" } ], "pagination": { "next_cursor": "eyJpZCI6IjY2MWU5NTExIn0", "has_more": true, "limit": 20 } } ``` --- #### `POST /api/v1/tracks` **Description**: Upload a new track. **Headers**: - `Authorization: Bearer {token}` - `Content-Type: multipart/form-data` **Permissions**: `creator`, `premium`, `admin` **Request** (multipart/form-data): ``` title: "Midnight Dreams" artist: "DJ Nova" description: "A dreamy electronic track..." genre: "Electronic" bpm: 128 musical_key: "Am" visibility: "public" is_downloadable: false file: (audio file) cover_art: (image file, optional) ``` **Response** (201 Created): ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "title": "Midnight Dreams", "status": "processing", "message": "Track uploaded successfully. Processing waveform and metadata..." } ``` **Errors**: - `403` - Insufficient permissions (1003) - `400` - Invalid file type (2010) - `400` - File too large (2009) - `400` - Upload limit reached (4005) --- #### `GET /api/v1/tracks/{id}` **Description**: Get track details. **Parameters**: - `id` (path, required) - Track UUID - `include` (query, optional) - Related resources (`creator,stats,comments`) **Response** (200 OK): Same as list item + full metadata --- #### `PATCH /api/v1/tracks/{id}` **Description**: Update track metadata. **Headers**: `Authorization: Bearer {token}` **Permissions**: Track owner or admin **Request**: ```json { "title": "Midnight Dreams (Remix)", "description": "Updated description", "genre": "House", "visibility": "private" } ``` **Response** (200 OK): Updated track object --- #### `DELETE /api/v1/tracks/{id}` **Description**: Delete track (soft delete). **Headers**: `Authorization: Bearer {token}` **Permissions**: Track owner or admin **Response** (204 No Content) --- #### `GET /api/v1/tracks/{id}/stream` **Description**: Get streaming URL for track. **Headers**: `Authorization: Bearer {token}` (optional for public tracks) **Response** (200 OK): ```json { "stream_url": "https://cdn.veza.io/streams/550e8400.m3u8", "format": "hls", "bitrates": [128, 256, 320], "expires_at": "2025-11-02T15:30:00Z" } ``` --- #### `POST /api/v1/tracks/{id}/like` **Description**: Like a track. **Headers**: `Authorization: Bearer {token}` **Response** (201 Created): ```json { "message": "Track liked successfully.", "liked_at": "2025-11-02T14:30:00Z" } ``` --- #### `DELETE /api/v1/tracks/{id}/like` **Description**: Unlike a track. **Response** (204 No Content) --- #### `GET /api/v1/tracks/{id}/likes` **Description**: Get users who liked track. **Response** (200 OK): ```json { "data": [ { "user": { "id": "uuid", "username": "jane_doe", "avatar_url": "https://..." }, "liked_at": "2025-11-01T12:00:00Z" } ], "pagination": { /* ... */ } } ``` --- #### `GET /api/v1/tracks/{id}/comments` **Description**: Get track comments. **Parameters**: - `timestamp` (query, optional) - Filter by waveform timestamp **Response** (200 OK): ```json { "data": [ { "id": "comment-uuid", "user": { "id": "uuid", "username": "commenter", "avatar_url": "https://..." }, "content": "Love the drop at 2:30!", "timestamp_seconds": 150, "created_at": "2025-11-01T14:00:00Z" } ], "pagination": { /* ... */ } } ``` --- #### `POST /api/v1/tracks/{id}/comments` **Description**: Add comment to track. **Headers**: `Authorization: Bearer {token}` **Request**: ```json { "content": "Amazing track!", "timestamp_seconds": 150 } ``` **Response** (201 Created): Comment object --- ### 7.4 Module: Playlists #### `GET /api/v1/playlists` **Description**: List public playlists. **Response**: Similar to tracks list --- #### `POST /api/v1/playlists` **Description**: Create playlist. **Request**: ```json { "name": "My Favorites", "description": "Best tracks of 2025", "visibility": "public", "is_collaborative": false } ``` **Response** (201 Created): ```json { "id": "playlist-uuid", "name": "My Favorites", "description": "Best tracks of 2025", "visibility": "public", "is_collaborative": false, "track_count": 0, "duration_seconds": 0, "created_at": "2025-11-02T14:30:00Z" } ``` --- #### `GET /api/v1/playlists/{id}` **Description**: Get playlist details with tracks. **Response** (200 OK): ```json { "id": "playlist-uuid", "name": "My Favorites", "description": "Best tracks of 2025", "owner": { "id": "uuid", "username": "johndoe" }, "tracks": [ { "id": "track-uuid", "title": "Track Title", "position": 1, "added_at": "2025-11-01T12:00:00Z" } ], "track_count": 15, "duration_seconds": 3675, "created_at": "2025-10-01T10:00:00Z" } ``` --- #### `POST /api/v1/playlists/{id}/tracks` **Description**: Add track to playlist. **Request**: ```json { "track_id": "550e8400-e29b-41d4-a716-446655440000", "position": 1 } ``` **Response** (201 Created) **Errors**: - `409` - Track already in playlist (3002) - `400` - Playlist is full (4007) --- #### `DELETE /api/v1/playlists/{id}/tracks/{track_id}` **Description**: Remove track from playlist. **Response** (204 No Content) --- #### `PATCH /api/v1/playlists/{id}/tracks/reorder` **Description**: Reorder tracks in playlist. **Request**: ```json { "positions": [ { "track_id": "uuid1", "position": 1 }, { "track_id": "uuid2", "position": 2 } ] } ``` **Response** (200 OK) --- ### 7.5 Module: Chat & Messaging #### `GET /api/v1/rooms` **Description**: List user's chat rooms. **Headers**: `Authorization: Bearer {token}` **Response** (200 OK): ```json { "data": [ { "id": "room-uuid", "name": "General Chat", "room_type": "public", "member_count": 1250, "last_message": { "content": "Hello everyone!", "sender": { "username": "jane_doe" }, "created_at": "2025-11-02T14:25:00Z" }, "unread_count": 5 } ] } ``` --- #### `POST /api/v1/rooms` **Description**: Create chat room. **Request**: ```json { "name": "My Private Room", "room_type": "private", "max_members": 50 } ``` **Response** (201 Created): Room object --- #### `GET /api/v1/rooms/{id}/messages` **Description**: Get room messages. **Parameters**: - `limit` (query, optional, default=50) - `before` (query, optional) - Message ID for pagination **Response** (200 OK): ```json { "data": [ { "id": "message-uuid", "sender": { "id": "uuid", "username": "jane_doe", "avatar_url": "https://..." }, "content": "Hello everyone!", "message_type": "text", "created_at": "2025-11-02T14:25:00Z" } ], "pagination": { /* ... */ } } ``` --- #### `POST /api/v1/rooms/{id}/messages` **Description**: Send message to room. **Request**: ```json { "content": "Hello everyone!", "message_type": "text", "reply_to_id": "optional-message-uuid" } ``` **Response** (201 Created): Message object --- #### `GET /api/v1/direct-messages` **Description**: List direct message conversations. **Response**: List of conversations with last message --- #### `POST /api/v1/direct-messages` **Description**: Send direct message. **Request**: ```json { "recipient_id": "550e8400-e29b-41d4-a716-446655440000", "content": "Hey, how are you?", "message_type": "text" } ``` **Response** (201 Created): Message object --- ### 7.6 Module: Marketplace #### `GET /api/v1/products` **Description**: List marketplace products. **Parameters**: - `category` (query, optional) - Filter by category - `price_min`, `price_max` (query, optional) - Price range - `genre` (query, optional) - Filter by genre - `sort` (query, optional) - Sort field **Response** (200 OK): ```json { "data": [ { "id": "product-uuid", "name": "EDM Sample Pack Vol. 1", "slug": "edm-sample-pack-vol-1", "description": "100+ high-quality EDM samples", "category": "sample", "price": 29.99, "currency": "USD", "seller": { "id": "uuid", "username": "producer_pro" }, "thumbnail_url": "https://...", "preview_file_url": "https://...", "sale_count": 450, "average_rating": 4.8, "review_count": 120 } ], "pagination": { /* ... */ } } ``` --- #### `POST /api/v1/products` **Description**: Create product listing. **Headers**: `Authorization: Bearer {token}` **Permissions**: `creator`, `admin` **Request**: ```json { "name": "EDM Sample Pack Vol. 1", "description": "100+ high-quality EDM samples...", "category": "sample", "price": 29.99, "currency": "USD", "tags": ["edm", "samples", "electronic"], "download_file_ids": ["uuid1", "uuid2"], "license_type": "Royalty-Free" } ``` **Response** (201 Created): Product object --- #### `GET /api/v1/products/{id}` **Description**: Get product details. **Response** (200 OK): Full product object with reviews --- #### `POST /api/v1/cart/items` **Description**: Add product to cart. **Request**: ```json { "product_id": "550e8400-e29b-41d4-a716-446655440000" } ``` **Response** (201 Created): Cart object --- #### `GET /api/v1/cart` **Description**: Get current user's cart. **Response** (200 OK): ```json { "id": "cart-uuid", "items": [ { "product": { "id": "uuid", "name": "Sample Pack", "price": 29.99 }, "added_at": "2025-11-02T14:00:00Z" } ], "item_count": 3, "subtotal": 89.97, "tax_total": 7.20, "total": 97.17, "currency": "USD" } ``` --- #### `POST /api/v1/orders` **Description**: Create order from cart (checkout). **Request**: ```json { "payment_method": "stripe", "billing_email": "user@example.com", "discount_code": "SUMMER25" } ``` **Response** (201 Created): ```json { "order_id": "order-uuid", "order_number": "ORD-2025-00001", "status": "pending", "total": 97.17, "payment_intent_id": "pi_1234567890", "client_secret": "pi_1234567890_secret_..." } ``` --- #### `GET /api/v1/orders/{id}` **Description**: Get order details. **Response** (200 OK): Full order object with items --- #### `GET /api/v1/orders` **Description**: List user's orders. **Response** (200 OK): List of orders --- ### 7.7 Module: Search #### `GET /api/v1/search` **Description**: Global search (tracks, users, playlists, products). **Parameters**: - `q` (query, required) - Search query - `type` (query, optional) - Filter by type (`tracks`, `users`, `playlists`, `products`) - `limit` (query, optional, default=20) **Response** (200 OK): ```json { "tracks": { "data": [ /* track objects */ ], "total": 150 }, "users": { "data": [ /* user objects */ ], "total": 25 }, "playlists": { "data": [ /* playlist objects */ ], "total": 40 }, "products": { "data": [ /* product objects */ ], "total": 30 } } ``` --- ### 7.8 Module: Analytics #### `POST /api/v1/analytics/events` **Description**: Track analytics event (client-side tracking). **Request**: ```json { "event_type": "track_play", "event_data": { "track_id": "uuid", "duration_played": 120, "completion_percentage": 50 }, "metadata": { "user_agent": "...", "referrer": "..." } } ``` **Response** (204 No Content) --- #### `GET /api/v1/analytics/tracks/{id}` **Description**: Get track analytics. **Headers**: `Authorization: Bearer {token}` **Permissions**: Track owner or admin **Response** (200 OK): ```json { "track_id": "uuid", "plays_total": 12500, "plays_unique": 8500, "likes_total": 850, "comments_total": 42, "plays_by_country": { "US": 5000, "UK": 2500, "CA": 1500 }, "plays_by_day": [ { "date": "2025-11-01", "plays": 450 }, { "date": "2025-11-02", "plays": 520 } ] } ``` --- *[7.9-7.15 Other modules follow similar patterns]* ## 8. WEBSOCKET APIS ### 8.1 Connection **URL**: `wss://api.veza.io/ws` **Authentication**: Send JWT in first message ```json { "type": "auth", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` **Response**: ```json { "type": "auth_success", "user_id": "550e8400-e29b-41d4-a716-446655440000" } ``` ### 8.2 Message Types #### Client → Server **Join Room**: ```json { "type": "join_room", "room_id": "room-uuid" } ``` **Leave Room**: ```json { "type": "leave_room", "room_id": "room-uuid" } ``` **Send Message**: ```json { "type": "message", "room_id": "room-uuid", "content": "Hello!", "message_type": "text" } ``` **Typing Indicator**: ```json { "type": "typing_start", "room_id": "room-uuid" } ``` #### Server → Client **New Message**: ```json { "type": "message", "room_id": "room-uuid", "message": { "id": "message-uuid", "sender": { /* user object */ }, "content": "Hello!", "created_at": "2025-11-02T14:30:00Z" } } ``` **User Joined**: ```json { "type": "user_joined", "room_id": "room-uuid", "user": { /* user object */ } } ``` **User Left**: ```json { "type": "user_left", "room_id": "room-uuid", "user_id": "uuid" } ``` **Typing Indicator**: ```json { "type": "typing", "room_id": "room-uuid", "user": { /* user object */ }, "is_typing": true } ``` **Presence Update**: ```json { "type": "presence", "user_id": "uuid", "status": "online", "last_seen_at": "2025-11-02T14:30:00Z" } ``` ### 8.3 Error Handling **Error Message**: ```json { "type": "error", "error": { "code": 1002, "message": "Invalid token" } } ``` ### 8.4 Heartbeat **Client sends**: ```json { "type": "ping" } ``` **Server responds**: ```json { "type": "pong" } ``` Interval: Every 30 seconds ## 9. GRPC APIS ### 9.1 Service: StreamService **Proto Definition**: ```protobuf syntax = "proto3"; package veza.stream.v1; service StreamService { rpc GetStreamURL(GetStreamURLRequest) returns (GetStreamURLResponse); rpc RecordPlayback(RecordPlaybackRequest) returns (RecordPlaybackResponse); rpc GetWaveform(GetWaveformRequest) returns (GetWaveformResponse); } message GetStreamURLRequest { string track_id = 1; string user_id = 2; int32 bitrate = 3; // optional, default 320 } message GetStreamURLResponse { string stream_url = 1; int32 bitrate = 2; string format = 3; int64 expires_at = 4; } ``` ### 9.2 Service: ChatService ```protobuf service ChatService { rpc SendMessage(SendMessageRequest) returns (SendMessageResponse); rpc GetMessages(GetMessagesRequest) returns (stream Message); rpc GetRoomPresence(GetRoomPresenceRequest) returns (GetRoomPresenceResponse); } ``` *[Additional gRPC services defined for inter-service communication]* ## 10. OPENAPI 3.0 SPECIFICATION ### 10.1 Metadata ```yaml openapi: 3.0.3 info: title: Veza API version: 1.0.0 description: | Veza platform API - Collaborative audio streaming, marketplace, and social network. **Authentication**: JWT Bearer token in `Authorization` header. **Rate Limiting**: Varies by endpoint (see headers). **Support**: api@veza.io contact: name: Veza API Support email: api@veza.io url: https://docs.veza.io license: name: Proprietary servers: - url: https://api.veza.io/api/v1 description: Production - url: https://staging-api.veza.io/api/v1 description: Staging - url: http://localhost:8080/api/v1 description: Local Development ``` ### 10.2 Security Schemes ```yaml components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT description: JWT access token obtained from /auth/login ``` ### 10.3 Common Schemas ```yaml components: schemas: UUID: type: string format: uuid example: "550e8400-e29b-41d4-a716-446655440000" Timestamp: type: string format: date-time example: "2025-11-02T14:30:00Z" Error: type: object required: - code - message properties: code: type: integer example: 1001 message: type: string example: "Token expired" details: type: array items: type: object properties: field: type: string message: type: string request_id: $ref: '#/components/schemas/UUID' timestamp: $ref: '#/components/schemas/Timestamp' Pagination: type: object properties: next_cursor: type: string nullable: true has_more: type: boolean limit: type: integer ``` ### 10.4 Example Endpoint Definition ```yaml paths: /tracks: get: summary: List tracks description: Get a paginated list of public tracks operationId: listTracks tags: - Tracks parameters: - name: limit in: query schema: type: integer default: 20 minimum: 1 maximum: 100 - name: cursor in: query schema: type: string - name: genre in: query schema: type: string - name: sort in: query schema: type: string default: "-created_at" responses: '200': description: Success content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Track' pagination: $ref: '#/components/schemas/Pagination' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/Error' post: summary: Upload track description: Upload a new audio track operationId: createTrack tags: - Tracks security: - BearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: - title - file properties: title: type: string minLength: 1 maxLength: 255 artist: type: string maxLength: 255 genre: type: string file: type: string format: binary cover_art: type: string format: binary responses: '201': description: Created content: application/json: schema: $ref: '#/components/schemas/Track' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' ``` *[Full OpenAPI 3.0 spec with all 500+ endpoints would be ~5,000 lines - included in separate YAML file]* ## ✅ CHECKLIST DE VALIDATION ### API Completeness - [ ] 500+ endpoints documentĂ©s pour tous les modules - [ ] Request/Response schemas complets - [ ] Authentication flows documentĂ©s - [ ] Error codes standardisĂ©s (1000-9999) - [ ] WebSocket protocol spĂ©cifiĂ© - [ ] gRPC services dĂ©finis ### Consistency - [ ] Naming conventions respectĂ©es (snake_case, plural resources) - [ ] HTTP methods utilisĂ©s correctement - [ ] Dates format ISO 8601 - [ ] UUIDs pour tous les IDs - [ ] Pagination cohĂ©rente (cursor-based) ### Security - [ ] JWT authentication implĂ©mentĂ©e - [ ] Rate limiting sur tous les endpoints - [ ] Permission checks documentĂ©s - [ ] Sensitive data jamais en query params ### Performance - [ ] Pagination obligatoire pour collections - [ ] Field selection supportĂ©e - [ ] Caching headers dĂ©finis - [ ] Compression activĂ©e (gzip) ## 📊 MÉTRIQUES DE SUCCÈS ### Performance Targets - **API Response Time p95**: < 100ms - **API Response Time p99**: < 500ms - **Throughput**: 10,000 req/s - **Availability**: 99.95% ### Developer Experience - **Time to First API Call**: < 5 minutes - **Documentation Completeness**: 100% - **API Error Rate**: < 0.1% - **Breaking Changes**: 0 in v1 ## 🔄 HISTORIQUE DES VERSIONS | Version | Date | Changements | |---------|------|-------------| | 1.0.0 | 2025-11-02 | Version initiale - API REST complĂšte | --- ## ⚠ AVERTISSEMENT **CETTE SPÉCIFICATION EST IMMUABLE** L'API v1 dĂ©finie ici est **VERROUILLÉE**. Toute modification nĂ©cessite: 1. **RFC API Change** avec impact analysis 2. **Backward compatibility** garantie 3. **Deprecation notice** (6 mois minimum) 4. **Migration guide** pour clients existants 5. **Approbation CTO** **Breaking changes INTERDITS en v1** - CrĂ©er v2 si nĂ©cessaire. --- **Document créé par**: API Team + Architecture **Date de crĂ©ation**: 2025-11-02 **Prochaine rĂ©vision**: Phase 4 (Q3 2026) **PropriĂ©taire**: Lead Backend Engineer **Statut**: ✅ **APPROUVÉ ET VERROUILLÉ**