veza/veza-docs/ORIGIN/ORIGIN_API_SPECIFICATION.md
2026-03-05 19:22:31 +01:00

61 KiB

ORIGIN_API_SPECIFICATION.md

📋 RÉSUMÉ EXÉCUTIF

Ce document définit la spécification complète des APIs de la plateforme Veza, une plateforme audio open source et éthique pour musiciens indépendants. Il documente les endpoints REST, événements WebSocket, et services gRPC avec leurs schémas de requête/réponse, codes d'erreur standardisés, authentication flows, rate limiting transparent, et versioning explicite. L'API suit les principes REST/RESTful, utilise JSON comme format d'échange ouvert (aucun vendor lock-in), et implémente OAuth 2.0 + JWT pour l'authentification.

Principes éthiques de l'API : aucune donnée comportementale dans les réponses, découverte basée sur des règles déclaratives (pas de ML/IA), pagination toujours disponible (pas de lock-in), portabilité complète des données, et rate limits publiquement documentés.

Exclusions éthiques : aucun endpoint d'IA/ML (mastering, séparation de stems, détection de genre, recommandations ML, content ID, auto-tagging, synthèse vocale, transcription), aucun endpoint blockchain/NFT/crypto (minting, smart contracts, tokens, staking, DAO, IPFS, wallet), aucune gamification addictive (XP, niveaux, achievements basés sur l'engagement, leaderboards, streaks).

🎯 OBJECTIFS

Objectif Principal

Définir une API complète, cohérente, documentée, éthique et ouverte qui servira de contrat entre frontend/backend/mobile, en respectant la souveraineté des utilisateurs sur leurs données et leur attention.

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) via des formats ouverts
  • Garantir la scalabilité (rate limiting transparent, caching, pagination obligatoire)
  • Supporter le versioning explicite (v1 stable, v2 pour évolutions, politique de dépréciation longue)
  • Garantir la portabilité des données (export complet pour chaque utilisateur)
  • Exclure toute collecte de données comportementales à des fins de profilage

📖 TABLE DES MATIÈRES

  1. Design Principles
  2. Authentication & Authorization
  3. Common Patterns
  4. Error Handling
  5. Rate Limiting
  6. Versioning
  7. REST API Endpoints
  8. WebSocket APIs
  9. gRPC APIs
  10. OpenAPI 3.0 Specification
  11. API Éthique
  12. Exclusions et Raisons Éthiques

🔒 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: 2026-03-04T14:30:00Z)
  5. IDs DOIVENT être UUID v4 (format: 550e8400-e29b-41d4-a716-446655440000)
  6. Pagination OBLIGATOIRE pour collections (cursor-based par défaut) — aucun endpoint ne force la consommation continue
  7. Rate limiting OBLIGATOIRE et PUBLIC (headers: X-RateLimit-*, documentation des limites accessible sans authentification)
  8. Authentication JWT dans header Authorization: Bearer {token}
  9. Error codes STANDARDISÉS (range 1000-9999, voir section 4) avec messages explicites et header Retry-After systématique sur 429
  10. Breaking changes INTERDITS dans v1 (créer v2 si nécessaire, politique de dépréciation ≥ 12 mois)
  11. AUCUNE donnée comportementale dans les réponses API (pas de tracking de scroll, temps de lecture, patterns de navigation)
  12. AUCUN endpoint ML/IA, blockchain/NFT, ou gamification addictive (voir section 12)
  13. Portabilité des données OBLIGATOIRE — endpoint d'export complet pour chaque utilisateur
  14. Format ouvert JSON — aucun format propriétaire, aucun vendor lock-in

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 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):

// 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)
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

Politique de transparence : tous les rate limits sont publiquement documentés et accessibles sans authentification via GET /api/v1/rate-limits. Les messages d'erreur 429 incluent systématiquement le header Retry-After avec le nombre de secondes avant réinitialisation.

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
Export 3 requests 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.",
    "retry_after_seconds": 1800
  }
}

5.3 Rate Limit Documentation Endpoint

