📡 Documentation API REST — Webradio Manager v2.14.0

Version : 2.8.0 | Base URL : http://localhost:5000 | Préfixe : /api/v1 | Format : JSON


Table des matières

  1. Authentification
  2. Utilisateurs
  3. Streaming
  4. Decks
  5. Mixer
  6. Playlist
  7. Playlists nommées
  8. Bibliothèque
  9. Scheduler
  10. Spots
  11. TTS (Text-to-Speech)
  12. Recherche
  13. Spotify
  14. Deezer
  15. YouTube
  16. Apple Music
  17. SoundCloud
  18. Scrobbler (Last.fm)
  19. Icecast
  20. Paramètres
  21. Préférences utilisateur (sessions)
  22. Upload
  23. Système de fichiers
  24. WebDAV
  25. Synchronisation réseau (FTP / SFTP / Samba)
  26. WebSocket
  27. Monitoring & Métriques
  28. HLS
  29. Modèles de données
  30. Codes d'erreur
  31. Versionnage & Rate Limiting
  32. Favoris
  33. Historique d'écoute
  34. Webradios et radios personnalisées
  35. Pistes en ligne, titre en cours, loudness
  36. Sauvegardes
  37. Scan asynchrone
  38. Planification de radios

1. Authentification

Préfixe : /api/v1/auth

Le système d'authentification utilise JWT (access + refresh tokens). Un compte admin par défaut est créé au premier démarrage : admin / admin.

POST /auth/login

Connexion utilisateur (limité à 5 tentatives/minute).

Body :

{
  "username": "admin",
  "password": "admin"
}

Champs optionnels pour la protection CAPTCHA : - captcha_token — token CAPTCHA (si activé) - session_id — ID de session CAPTCHA - captcha_answer — réponse au défi mathématique

Réponse (200) :

{
  "message": "Login successful",
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIs...",
  "user": {
    "id": 1,
    "username": "admin",
    "email": "admin@example.com",
    "role": "admin",
    "is_active": true
  }
}

Erreurs : - 400 — VALIDATION_ERROR / CAPTCHA_FAILED / MISSING_CREDENTIALS - 401 — INVALID_CREDENTIALS - 403 — ACCOUNT_DISABLED - 429 — TOO_MANY_ATTEMPTS (header Retry-After: 300)

POST /auth/logout

Déconnexion (invalide le refresh token).

Body : {} (vide)

POST /auth/refresh

Rafraîchit le token d'accès JWT.

Body :

