Backend Go: - Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN. - Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError). - Sécurisation de config.go, CORS, statuts de santé et monitoring. - Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles). - Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés. - Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*. Chat server (Rust): - Refonte du pipeline JWT + sécurité, audit et rate limiting avancé. - Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing). - Nettoyage des panics, gestion d’erreurs robuste, logs structurés. - Migrations chat alignées sur le schéma UUID et nouvelles features. Stream server (Rust): - Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core. - Transactions P0 pour les jobs et segments, garanties d’atomicité. - Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION). Documentation & audits: - TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services. - Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3). - Scripts de reset et de cleanup pour la lab DB et la V1. Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
42 KiB
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
- Design Principles
- Authentication & Authorization
- Common Patterns
- Error Handling
- Rate Limiting
- Versioning
- REST API Endpoints
- WebSocket APIs
- gRPC APIs
- OpenAPI 3.0 Specification
🔒 RÈGLES IMMUABLES
- URLs DOIVENT suivre le pattern
/api/v{version}/{resource} - HTTP methods DOIVENT respecter REST (GET=read, POST=create, PUT=replace, PATCH=update, DELETE=delete)
- Responses DOIVENT être JSON avec
Content-Type: application/json - Dates DOIVENT être ISO 8601 (format:
2025-11-02T14:30:00Z) - IDs DOIVENT être UUID v4 (format:
550e8400-e29b-41d4-a716-446655440000) - Pagination OBLIGATOIRE pour collections (cursor-based par défaut)
- Rate limiting OBLIGATOIRE (headers:
X-RateLimit-*) - Authentication JWT dans header
Authorization: Bearer {token} - Error codes STANDARDISÉS (range 1000-9999, voir section 4)
- 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:
{
"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:
{
"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:
{
"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 subscribermoderator- Community moderatoradmin- 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):
// 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
{
"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
- Announce deprecation (6 months notice minimum)
- Add header
Deprecation: trueto deprecated endpoints - Provide migration guide in docs
- Monitor usage of deprecated endpoints
- Remove in next major version
7. REST API ENDPOINTS
7.1 Module: Authentication
POST /api/v1/auth/register
Description: Register new user account.
Request:
{
"email": "user@example.com",
"username": "johndoe",
"password": "SecurePass123!",
"first_name": "John",
"last_name": "Doe"
}
Response (201 Created):
{
"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:
{
"email": "user@example.com",
"password": "SecurePass123!"
}
Response (200 OK):
{
"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:
{
"refresh_token": "dGhpc2lzYXJlZnJlc2h0b2tlbg..."
}
Response (200 OK):
{
"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:
{
"email": "user@example.com"
}
Response (200 OK):
{
"message": "Password reset email sent if account exists."
}
POST /api/v1/auth/reset-password
Description: Reset password with token.
Request:
{
"token": "reset_token_from_email",
"new_password": "NewSecurePass456!"
}
Response (200 OK):
{
"message": "Password reset successful."
}
Errors:
400- Invalid or expired token (1002)
POST /api/v1/auth/verify-email
Description: Verify email with token.
Request:
{
"token": "email_verification_token"
}
Response (200 OK):
{
"message": "Email verified successfully."
}
GET /api/v1/auth/me
Description: Get current authenticated user.
Headers: Authorization: Bearer {token}
Response (200 OK):
{
"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 UUIDinclude(query, optional) - Related resources (profile,stats,badges)
Response (200 OK):
{
"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:
{
"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 UUIDlimit(query, optional, default=20) - Page sizecursor(query, optional) - Pagination cursorsort(query, optional, default=-created_at) - Sort fieldvisibility(query, optional) - Filter by visibility
Response (200 OK):
{
"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):
{
"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):
{
"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:
{
"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 sizecursor(query, optional) - Pagination cursorgenre(query, optional) - Filter by genrebpm_min,bpm_max(query, optional) - BPM rangeduration_min,duration_max(query, optional) - Duration range (seconds)sort(query, optional, default=-created_at) - Sort fieldsearch(query, optional) - Full-text search
Response (200 OK):
{
"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):
{
"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 UUIDinclude(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:
{
"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):
{
"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):
{
"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):
{
"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):
{
"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:
{
"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:
{
"name": "My Favorites",
"description": "Best tracks of 2025",
"visibility": "public",
"is_collaborative": false
}
Response (201 Created):
{
"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):
{
"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:
{
"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:
{
"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):
{
"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:
{
"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):
{
"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:
{
"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:
{
"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 categoryprice_min,price_max(query, optional) - Price rangegenre(query, optional) - Filter by genresort(query, optional) - Sort field
Response (200 OK):
{
"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:
{
"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:
{
"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):
{
"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:
{
"payment_method": "stripe",
"billing_email": "user@example.com",
"discount_code": "SUMMER25"
}
Response (201 Created):
{
"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 querytype(query, optional) - Filter by type (tracks,users,playlists,products)limit(query, optional, default=20)
Response (200 OK):
{
"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:
{
"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):
{
"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
{
"type": "auth",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response:
{
"type": "auth_success",
"user_id": "550e8400-e29b-41d4-a716-446655440000"
}
8.2 Message Types
Client → Server
Join Room:
{
"type": "join_room",
"room_id": "room-uuid"
}
Leave Room:
{
"type": "leave_room",
"room_id": "room-uuid"
}
Send Message:
{
"type": "message",
"room_id": "room-uuid",
"content": "Hello!",
"message_type": "text"
}
Typing Indicator:
{
"type": "typing_start",
"room_id": "room-uuid"
}
Server → Client
New Message:
{
"type": "message",
"room_id": "room-uuid",
"message": {
"id": "message-uuid",
"sender": { /* user object */ },
"content": "Hello!",
"created_at": "2025-11-02T14:30:00Z"
}
}
User Joined:
{
"type": "user_joined",
"room_id": "room-uuid",
"user": { /* user object */ }
}
User Left:
{
"type": "user_left",
"room_id": "room-uuid",
"user_id": "uuid"
}
Typing Indicator:
{
"type": "typing",
"room_id": "room-uuid",
"user": { /* user object */ },
"is_typing": true
}
Presence Update:
{
"type": "presence",
"user_id": "uuid",
"status": "online",
"last_seen_at": "2025-11-02T14:30:00Z"
}
8.3 Error Handling
Error Message:
{
"type": "error",
"error": {
"code": 1002,
"message": "Invalid token"
}
}
8.4 Heartbeat
Client sends:
{ "type": "ping" }
Server responds:
{ "type": "pong" }
Interval: Every 30 seconds
9. GRPC APIS
9.1 Service: StreamService
Proto Definition:
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
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
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
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: JWT access token obtained from /auth/login
10.3 Common Schemas
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
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:
- RFC API Change avec impact analysis
- Backward compatibility garantie
- Deprecation notice (6 mois minimum)
- Migration guide pour clients existants
- 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É