GET /api/v1/rate-limits

Description: Documentation publique de tous les rate limits (aucune authentification requise).

Response (200 OK):

{
  "rate_limits": [
    {
      "endpoint_type": "authentication",
      "limit": 10,
      "window_seconds": 60,
      "description": "Login, register, password reset"
    },
    {
      "endpoint_type": "read",
      "limit": 1000,
      "window_seconds": 3600,
      "description": "GET requests on all resources"
    },
    {
      "endpoint_type": "write",
      "limit": 100,
      "window_seconds": 3600,
      "description": "POST, PUT, PATCH requests"
    },
    {
      "endpoint_type": "upload",
      "limit": 10,
      "window_seconds": 3600,
      "description": "File uploads (audio, images)"
    },
    {
      "endpoint_type": "search",
      "limit": 500,
      "window_seconds": 3600,
      "description": "Search queries"
    },
    {
      "endpoint_type": "streaming",
      "limit": 10000,
      "window_seconds": 86400,
      "description": "Stream plays per day"
    },
    {
      "endpoint_type": "export",
      "limit": 3,
      "window_seconds": 86400,
      "description": "Data export requests per day"
    }
  ],
  "headers_documentation": {
    "X-RateLimit-Limit": "Maximum requests allowed in window",
    "X-RateLimit-Remaining": "Remaining requests in current window",
    "X-RateLimit-Reset": "Unix timestamp when window resets",
    "X-RateLimit-Window": "Window duration in seconds",
    "Retry-After": "Seconds to wait before retrying (on 429 responses)"
  }
}

5.4 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:

{
  "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 UUID
  • include (query, optional) - Related resources (profile,stats)

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
  },
  "is_verified": true,
  "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 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):