{
  "refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}

Réponse (200) :

{
  "token": "eyJhbGciOiJIUzI1NiIs..."
}

GET /auth/me

Retourne les informations de l'utilisateur connecté.

Headers : Authorization: Bearer <token>

POST /auth/forgot-password

Demande de réinitialisation de mot de passe (envoie un email).

Body :

{
  "email": "user@example.com"
}

POST /auth/reset-password

Réinitialise le mot de passe avec un token.

Body :

{
  "token": "token-de-reinitialisation",
  "new_password": "nouveau_mot_de_passe"
}

GET /auth/health

Health check spécifique au module auth.


2. Utilisateurs

Préfixe : /api/v1/users

Gestion des utilisateurs (admin uniquement).

GET /users

Liste tous les utilisateurs.

Headers : Authorization: Bearer <admin_token>

Réponse (200) :

{
  "users": [
    {"id": 1, "username": "admin", "email": "admin@example.com", "role": "admin", "is_active": true}
  ]
}

GET /users/{user_id}

Récupère un utilisateur par son ID.

POST /users

Crée un nouvel utilisateur.

Body :

{
  "username": "dj1",
  "email": "dj1@example.com",
  "password": "motdepasse",
  "role": "dj"
}

Rôles valides : admin, dj, viewer

PUT /users/{user_id}

Met à jour un utilisateur.

Body : champs optionnels role, email, is_active

DELETE /users/{user_id}

Supprime un utilisateur. Impossible de se supprimer soi-même.

POST /users/{user_id}/reset-password

Réinitialise le mot de passe d'un utilisateur (admin).

Body : {"new_password": "nouveau_mdp"}

GET /users/{user_id}/permissions

Liste les permissions d'un utilisateur.

POST /users/{user_id}/permissions

Ajoute une permission.

Body : {"permission": "library.edit"}

DELETE /users/{user_id}/permissions/{perm_id}

Supprime une permission.

POST /users/register

Inscription publique (avec validation).

Body :

{
  "username": "nouveau",
  "email": "nouveau@example.com",
  "password": "motdepasse"
}

GET /auth/audit-logs

Journal d'audit des connexions (admin). Query : page, per_page, action, user_id


3. Streaming

Préfixe : /api/v1/streaming

GET /streaming/status

Retourne l'état actuel du stream.

Réponse (200) :

{
  "is_live": true,
  "bitrate": 128,
  "format": "mp3",
  "listeners": 5,
  "protocol": "icecast",
  "pid": 12345,
  "uptime": "01:23:45",
  "icecast_host": "localhost",
  "icecast_port": 8000
}

POST /streaming/start

Démarre le flux Icecast via FFmpeg.

Query : ?protocol=icecast|shoutcast|rtmp (optionnel)

Body (optionnel) : config override JSON

Réponse (200) :

{"success": true, "message": "Stream started", "pid": 12345}

POST /streaming/stop

Arrête le flux.

GET /streaming/protocol

Retourne le protocole de streaming actuel et les options disponibles.

POST /streaming/protocol

Change le protocole de streaming.

Body : {"protocol": "icecast"}

GET /streaming/hls

Retourne les informations de streaming HLS (URL de la playlist m3u8).

GET /streaming/mounts

Liste les points de montage Icecast configurés.

POST /streaming/mounts

Met à jour les points de montage.


4. Decks

Préfixe : /api/v1/decks

GET /decks

Retourne l'état des deux decks A et B.

Réponse (200) :

{
  "decks": {
    "A": {
      "deck": "A",
      "current_track_id": "abc123",
      "is_playing": true,
      "is_paused": false,
      "volume": 0.8,
      "speed": 1.0,
      "eq_low": 0.0,
      "eq_mid": 0.0,
      "eq_high": 0.0,
      "cue_position": 30.5,
      "loop_enabled": false,
      "playback_position": 45.2
    },
    "B": { "deck": "B", "is_playing": false, "volume": 0.8 }
  }
}

GET /decks/{A|B}

Retourne l'état d'un deck spécifique.

POST /decks/{A|B}/play

Démarre la lecture sur le deck.

POST /decks/{A|B}/pause

Met en pause le deck.

POST /decks/{A|B}/stop

Arrête la lecture.

POST /decks/{A|B}/clear

Vide le deck (décharge la piste).

POST /decks/{A|B}/cue

Définit un point cue.

Body : {"position": 30.5}

POST /decks/{A|B}/cue/jump

Saute au point cue.

POST /decks/{A|B}/loop

Définit une boucle.

Body :

{
  "enabled": true,
  "start": 10.0,
  "end": 45.0
}

POST /decks/{A|B}/volume

Règle le volume (0.0 à 1.0).

Body : {"volume": 0.75}

POST /decks/{A|B}/eq

Règle l'égaliseur 3 bandes (-1.0 à 1.0).

Body :

{
  "low": 0.3,
  "mid": 0.0,
  "high": -0.2
}

POST /decks/{A|B}/speed

Règle la vitesse/pitch (0.5 à 2.0).

Body : {"speed": 1.2}

POST /decks/{A|B}/load

Charge une piste sur le deck.

Body : {"track_id": "abc123"}


5. Mixer

Préfixe : /api/v1/mixer

GET /mixer

Retourne l'état complet du mixer.

Réponse (200) :

{
  "crossfader": {"position": 0.5},
  "master_volume": 0.8
}

POST /mixer/crossfader

Définit la position du crossfader. - 0.0 = 100% Deck A - 0.5 = 50% A + 50% B (centre) - 1.0 = 100% Deck B

Body : {"position": 0.3}

POST /mixer/master

Définit le volume master (0.0 à 1.0).

Body : {"volume": 0.8}


6. Playlist

Préfixe : /api/v1/playlist

GET /playlist

Liste la playlist (file d'attente active) avec pagination.

Query : page (défaut 1), per_page (défaut 50, max 200)

POST /playlist

Ajoute une piste à la playlist.

Body : {"track_id": "abc123"}

Options : - position (int) — insérer à une position spécifique - next (bool) — insérer en tête de file

DELETE /playlist/{track_id}

Retire une piste de la playlist.

POST /playlist/reorder

Réordonne la playlist.

Body : {"track_ids": [3, 1, 2]}

DELETE /playlist

Vide entièrement la playlist.

GET /playlist/next

Retourne la prochaine piste de la file d'attente.


7. Playlists nommées

Préfixe : /api/v1/playlists

GET /playlists

Liste toutes les playlists nommées.

POST /playlists

Crée une nouvelle playlist.

Body :

{
  "name": "Ma playlist jazz",
  "description": "Mes titres jazz préférés"
}

GET /playlists/{playlist_id}

Récupère les détails d'une playlist.

PUT /playlists/{playlist_id}

Met à jour le nom/description d'une playlist.

DELETE /playlists/{playlist_id}

Supprime une playlist.

GET /playlists/{playlist_id}/tracks

Liste les pistes d'une playlist.

POST /playlists/{playlist_id}/tracks

Ajoute des pistes à une playlist.

Body :

{
  "track_ids": ["abc123", "def456"],
  "position": 0
}

DELETE /playlists/{playlist_id}/tracks/{track_id}

Retire une piste d'une playlist.

DELETE /playlists/{playlist_id}/tracks

Retire plusieurs pistes d'une playlist (bulk).

Body : {"track_ids": [1, 2, 3]}

PUT /playlists/{playlist_id}/reorder

Réordonne les pistes d'une playlist.

Body : {"track_ids": [3, 1, 2]}

GET /playlists/{playlist_id}/export

Exporte une playlist au format M3U.


8. Bibliothèque

Préfixe : /api/v1/library

GET /library/tracks

Liste les pistes avec pagination, recherche, tri et filtres.

Query params :

Paramètre Type Défaut Description
page int 1 Numéro de page
per_page int 50 Éléments par page (max 200)
search string — Recherche par titre/artiste/album
sort string track_name Champ de tri
sort_dir string asc asc ou desc
genre string — Filtrer par genre
source string — Filtrer par source (local/spotify/deezer/youtube)

Réponse (200) :

{
  "tracks": [...],
  "total": 150,
  "page": 1,
  "per_page": 50,
  "total_pages": 3
}

POST /library/tracks

Ajoute une piste manuellement à la bibliothèque.

Body :

{
  "track_name": "Mon titre",
  "artist": "Mon artiste",
  "album": "Mon album",
  "genre": "Jazz",
  "file_path": "/path/to/file.mp3"
}

GET /library/tracks/{track_id}

Récupère une piste par son track_id (chaîne).

PUT /library/tracks/{track_id}

Édite les métadonnées d'une piste.

Body : champs optionnels track_name, artist, album, genre, bpm, year, rating

DELETE /library/tracks/{track_id}

Supprime une piste de la bibliothèque.

POST /library/scan

Scanne un dossier pour importer des fichiers audio.

Body :

{
  "path": "/chemin/vers/musique"
}

Si path est omis, utilise library.scan_paths ou library.path de la config.

Réponse (200) :

{
  "message": "Scan complete",
  "files_found": 120,
  "tracks_added": 115,
  "tracks_updated": 5,
  "errors": [],
  "scanned_path": "/home/user/Music"
}

Formats supportés : MP3, OGG, FLAC, WAV, M4A

GET /library/tracks/{track_id}/stream

Stream un fichier audio (pour lecture depuis la bibliothèque).

GET /library/tracks/{track_id}/cover

Sert la pochette d'une piste (image). Réponse (200) : image (JPG/PNG/WebP). 404 si pas de pochette.

PUT /library/tracks/{track_id}/cover

Définit la pochette d'une piste. Authentification requise (admin).

Option A — Upload multipart (fichier image) :

Content-Type: multipart/form-data
Champ : file (image/jpeg, image/png, image/webp, image/gif)

Option B — URL :

{ "cover_url": "https://example.com/cover.jpg" }

Réponse (200) :

{ "message": "Cover updated", "cover": "b6616a64-....png" }

POST /library/tracks/{track_id}/enrich

Enrichit les métadonnées d'une piste via MusicBrainz + 6 sources.

Réponse (200) :

{
  "message": "Enrichment complete",
  "metadata": {"musicbrainz": {...}, "cover_url": "..."}
}

POST /library/tracks/enrich-bulk

Enrichissement en masse de plusieurs pistes.

Body : {"track_ids": ["abc123", "def456"]}

POST /library/enrich-async

Lance un job d'enrichissement asynchrone.

Body : {"track_ids": ["abc123", "def456"]}

Réponse (201) : {"job_id": "uuid", "message": "Enrichment job started"}

GET /library/enrich-job/{job_id}

Vérifie l'état d'un job d'enrichissement.

Réponse (200) :

{
  "job_id": "uuid",
  "status": "running",
  "progress": 3,
  "total": 10
}

GET /library/tracks/{track_id}/similar

Trouve des pistes similaires (basé sur le genre et les tags).

GET /library/tracks/{track_id}/cover

Retourne la pochette d'album d'une piste.


9. Scheduler

Préfixe : /api/v1/scheduler

GET /scheduler/events

Liste les événements planifiés.

Query params : - enabled_only (bool) — filtrer les événements activés uniquement - recurrence (string) — filtrer par type de récurrence - from_time (ISO datetime) — filtrer à partir d'une date

Réponse (200) :

{
  "events": [...],
  "count": 5
}

POST /scheduler/events

Crée un événement planifié.

Body :

{
  "name": "Spot météo matin",
  "start_time": "2026-07-10T08:00:00",
  "track_id": 1,
  "spot_id": null,
  "recurrence": "daily",
  "priority": 1,
  "enabled": true
}

Récurrences valides : none, every_15min, every_30min, hourly, daily, weekly

Soit track_id soit spot_id doit être fourni (pas les deux).

PUT /scheduler/events/{event_id}

Met à jour un événement.

DELETE /scheduler/events/{event_id}

Supprime un événement.

GET /scheduler/next

Retourne le prochain événement planifié.


10. Spots

Préfixe : /api/v1/spots

GET /spots

Liste les spots générés (paginé, filtrable par type).

Query params : type (weather/promo/nextup/traffic/generic), page, per_page

Réponse (200) :

{
  "spots": [...],
  "count": 10,
  "total": 50,
  "page": 1,
  "per_page": 50,
  "pages": 1
}

POST /spots/generate

Génère un spot audio via TTS.

Body :

{
  "type": "promo",
  "text": "Bienvenue sur notre webradio !",
  "city": "Paris",
  "engine": "gtts"
}

GET /spots/{spot_id}

Détails d'un spot.

DELETE /spots/{spot_id}

Supprime un spot et son fichier audio associé.

POST /spots/bulk-delete

Supprime plusieurs spots en une fois.

Body : {"spot_ids": [1, 2, 3]}

POST /spots/weather

Génère un spot météo. Utilise Open-Meteo (gratuit).

Body :

{
  "city": "Paris",
  "engine": "gtts"
}

POST /spots/nextup

Génère une annonce « next up » (annonce du titre suivant).

Body :

{
  "track_name": "Bohemian Rhapsody",
  "artist": "Queen"
}

Types de spots disponibles :

Type Description
weather Bulletin météo (Open-Meteo, gratuit)
nextup Annonce du titre suivant
promo Spot promotionnel personnalisé
traffic Information trafic
generic Spot texte libre

11. TTS (Text-to-Speech)

Préfixe : /api/v1/tts

GET /tts/voices

Liste les voix TTS disponibles.

Réponse (200) :

{
  "voices": ["fr-FR", "en-US", "es-ES", ...],
  "engine": "gtts"
}

Moteurs supportés :

Moteur Type Format Prérequis
gTTS Online MP3 Connexion Internet
espeak Offline WAV Binaire espeak installé
fallback_silent Offline WAV Toujours disponible

12. Recherche

Préfixe : /api/v1

Recherche multi-plateformes (local + Spotify + Deezer + YouTube).

Query params :

Paramètre Type Défaut Description
q string requis Terme de recherche
source string all all, local, spotify, deezer, youtube
limit int 10 Nombre max de résultats (max 10)

Réponse (200) :

{
  "local": [...],
  "spotify": [...],
  "deezer": [...],
  "youtube": [...]
}

13. Spotify

Préfixe : /api/v1/spotify

GET /spotify/search

Recherche sur Spotify.

Query : q (requis), limit (défaut 5)

GET /spotify/search/artists

Recherche d'artistes sur Spotify.

Query : q (requis), limit (défaut 5)

GET /spotify/track/{track_id}

Récupère les infos d'une piste Spotify.

GET /spotify/recommendations

Recommandations basées sur des seeds.

Query : seed_artists, seed_tracks, seed_genres, limit

GET /spotify/playlists

Liste les playlists Spotify de l'utilisateur.

GET /spotify/playlist/{playlist_id}

Récupère les détails d'une playlist Spotify.

GET /spotify/playlist/{playlist_id}/tracks

Liste les pistes d'une playlist Spotify.

GET /spotify/player

Retourne la piste en cours de lecture sur Spotify.

POST /spotify/player/play

Lance la lecture sur l'appareil Spotify connecté.

Body : {"device_id": "...", "track_uri": "spotify:track:..."}

POST /spotify/player/pause

Met en pause le player Spotify.

POST /spotify/player/next

Piste suivante sur Spotify.

POST /spotify/player/previous

Piste précédente sur Spotify.

POST /spotify/player/volume

Règle le volume Spotify.

Body : {"volume_percent": 50}


14. Deezer

Préfixe : /api/v1/deezer

GET /deezer/search

Recherche sur Deezer.

Query : q (requis), limit (défaut 5)

GET /deezer/playlist/{playlist_id}

Récupère les détails d'une playlist Deezer.

GET /deezer/playlist/{playlist_id}/tracks

Liste les pistes d'une playlist Deezer.

GET /deezer/user/{user_id}/playlists

Liste les playlists d'un utilisateur Deezer.

GET /deezer/me

Retourne les infos de l'utilisateur Deezer connecté.

GET /deezer/me/playlists

Liste les playlists de l'utilisateur connecté.

GET /deezer/oauth/url

Génère l'URL d'autorisation OAuth Deezer.

GET /deezer/oauth/callback

Callback OAuth Deezer.

POST /deezer/login

Connexion via jeton ARL (méthode alternative).

Body : {"arl": "cookie_arl_de_192_caracteres"}

POST /deezer/login/arl

Connexion par ARL (identique à /login).

POST /deezer/premium-check

Vérifie si le compte Deezer est Premium.

POST /deezer/import

Importe une piste Deezer dans la bibliothèque.

Body :

{
  "track_id": "deezer_track_id",
  "track_name": "Titre",
  "artist": "Artiste",
  "album": "Album"
}

15. YouTube

Préfixe : /api/v1/youtube

GET /youtube/search

Recherche sur YouTube.

Query : q (requis)

GET /youtube/track/{video_id}

Récupère les infos d'une vidéo YouTube.

POST /youtube/preview

Prévisualise l'import d'une vidéo YouTube (avec yt-dlp).

Body : {"url": "https://youtube.com/watch?v=..."}

GET /youtube/playlist

Récupère les infos d'une playlist YouTube.

Query : url (requis)

POST /youtube/import

Importe une piste ou playlist YouTube dans la bibliothèque.

Body :

{
  "url": "https://youtube.com/watch?v=...",
  "track_name": "Titre",
  "artist": "Artiste",
  "album": "Album"
}

GET /youtube/user-playlists

Liste les playlists YouTube de l'utilisateur.

GET /youtube/status

Statut du service YouTube (yt-dlp).


16. Apple Music

Préfixe : /api/v1/apple-music

GET /apple-music/search

Recherche sur Apple Music.

Query : q (requis), limit (défaut 5)

GET /apple-music/track/{track_id}

Récupère les infos d'une piste Apple Music.

GET /apple-music/playlists

Liste les playlists Apple Music de l'utilisateur.

GET /apple-music/playlist/{playlist_id}/tracks

Liste les pistes d'une playlist Apple Music.

GET /apple-music/auth-url

Génère l'URL d'autorisation Apple Music.

POST /apple-music/callback

Callback d'autorisation Apple Music.

POST /apple-music/add

Importe une piste Apple Music dans la bibliothèque.


17. SoundCloud

Préfixe : /api/v1/soundcloud

GET /soundcloud/search

Recherche sur SoundCloud.

Query : q (requis), limit (défaut 5)

GET /soundcloud/track/{track_id}

Récupère les infos d'une piste SoundCloud.

POST /soundcloud/resolve

Résout une URL SoundCloud en piste.

Body : {"url": "https://soundcloud.com/..."}

GET /soundcloud/playlists

Liste les playlists SoundCloud.

GET /soundcloud/playlist/{playlist_id}/tracks

Liste les pistes d'une playlist SoundCloud.

GET /soundcloud/auth-url

Génère l'URL d'autorisation SoundCloud.

POST /soundcloud/callback

Callback d'autorisation SoundCloud.

POST /soundcloud/add

Importe une piste SoundCloud dans la bibliothèque.


18. Scrobbler (Last.fm)

Préfixe : /api/v1/scrobbler

POST /scrobbler/scrobble

Scrobble une piste sur Last.fm.

Body :

{
  "track": "Bohemian Rhapsody",
  "artist": "Queen",
  "album": "A Night at the Opera",
  "timestamp": 1719500000,
  "duration": 355
}

POST /scrobbler/nowplaying

Met à jour « Now Playing » sur Last.fm.

Body : {"track": "...", "artist": "...", "album": "..."}

GET /scrobbler/status

Vérifie si Last.fm est configuré.

Réponse (200) :

{
  "configured": true,
  "username": "mon_username",
  "scrobble_enabled": true
}

GET /scrobbler/track

Récupère les infos d'une piste via Last.fm.

Query : track (requis), artist (optionnel)

GET /scrobbler/search

Recherche Last.fm.

Query : q (requis), limit (défaut 10, max 50)

GET /scrobbler/enrich

Enrichit les métadonnées d'une piste via Last.fm.

Query : track (requis), artist (optionnel)

POST /scrobbler/scrobble/batch

Scrobble plusieurs pistes en une fois (max 50).

Body :

{
  "scrobbles": [
    {"track": "Titre 1", "artist": "Artiste 1"},
    {"track": "Titre 2", "artist": "Artiste 2"}
  ]
}

GET /scrobbler/config

Récupère la configuration Last.fm.

POST /scrobbler/config

Met à jour la configuration Last.fm.

Body : {"username": "...", "api_key": "...", "session_key": "...", "scrobble_enabled": true}

GET /scrobbler/history

Historique des scrobbles (paginé).

Query : page, per_page

POST /scrobbler/clear-history

Efface l'historique des scrobbles.


19. Icecast

Préfixe : /api/v1/icecast

GET /icecast/status

Statut d'Icecast (installé, en cours d'exécution, port).

POST /icecast/install

Installe Icecast automatiquement.

POST /icecast/start

Démarre le serveur Icecast.

POST /icecast/stop

Arrête le serveur Icecast.

POST /icecast/record/start

Démarre l'enregistrement du stream.

Body : {"format": "mp3"}

POST /icecast/record/stop

Arrête l'enregistrement.

GET /icecast/record/status

Statut de l'enregistrement.


20. Paramètres

Préfixe : /api/v1

GET /health

Health check pour monitoring/Docker.

Réponse (200) :

{"status": "ok", "service": "webradio-manager"}

GET /health/detailed

Health check détaillé (uptime, mémoire, DB, WebSocket, scheduler).

GET /settings

Liste tous les paramètres.

Réponse (200) :

{
  "settings": {
    "weather.city": "Paris",
    "tts.engine": "gtts",
    "library.path": "/home/user/Music"
  },
  "count": 15
}

Les clés sensibles (*_api_key, *_token, *_secret, password, *_arl) sont déchiffrées automatiquement.

GET /settings/{key}

Récupère un paramètre par sa clé.

PUT /settings/{key}

Met à jour un paramètre.

Body : {"value": "nouvelle_valeur"}

POST /settings

Mise à jour en masse (recommandée).

Body :

{
  "weather.city": "Lyon",
  "tts.engine": "gtts",
  "library.path": "/home/user/Music",
  "icecast.port": 8000
}

GET /openapi.json

Spécification OpenAPI 3.0 complète.


21. Préférences utilisateur (sessions)

Préfixe : /api/v1/preferences

Préférences propres à chaque utilisateur (session) : thème, langue, configuration de l'espace de travail. Indépendantes des settings globales de l'application.

GET /preferences

Retourne toutes les préférences de l'utilisateur connecté.

Réponse (200) :

{ "preferences": { "theme": "dark", "lang": "fr" }, "count": 2 }

PUT /preferences/

Définit une préférence.

Body : { "value": "dark" }

Réponse (200) :

{ "key": "theme", "value": "dark" }

POST /preferences

Mise à jour groupée.

Body : { "theme": "dark", "lang": "fr" }

Réponse (200) :

{ "message": "Preferences updated", "updated": ["theme", "lang"], "count": 2 }

Authentification requise (JWT) — chaque compte a ses propres préférences.


22. Upload

Préfixe : /api/v1

POST /upload

Upload un fichier audio via multipart/form-data.

Content-Type : multipart/form-data Champ : file (fichier binaire audio)

Formats acceptés : MP3, OGG, FLAC, WAV, M4A

Réponse (201) :

{
  "message": "Upload successful",
  "track": {
    "track_id": "abc123",
    "track_name": "Mon titre",
    "artist": "Artiste",
    "file_path": "/path/to/file.mp3"
  }
}

23. Système de fichiers

Préfixe : /api/v1/filesystem

GET /filesystem/roots

Retourne les racines de fichiers accessibles (drives sous Windows, / sous Linux).

GET /filesystem/browse

Parcourt un dossier.

Query : path (chemin du dossier à explorer)


24. WebDAV

Préfixe : /api/v1/webdav

GET /webdav/status

État de la connexion WebDAV. Retourne configured, url, remote_path.

POST /webdav/sync

Synchronise la bibliothèque vers le serveur WebDAV.

Body : vide (utilise la configuration des Paramètres : URL, utilisateur, mot de passe, dossier distant webdav_remote_path)

Réponse (200) :

{ "message": "Sync complete", "files_found": 12, "synced": 5, "errors": [] }

POST /webdav/test

Teste la connexion WebDAV (PROPFIND sur l'URL + dossier distant configuré).

Body : vide (configuration depuis les Paramètres)

Réponse (200) :

{ "success": true, "message": "Connexion WebDAV OK", "info": { "url": "http://nas:5005/music/", "status": 207 } }

Échec possible : success: false avec message explicite (401 auth refusée, 404 dossier introuvable, etc.)


25. Synchronisation réseau (FTP / SFTP / Samba)

Préfixe : /api/v1

GET /ftp/status

État de la configuration FTP/SFTP. Retourne configured, host, port, protocol, remote_path, username_set.

POST /ftp/sync

Upload de la bibliothèque vers un serveur FTP/SFTP.

Body : vide (configuration depuis les Paramètres : ftp_host, ftp_port, ftp_protocol (ftp|sftp), ftp_username, ftp_password, ftp_remote_path, ftp_passive)

Réponse (200) :

{ "message": "FTP sync complete", "files_found": 12, "synced": 5, "errors": [] }

GET /samba/status

État de la configuration Samba. Retourne configured, server, share, remote_path, port, username_set.

POST /samba/sync

Upload de la bibliothèque vers un partage SMB.

Body : vide (configuration depuis les Paramètres : samba_server, samba_share, samba_port, samba_username, samba_password, samba_remote_path)

Réponse (200) :

{ "message": "Samba sync complete", "files_found": 12, "synced": 5, "errors": [] }

POST /ftp/test

Teste la connexion FTP/SFTP (login + accès au dossier distant).

Body : vide (configuration depuis les Paramètres)

Réponse (200) :

{ "success": true, "message": "Connexion FTP OK", "info": { "host": "nas", "port": 21, "protocol": "ftp", "cwd": "/", "remote_path_ok": true } }

POST /samba/test

Teste la connexion Samba/SMB (connect + list du partage + dossier distant).

Body : vide (configuration depuis les Paramètres)

Réponse (200) :

{ "success": true, "message": "Connexion Samba OK", "info": { "server": "192.168.0.10", "share": "music", "share_ok": true, "remote_path_ok": true } }

26. WebSocket

Préfixe : /socket.io

Connexion SocketIO pour les événements temps réel.

Endpoint REST associé : /api/v1/ws

GET /ws/status

Statut de la connexion WebSocket.

GET /ws/clients

Nombre de clients connectés.

POST /ws/broadcast

Envoie un événement personnalisé à tous les clients.

Body :

{
  "event": "custom_event",
  "data": {"message": "Bonjour à tous !"}
}

GET /ws/health

Health check WebSocket.

Événements temps réel :

Événement Direction Description
deck_update Serveur → Client Changement d'état d'un deck
mixer_update Serveur → Client Changement crossfader/volume
stream_status Serveur → Client Statut du flux Icecast
playlist_update Serveur → Client Modification de la playlist
now_playing Serveur → Client Changement de piste en cours
enrich:progress Serveur → Client Progression enrichissement
enrich:done Serveur → Client Enrichissement terminé

27. Monitoring & Métriques

Préfixe : /api/v1

GET /monitoring/dashboard

Tableau de bord complet (uptime, streams, DB, WebSocket, CPU/RAM).

GET /monitoring/system

Métriques système (CPU, RAM, disque).

GET /monitoring/streams

Métriques des flux (bitrate, listeners, uptime).

GET /monitoring/db

Santé de la base de données.

GET /monitoring/ws

Métriques WebSocket (clients connectés, messages).

GET /metrics

Métriques au format Prometheus.


28. HLS

Préfixe : /api/v1/hls

GET /hls/radio.m3u8

Playlist HLS principale (m3u8).

GET /hls/segment_{num}.ts

Segment HLS individuel.


29. Modèles de données

Track

{
  "id": 1,
  "track_id": "abc123def456",
  "track_name": "Bohemian Rhapsody",
  "artist": "Queen",
  "album": "A Night at the Opera",
  "genre": "Rock",
  "duration": 355,
  "file_path": "/home/user/Music/queen.mp3",
  "source_platform": "local",
  "track_order": 1,
  "status": "queued",
  "bpm": 72.0,
  "rating": 5,
  "year": 1975,
  "metadata_json": {
    "musicbrainz": {
      "cover_url": "https://coverartarchive.org/...",
      "year": 1975,
      "tags": ["rock", "classic rock"]
    }
  },
  "created_at": "2026-06-27T10:00:00"
}

Statuts : pending, queued, playing, active Sources : local, spotify, deezer, youtube, apple_music, soundcloud

Spot

{
  "id": 1,
  "spot_type": "weather",
  "city": "Paris",
  "generated_text": "Météo pour Paris : 22°C, ensoleillé...",
  "audio_path": "/tmp/webradio/spot_abc123.mp3",
  "duration": 15.0,
  "status": "ready",
  "scheduled_at": null,
  "created_at": "2026-06-27T10:00:00"
}

Types : weather, promo, nextup, traffic, generic Statuts : scheduled, ready, played

Schedule

{
  "id": 1,
  "name": "Spot météo matin",
  "track_id": null,
  "spot_id": 1,
  "start_time": "2026-07-10T08:00:00",
  "end_time": null,
  "recurrence": "daily",
  "priority": 1,
  "enabled": true
}

DeckState

{
  "deck": "A",
  "current_track_id": "abc123",
  "is_playing": true,
  "is_paused": false,
  "volume": 0.8,
  "speed": 1.0,
  "loop_enabled": false,
  "loop_start": null,
  "loop_end": null,
  "cue_position": 30.5,
  "eq_low": 0.0,
  "eq_mid": 0.0,
  "eq_high": 0.0,
  "playback_position": 45.2,
  "updated_at": "2026-06-27T10:05:00"
}

User

{
  "id": 1,
  "username": "admin",
  "email": "admin@example.com",
  "role": "admin",
  "is_active": true,
  "last_login": "2026-07-10T08:00:00",
  "created_at": "2026-06-27T10:00:00"
}

Rôles : admin, dj, viewer


30. Codes d'erreur

Code Signification Causes fréquentes
200 Succès Opération réussie
201 Créé Ressource créée (POST)
400 Requête invalide Paramètres manquants ou invalides
401 Non authentifié Token manquant ou expiré
403 Interdit Rôle insuffisant
404 Non trouvé Ressource inexistante
409 Conflit Ressource déjà existante
429 Trop de requêtes Rate limit dépassé
500 Erreur serveur Exception non gérée
502 Bad Gateway Échec service externe (TTS)
503 Service indisponible Service externe down

Format d'erreur standard

{
  "error": "Description de l'erreur",
  "details": [{"field": "...", "message": "..."}]
}

31. Versionnage & Rate Limiting

Versionnage

L'API supporte le versionnage via le header Accept-Version : - Accept-Version: v1 — API v1 (préfixe /api/v1) - Accept-Version: v2 — API v2 - Versions inconnues → 400

Rate Limiting

Swagger UI


Dernière mise à jour : 2026-08-10 Version API : v1 (préfixe /api/v1) + v2 Compatibilité : Webradio Manager v2.0.0 à v2.8.0


Sauf mention contraire, ces routes exigent Authorization: Bearer <token>.

32. Favoris

Méthode Route Description
GET /favorites Liste {favorites: [...]}
POST /favorites Ajoute : {track_id} (piste existante) ou {source, external_id, title, artist?, album?, duration?, cover_url?, preview_url?} (piste en ligne créée à la volée). Réponse 201, ou 200 + already_favorite
DELETE /favorites/<track_id> Retire (track_id = identifiant public, ex. radio:abc)

33. Historique d'écoute

Méthode Route Description
POST /history {track_id} — enregistre un démarrage de lecture (doublon < 30 s ignoré : recorded:false)
GET /history?limit=30 Pistes récentes dédoublonnées
GET /history/stats {total_plays_7d, top: [{track_id, track_name, artist, plays, ...}]}

34. Webradios et radios personnalisées

Méthode Route Description
GET /radio/search?q=&country=&limit=&custom=1 Radios radio-browser.info + radios perso en tête ; custom=1 : radios perso seules (public, sans token)
GET /radio/status Disponibilité
GET /radio/custom Liste des radios perso
POST /radio/custom {name, url, logo_url?}
PUT /radio/custom/<id> Modifie name, url, logo_url
DELETE /radio/custom/<id> Supprime
POST /radio/custom/import-csv Multipart file (colonnes name,url,logo ; , ou ;) → {added, skipped} (URL déjà présentes ignorées)
GET /radio/custom/export CSV (;, BOM UTF-8)

35. Pistes en ligne, titre en cours, loudness

Méthode Route Description
POST /playlists/<id>/tracks/online Ajoute une piste en ligne (source : youtube, radio, …) ; réponse {track}
GET /library/tracks/<track_id>/stream Flux audio (fichier local, ou proxy same-origin pour les pistes en ligne ; sans token, lu par <audio>)
GET /library/tracks/<track_id>/nowplaying Webradio : {available, artist, title, raw, station} (métadonnées ICY relevées par le proxy)
POST /library/tracks/<track_id>/download Rend locale une piste YouTube en ligne
POST /library/tracks/<track_id>/loudness Mesure/relit le loudness EBU R128 → {loudness_lufs, target_lufs, gain_db}
POST /library/loudness/analyze Analyse toutes les pistes locales (arrière-plan)
GET /library/loudness/status {running, done, total}
POST /youtube/import Renvoie {duplicate: true, track_id} sans télécharger si la vidéo est déjà importée

36. Sauvegardes

Administrateur uniquement, SQLite.

Méthode Route Description
GET /admin/backups Liste {backups: [{name, size, modified}], supported}
POST /admin/backups Crée une sauvegarde manuelle
GET /admin/backups/<name> Télécharge
POST /admin/backups/<name>/restore Body {confirm: true} — vérifie l'intégrité, crée webradio_prerestore_*, restaure à chaud → {restored, safety_backup, relogin}

Une sauvegarde automatique quotidienne (7 conservées) est faite par le serveur.

37. Scan asynchrone

Méthode Route Description
POST /library/scan {async: true} → 202 {status: started\|running} ; sans async, scan synchrone (limite 120/h)
GET /library/scan/status {running, path, elapsed, error, result: {files_found, tracks_added, tracks_updated, tracks_removed, errors[]}}

38. Planification de radios

POST /scheduler/events et PUT /scheduler/events/<id> acceptent en plus :

Les événements pilotent le deck de l'utilisateur propriétaire de l'événement.