{
  "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 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):

{
  "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 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:

{
  "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 category
  • price_min, price_max (query, optional) - Price range
  • genre (query, optional) - Filter by genre
  • sort (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


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):

{
  "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: Statistiques Créateur (Analytics éthiques)

Principe éthique : seules les statistiques agrégées et anonymisées sont disponibles. Aucune donnée comportementale individuelle (temps de lecture, scroll, patterns de navigation) n'est collectée ni exposée. Les créateurs accèdent uniquement aux compteurs agrégés de leurs propres contenus.

GET /api/v1/analytics/tracks/{id}

Description: Statistiques agrégées d'un track (réservé au propriétaire).

Headers: Authorization: Bearer {token}

Permissions: Track owner or admin

Response (200 OK):

{
  "track_id": "uuid",
  "plays_total": 12500,
  "likes_total": 850,
  "comments_total": 42,
  "plays_by_day": [
    { "date": "2026-03-01", "plays": 450 },
    { "date": "2026-03-02", "plays": 520 }
  ]
}

Données exclues volontairement : géolocalisation par pays, données démographiques, user agents, referrers, durée de lecture individuelle, taux de complétion. Ces données ne sont ni collectées ni stockées.


GET /api/v1/analytics/summary

Description: Résumé global des statistiques du créateur authentifié.

Headers: Authorization: Bearer {token}

Permissions: creator, admin

Response (200 OK):

{
  "total_tracks": 85,
  "total_plays": 125000,
  "total_likes": 8500,
  "total_comments": 420,
  "plays_last_30_days": 15000,
  "top_tracks": [
    {
      "track_id": "uuid",
      "title": "Midnight Dreams",
      "plays": 12500,
      "likes": 850
    }
  ]
}

7.9 Module: Découverte Éthique

Principe : la découverte est basée sur des règles déclaratives, des tags/genres déclarés par les créateurs, et le graphe social opt-in. Aucun algorithme de recommandation ML/IA, aucun profilage comportemental.

GET /api/v1/discover/genres

Description: Découverte par genres et tags déclarés. Retourne les tracks publics correspondant aux genres/tags demandés, triés chronologiquement (plus récents en premier).

Parameters:

  • genres (query, required) - Genres à découvrir, séparés par virgules (electronic,house,jazz)
  • tags (query, optional) - Tags supplémentaires (ambient,chill)
  • limit (query, optional, default=20) - Page size
  • cursor (query, optional) - Pagination cursor
  • sort (query, optional, default=-published_at) - Tri (-published_at, title, -like_count)

Response (200 OK):

{
  "data": [
    {
      "id": "track-uuid",
      "title": "Midnight Dreams",
      "artist": "DJ Nova",
      "genre": "Electronic",
      "tags": ["ambient", "chill"],
      "duration": 245,
      "cover_art_url": "https://cdn.veza.io/covers/...",
      "creator": {
        "id": "creator-uuid",
        "username": "djnova",
        "avatar_url": "https://..."
      },
      "play_count": 12500,
      "like_count": 850,
      "published_at": "2026-03-01T10:00:00Z"
    }
  ],
  "filters_applied": {
    "genres": ["electronic"],
    "tags": [],
    "sort": "-published_at"
  },
  "pagination": {
    "next_cursor": "eyJpZCI6IjY2MWU5NTExIn0",
    "has_more": true,
    "limit": 20
  }
}

GET /api/v1/discover/editorial

Description: Playlists éditorialisées par l'équipe ou des curateurs vérifiés. Curation humaine uniquement, aucune automatisation algorithmique.

Parameters:

  • limit (query, optional, default=10)
  • cursor (query, optional)
  • genre (query, optional) - Filtrer par genre

Response (200 OK):

{
  "data": [
    {
      "id": "playlist-uuid",
      "name": "Sélection de la semaine — Électronique",
      "description": "Les coups de cœur de l'équipe éditoriale",
      "curator": {
        "id": "curator-uuid",
        "username": "veza_editorial",
        "is_verified": true
      },
      "track_count": 12,
      "cover_art_url": "https://cdn.veza.io/editorial/...",
      "published_at": "2026-03-01T08:00:00Z"
    }
  ],
  "pagination": { "next_cursor": "...", "has_more": true, "limit": 10 }
}

GET /api/v1/discover/social

Description: Découverte par graphe social (opt-in). Retourne les tracks récemment écoutés ou likés par les contacts de l'utilisateur authentifié, uniquement si ces contacts ont activé le partage d'écoute.

Headers: Authorization: Bearer {token}

Parameters:

  • limit (query, optional, default=20)
  • cursor (query, optional)

Response (200 OK):

{
  "data": [
    {
      "track": {
        "id": "track-uuid",
        "title": "Summer Vibes",
        "artist": "johndoe",
        "genre": "House",
        "cover_art_url": "https://..."
      },
      "shared_by": [
        {
          "user_id": "contact-uuid",
          "username": "jane_smith",
          "action": "liked",
          "action_at": "2026-03-02T15:00:00Z"
        }
      ]
    }
  ],
  "opt_in_notice": "Seuls les contacts ayant activé le partage d'écoute apparaissent ici.",
  "pagination": { "next_cursor": "...", "has_more": true, "limit": 20 }
}

Errors:

  • 401 - Non authentifié (1002)

GET /api/v1/discover/new

Description: Nouveaux tracks dans les genres suivis par l'utilisateur, triés chronologiquement. Aucune pondération algorithmique — ordre strictement chronologique inversé.

Headers: Authorization: Bearer {token}

Parameters:

  • limit (query, optional, default=20)
  • cursor (query, optional)

Response (200 OK):

{
  "data": [
    {
      "id": "track-uuid",
      "title": "Fresh Beat",
      "artist": "producer_x",
      "genre": "Electronic",
      "published_at": "2026-03-04T09:00:00Z",
      "creator": {
        "id": "creator-uuid",
        "username": "producer_x"
      }
    }
  ],
  "followed_genres": ["electronic", "house", "jazz"],
  "pagination": { "next_cursor": "...", "has_more": true, "limit": 20 }
}

GET /api/v1/discover/nearby

Description: Découverte par proximité géographique (optionnel, opt-in). Retourne les créateurs et tracks publiés par des artistes proches de la localisation déclarée de l'utilisateur. La localisation est basée sur la ville/région déclarée dans le profil, pas de géolocalisation temps-réel.

Headers: Authorization: Bearer {token}

Parameters:

  • radius_km (query, optional, default=50) - Rayon de recherche en km
  • limit (query, optional, default=20)
  • cursor (query, optional)

Response (200 OK):

{
  "data": [
    {
      "creator": {
        "id": "creator-uuid",
        "username": "local_artist",
        "display_name": "Local Artist",
        "location": "Paris, France"
      },
      "recent_tracks": [
        {
          "id": "track-uuid",
          "title": "Paris Nights",
          "published_at": "2026-03-03T20:00:00Z"
        }
      ]
    }
  ],
  "search_location": "Paris, France",
  "radius_km": 50,
  "pagination": { "next_cursor": "...", "has_more": true, "limit": 20 }
}

Errors:

  • 400 - Localisation non renseignée dans le profil (2001)

PUT /api/v1/discover/preferences

Description: Définir les préférences de découverte de l'utilisateur (genres suivis, opt-in social, opt-in proximité).

Headers: Authorization: Bearer {token}

Request:

{
  "followed_genres": ["electronic", "house", "jazz", "hip-hop"],
  "social_sharing_enabled": true,
  "nearby_discovery_enabled": true
}

Response (200 OK):

{
  "followed_genres": ["electronic", "house", "jazz", "hip-hop"],
  "social_sharing_enabled": true,
  "nearby_discovery_enabled": true,
  "updated_at": "2026-03-04T14:30:00Z"
}

7.10 Module: Portabilité des Données

Principe éthique : tout utilisateur peut exporter l'intégralité de ses données à tout moment, dans un format ouvert et documenté. Aucune rétention artificielle.

POST /api/v1/export

Description: Demander un export complet des données de l'utilisateur (RGPD Art. 20). L'export est préparé de manière asynchrone et notifié par email.

Headers: Authorization: Bearer {token}

Request:

{
  "format": "json",
  "include": ["profile", "tracks", "playlists", "likes", "comments", "messages", "orders", "preferences"]
}

Response (202 Accepted):

{
  "export_id": "export-uuid",
  "status": "processing",
  "estimated_completion": "2026-03-04T15:00:00Z",
  "message": "Votre export est en cours de préparation. Vous recevrez un email avec le lien de téléchargement."
}

GET /api/v1/export/{id}

Description: Vérifier le statut d'un export.

Headers: Authorization: Bearer {token}

Response (200 OK):

{
  "export_id": "export-uuid",
  "status": "completed",
  "download_url": "https://cdn.veza.io/exports/...",
  "download_expires_at": "2026-03-11T15:00:00Z",
  "file_size_bytes": 15728640,
  "created_at": "2026-03-04T14:30:00Z",
  "completed_at": "2026-03-04T14:45:00Z"
}

DELETE /api/v1/account

Description: Supprimer définitivement le compte et toutes les données associées (RGPD Art. 17 — droit à l'effacement). Opération irréversible après période de grâce de 30 jours.

Headers: Authorization: Bearer {token}

Request:

{
  "confirmation": "DELETE_MY_ACCOUNT",
  "password": "current_password"
}

Response (200 OK):

{
  "message": "Votre compte sera définitivement supprimé dans 30 jours. Reconnectez-vous avant cette date pour annuler.",
  "deletion_scheduled_at": "2026-04-03T14:30:00Z"
}

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: 2.0.0
  description: |
    Veza platform API — Open source ethical audio platform for independent musicians.
    
    **Authentication**: JWT Bearer token in `Authorization` header.
    
    **Rate Limiting**: Publicly documented. See `GET /api/v1/rate-limits`.
    
    **Ethical principles**: No behavioral data, no ML/AI recommendations, no blockchain/NFT,
    no addictive gamification. Full data portability.
    
    **Support**: api@veza.io    
  contact:
    name: Veza API Support
    email: api@veza.io
    url: https://docs.veza.io
  license:
    name: AGPL-3.0
    url: https://www.gnu.org/licenses/agpl-3.0.html
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 included in separate YAML file]

11. API ÉTHIQUE

11.1 Aucune Donnée Comportementale dans les Réponses

Les réponses API ne contiennent jamais :

  • De données de tracking utilisateur (scroll depth, mouse movements, session duration)
  • De scores de recommandation ou poids algorithmiques
  • De profils comportementaux dérivés
  • D'identifiants de tracking tiers (pixels, fingerprints)
  • De données permettant le profilage publicitaire

Les seules données retournées sont celles explicitement demandées par l'utilisateur ou le créateur, dans le cadre de l'utilisation directe de la plateforme.

11.2 Pagination Toujours Disponible

Tous les endpoints retournant des collections supportent la pagination :

  • Cursor-based (par défaut) ou offset-based
  • Aucun endpoint ne force une consommation continue (pas de scroll infini obligatoire côté API)
  • Le client est libre de consommer les données à son rythme
  • Les paramètres limit et cursor/page sont toujours disponibles

11.3 Format Ouvert — Aucun Vendor Lock-in

  • Format unique : JSON (application/json) pour toutes les réponses REST
  • Pas de format propriétaire : aucun SDK obligatoire, aucun protocole fermé
  • Documentation ouverte : OpenAPI 3.0, libre d'accès
  • Export standard : les données utilisateur sont exportables en JSON standard (voir section 7.10)
  • Interopérabilité : tout client HTTP standard peut consommer l'API

11.4 Versioning Explicite avec Politique de Dépréciation Longue

  • Versioning sémantique dans l'URL (/api/v1/, /api/v2/)
  • Politique de dépréciation : minimum 12 mois entre l'annonce de dépréciation et la suppression
  • Header de dépréciation : Deprecation: true + Sunset: <date ISO 8601> sur les endpoints dépréciés
  • Guide de migration publié pour chaque changement majeur
  • Aucun breaking change dans une version stable sans nouvelle version majeure

11.5 Portabilité des Données

  • Tout utilisateur peut exporter l'intégralité de ses données à tout moment (POST /api/v1/export)
  • Format d'export : JSON standard, documenté, lisible par des outils tiers
  • Droit à l'effacement : suppression complète du compte et des données (DELETE /api/v1/account)
  • Conformité RGPD (Art. 17 droit à l'effacement, Art. 20 portabilité)

12. EXCLUSIONS ET RAISONS ÉTHIQUES

Cette section documente les catégories d'endpoints volontairement exclues de l'API Veza, avec les raisons éthiques associées.

12.1 Endpoints IA/ML — EXCLUS

Endpoint exclu Raison éthique
POST /api/v1/tracks/{id}/master (mastering automatique) Remplace le travail créatif humain, dévalorise l'ingénierie du son
POST /api/v1/tracks/{id}/stems (séparation de stems) Risque d'utilisation pour plagiat, extraction non consentie
GET /api/v1/tracks/{id}/genre-detect (détection de genre ML) Les genres sont déclarés par les créateurs, pas imposés par un algorithme
GET /api/v1/recommendations (recommandations ML) Crée des bulles de filtre, favorise l'engagement addictif sur la diversité
POST /api/v1/tracks/{id}/content-id (content ID ML) Système de surveillance automatisée, risque de faux positifs avec censure
POST /api/v1/tracks/{id}/auto-tag (auto-tagging ML) Les tags sont la responsabilité des créateurs, pas d'une machine
GET /api/v1/tracks/{id}/similar (similarité ML) Favorise l'homogénéité, réduit la diversité musicale
POST /api/v1/voice/synthesize (synthèse vocale) Risque d'usurpation d'identité vocale, deepfakes audio
POST /api/v1/tracks/{id}/transcribe (transcription lyrics ML) Les paroles sont fournies par les artistes, respect du droit d'auteur

Alternative éthique : découverte basée sur les genres/tags déclarés par les créateurs, curation éditoriale humaine, et graphe social opt-in (voir section 7.9).

12.2 Endpoints Blockchain/NFT/Crypto — EXCLUS

Endpoint exclu Raison éthique
POST /api/v1/nft/mint (minting NFT) Spéculation financière sur l'art, impact environnemental
GET /api/v1/contracts/{id} (smart contracts) Complexité inutile, exclusion des artistes non-technophiles
POST /api/v1/tokens/transfer (transfert tokens) Financiarisation des interactions sociales
POST /api/v1/staking/deposit (staking) Mécanisme spéculatif incompatible avec une plateforme artistique
GET /api/v1/dao/proposals (DAO governance) Gouvernance ploutocratique (pouvoir proportionnel aux tokens détenus)
POST /api/v1/ipfs/pin (IPFS storage) Fausse décentralisation, complexité pour les utilisateurs
POST /api/v1/wallet/connect (wallet crypto) Barrière à l'entrée, exclusion économique

Alternative éthique : paiements classiques (Stripe), licence créative déclarée par l'artiste, gouvernance communautaire transparente sans tokens.

12.3 Endpoints Gamification Addictive — EXCLUS

Endpoint exclu Raison éthique
GET /api/v1/users/{id}/xp (points d'expérience) Conditionne l'engagement par la récompense, pas par l'intérêt
GET /api/v1/users/{id}/level (niveaux) Hiérarchise artificiellement les utilisateurs
GET /api/v1/users/{id}/achievements (achievements engagement) Oriente le comportement vers des métriques, pas vers la création
GET /api/v1/leaderboards (classements) Compétition artificielle, pression sociale, anxiété de performance
GET /api/v1/users/{id}/streaks (séries consécutives) Manipulation psychologique (aversion à la perte), engagement forcé
POST /api/v1/rewards/claim (réclamation récompenses) Boucle de renforcement addictive

Alternative éthique : le statut is_verified pour les créateurs vérifiés (basé sur l'identité, pas sur l'activité), statistiques agrégées transparentes pour les créateurs (section 7.8).

CHECKLIST DE VALIDATION

API Completeness

  • Endpoints documentés pour tous les modules actifs
  • Request/Response schemas complets
  • Authentication flows documentés
  • Error codes standardisés (1000-9999)
  • WebSocket protocol spécifié
  • gRPC services définis
  • Endpoints de découverte éthique documentés
  • Endpoints de portabilité des données documentés

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
  • Rate limits publiquement documentés (GET /api/v1/rate-limits)
  • Permission checks documentés
  • Sensitive data jamais en query params
  • Header Retry-After systématique sur 429

Éthique

  • Aucune donnée comportementale dans les réponses
  • Pagination disponible sur toutes les collections
  • Format ouvert JSON, aucun vendor lock-in
  • Portabilité des données (export complet)
  • Droit à l'effacement implémenté
  • Exclusions ML/IA, blockchain/NFT, gamification documentées
  • Découverte basée sur règles, pas sur ML

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
2.0.0 2026-03-04 Révision éthique — Suppression endpoints ML/IA, blockchain/NFT, gamification addictive. Ajout découverte éthique (genres, éditorial, social, chronologique, proximité). Portabilité des données (export, effacement). Rate limits publics. Section API Éthique et Exclusions documentées. Licence open source.

⚠️ AVERTISSEMENT

CETTE SPÉCIFICATION SUIT LE VERSIONING SÉMANTIQUE

Toute modification nécessite :

  1. RFC API Change avec impact analysis
  2. Backward compatibility garantie au sein d'une version majeure
  3. Deprecation notice (12 mois minimum)
  4. Migration guide pour clients existants
  5. Revue éthique — vérification que le changement respecte les principes de la section 11

Breaking changes INTERDITS dans une version stable — Créer une nouvelle version majeure si nécessaire.


Document créé par : API Team + Architecture
Date de création : 2025-11-02
Révision éthique : 2026-03-04 (v2.0.0)
Prochaine révision : Q3 2026
Propriétaire : Lead Backend Engineer
Licence : Open Source

Statut : APPROUVÉ — RÉVISION ÉTHIQUE v2.0.0