{"swagger": "2.0", "info": {"title": "JeuxCracks API", "description": "Documentation officielle de l'API JeuxCracks (Backend Web & Telemetry)", "termsOfService": "https://www.jeuxcracks.fr/terms/", "contact": {"email": "uptime@jeuxcracks.fr"}, "license": {"name": "BSD License"}, "version": "v1"}, "host": "api.jeuxcracks.fr", "schemes": ["https"], "basePath": "/", "consumes": ["application/json"], "produces": ["application/json"], "securityDefinitions": {"Basic": {"type": "basic"}}, "security": [{"Basic": []}], "paths": {"/Cracks/api/game/": {"get": {"operationId": "Cracks_api_game_list", "summary": "Récupère les informations d'un jeu précis de la base de données au format JSON", "description": "La requête doit inclure un paramètre :\n- `id` : L'ID interne du jeu (facultatif).\n- `steam_id` : L'ID Steam du jeu (facultatif).\n- `title` : Le titre interne du jeu (facultatif).\n\nLa requête renvoie une réponse JSON.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["Cracks"]}, "parameters": []}, "/Cracks/api/liste_jeux/": {"get": {"operationId": "Cracks_api_liste_jeux_list", "description": "Récupère tous les jeux de la base de données au format JSON avec pagination,\nfiltrage par catégorie, statut en ligne, et triage par vues et likes selon les paramètres de la requête.\n\nDétail des paramètres\n\ntitle=Zelda: Filtrera les jeux dont le titre contient \"Zelda\".\ncategory=Action: Filtrera les jeux appartenant à la catégorie \"Action\".\nonline=true: Filtrera pour afficher uniquement les jeux qui sont actuellement en ligne.\nviews=true: Trier les jeux par le nombre de vues, du plus élevé au plus bas.\nlimit=20: Limitera le nombre de jeux affichés à 20 par page.\npage=2: Affichera la deuxième page de résultats.\n\nexemple de request GET /Cracks/api/liste_jeux/?title=ark&category=Action&online=true&views=true&likes=true&limit=20&page=1", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["Cracks"]}, "parameters": []}, "/Cracks/api/pour_le_fdp/": {"get": {"operationId": "Cracks_api_pour_le_fdp_list", "description": "", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["Cracks"]}, "parameters": []}, "/Cracks/api/report/{game_id}/": {"post": {"operationId": "Cracks_api_report_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["Cracks"]}, "parameters": [{"name": "game_id", "in": "path", "required": true, "type": "string"}]}, "/Cracks/api/toggle_favorite/{game_id}/": {"post": {"operationId": "Cracks_api_toggle_favorite_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["Cracks"]}, "parameters": [{"name": "game_id", "in": "path", "required": true, "type": "string"}]}, "/Cracks/api/toggle_like/{game_id}/": {"post": {"operationId": "Cracks_api_toggle_like_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["Cracks"]}, "parameters": [{"name": "game_id", "in": "path", "required": true, "type": "string"}]}, "/Cracks/api/update-game/": {"put": {"operationId": "Cracks_api_update-game_update", "summary": "Modifie un jeu existant dans la base de données.", "description": "La requête doit inclure les paramètres suivants :\n- `api_key` : La clé API valide pour accéder à l'API.\n- `game_id` : L'ID du jeu à modifier.\n- `user_id` : L'ID de l'utilisateur qui effectue la requête.\n- `title` : Nouveau titre du jeu (facultatif).\n- `note_staff` : Nouvelle note du staff (facultatif).\n- `url` : Nouvelle URL du jeu (facultatif).\n- `is_online` : Statut en ligne du jeu (facultatif).\n- `categories` : Liste des noms des nouvelles catégories (facultatif).\n- `source_id` : ID de la nouvelle source (facultatif).\n\nLa requête renvoie une réponse JSON indiquant le succès ou l'échec de la modification du jeu.", "parameters": [{"name": "api_key", "in": "query", "required": true, "type": "string", "maxLength": 255, "minLength": 1}, {"name": "game_id", "in": "query", "required": true, "type": "integer"}, {"name": "user_id", "in": "query", "required": true, "type": "integer"}, {"name": "title", "in": "query", "required": false, "type": "string", "maxLength": 255, "minLength": 1}, {"name": "note_staff", "in": "query", "required": false, "type": "string", "minLength": 1}, {"name": "url", "in": "query", "required": false, "type": "string", "format": "uri", "minLength": 1}, {"name": "is_online", "in": "query", "required": false, "type": "boolean"}, {"name": "categories", "in": "query", "required": false, "type": "array", "items": {"type": "string", "maxLength": 100, "minLength": 1}}, {"name": "sources", "in": "query", "required": false, "type": "array", "items": {"type": "integer"}}], "responses": {"200": {"description": ""}}, "tags": ["Cracks"]}, "parameters": []}, "/Cracks/api/views/{game_id}/": {"get": {"operationId": "Cracks_api_views_read", "description": "", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["Cracks"]}, "parameters": [{"name": "game_id", "in": "path", "required": true, "type": "string"}]}, "/Cracks/game/api/add_games": {"post": {"operationId": "Cracks_game_api_add_games_create", "summary": "Ajoute un nouveau jeu dans la base de données en utilisant son ID Steam.", "description": "La requête doit inclure trois paramètres :\n- `api_key` : La clé API valide pour accéder à l'API.\n- `game_id` : L'ID Steam du jeu à ajouter.\n- `user_id` : L'ID de l'utilisateur qui effectue la requête.\n- `game_link` : URL du jeu, facultatif.\n\nLa requête renvoie une réponse JSON indiquant le succès ou l'échec de l'ajout du jeu.", "parameters": [{"name": "api_key", "in": "query", "description": "Clé API pour authentification", "required": true, "type": "string", "minLength": 1}, {"name": "game_id", "in": "query", "description": "ID Steam du jeu", "required": true, "type": "string", "minLength": 1}, {"name": "user_id", "in": "query", "description": "ID de l'utilisateur", "required": true, "type": "string", "minLength": 1}, {"name": "game_link", "in": "query", "description": "URL du jeu, facultatif", "required": false, "type": "string", "format": "uri", "x-nullable": true}], "responses": {"201": {"description": ""}}, "tags": ["Cracks"]}, "parameters": []}, "/api/app/categories/": {"get": {"operationId": "api_app_categories_list", "description": "Liste des catégories de jeux", "parameters": [{"name": "page", "in": "query", "description": "A page number within the paginated result set.", "required": false, "type": "integer"}], "responses": {"200": {"description": "", "schema": {"required": ["count", "results"], "type": "object", "properties": {"count": {"type": "integer"}, "next": {"type": "string", "format": "uri", "x-nullable": true}, "previous": {"type": "string", "format": "uri", "x-nullable": true}, "results": {"type": "array", "items": {"$ref": "#/definitions/Category"}}}}}}, "tags": ["api"]}, "parameters": []}, "/api/app/categories/{id}/": {"get": {"operationId": "api_app_categories_read", "description": "Liste des catégories de jeux", "parameters": [], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/Category"}}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "description": "A unique integer value identifying this category.", "required": true, "type": "integer"}]}, "/api/app/games/": {"get": {"operationId": "api_app_games_list", "description": "API principale du catalogue de jeux", "parameters": [{"name": "page", "in": "query", "description": "A page number within the paginated result set.", "required": false, "type": "integer"}, {"name": "limit", "in": "query", "description": "Number of results to return per page.", "required": false, "type": "integer"}, {"name": "q", "in": "query", "description": "Recherche textuelle", "type": "string"}, {"name": "category", "in": "query", "description": "Slug de catégorie", "type": "string"}, {"name": "tags", "in": "query", "description": "Tags séparés par virgule", "type": "string"}, {"name": "sort", "in": "query", "description": "newest, popular, views, downloads, likes", "type": "string"}], "responses": {"200": {"description": "", "schema": {"required": ["count", "results"], "type": "object", "properties": {"count": {"type": "integer"}, "next": {"type": "string", "format": "uri", "x-nullable": true}, "previous": {"type": "string", "format": "uri", "x-nullable": true}, "results": {"type": "array", "items": {"$ref": "#/definitions/GameList"}}}}}}, "tags": ["api"]}, "post": {"operationId": "api_app_games_create", "description": "API principale du catalogue de jeux", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/GameCreateUpdate"}}], "responses": {"201": {"description": "", "schema": {"$ref": "#/definitions/GameCreateUpdate"}}}, "tags": ["api"]}, "parameters": []}, "/api/app/games/by-slug/{slug}/": {"get": {"operationId": "api_app_games_by_slug", "description": "Récupérer un jeu par son slug", "parameters": [{"name": "page", "in": "query", "description": "A page number within the paginated result set.", "required": false, "type": "integer"}, {"name": "limit", "in": "query", "description": "Number of results to return per page.", "required": false, "type": "integer"}], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/GameDetail"}}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string", "format": "slug", "pattern": "^[-a-zA-Z0-9_]+$"}]}, "/api/app/games/favorites/": {"get": {"operationId": "api_app_games_favorites", "description": "Jeux en favoris de l'utilisateur", "parameters": [{"name": "page", "in": "query", "description": "A page number within the paginated result set.", "required": false, "type": "integer"}, {"name": "limit", "in": "query", "description": "Number of results to return per page.", "required": false, "type": "integer"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/GameList"}}}}, "tags": ["api"]}, "parameters": []}, "/api/app/games/liked/": {"get": {"operationId": "api_app_games_liked", "description": "Jeux likés par l'utilisateur", "parameters": [{"name": "page", "in": "query", "description": "A page number within the paginated result set.", "required": false, "type": "integer"}, {"name": "limit", "in": "query", "description": "Number of results to return per page.", "required": false, "type": "integer"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/GameList"}}}}, "tags": ["api"]}, "parameters": []}, "/api/app/games/popular/": {"get": {"operationId": "api_app_games_popular", "description": "Top 10 jeux par vues", "parameters": [{"name": "page", "in": "query", "description": "A page number within the paginated result set.", "required": false, "type": "integer"}, {"name": "limit", "in": "query", "description": "Number of results to return per page.", "required": false, "type": "integer"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/GameList"}}}}, "tags": ["api"]}, "parameters": []}, "/api/app/games/recent/": {"get": {"operationId": "api_app_games_recent", "description": "10 derniers jeux ajoutés", "parameters": [{"name": "page", "in": "query", "description": "A page number within the paginated result set.", "required": false, "type": "integer"}, {"name": "limit", "in": "query", "description": "Number of results to return per page.", "required": false, "type": "integer"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/GameList"}}}}, "tags": ["api"]}, "parameters": []}, "/api/app/games/search/": {"get": {"operationId": "api_app_games_search", "description": "Recherche avancée avec fuzzy matching et filtres multiples", "parameters": [{"name": "page", "in": "query", "description": "A page number within the paginated result set.", "required": false, "type": "integer"}, {"name": "limit", "in": "query", "description": "Number of results to return per page.", "required": false, "type": "integer"}, {"name": "q", "in": "query", "description": "Terme de recherche (fuzzy)", "type": "string"}, {"name": "category", "in": "query", "description": "Slug de catégorie", "type": "string"}, {"name": "tags", "in": "query", "description": "Tags séparés par virgule", "type": "string"}, {"name": "developer", "in": "query", "description": "Nom du développeur", "type": "string"}, {"name": "year", "in": "query", "description": "Année de sortie", "type": "integer"}, {"name": "is_online", "in": "query", "description": "Jeux avec version online", "type": "boolean"}, {"name": "sort", "in": "query", "description": "Tri: relevance|newest|popular|views|downloads", "type": "string", "default": "relevance"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/GameList"}}}}, "tags": ["api"]}, "parameters": []}, "/api/app/games/trending/": {"get": {"operationId": "api_app_games_trending", "description": "Jeux trending (vues récentes)", "parameters": [{"name": "page", "in": "query", "description": "A page number within the paginated result set.", "required": false, "type": "integer"}, {"name": "limit", "in": "query", "description": "Number of results to return per page.", "required": false, "type": "integer"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/GameList"}}}}, "tags": ["api"]}, "parameters": []}, "/api/app/games/{id}/": {"get": {"operationId": "api_app_games_read", "description": "API principale du catalogue de jeux", "parameters": [], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/GameDetail"}}}, "tags": ["api"]}, "put": {"operationId": "api_app_games_update", "description": "API principale du catalogue de jeux", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/GameCreateUpdate"}}], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/GameCreateUpdate"}}}, "tags": ["api"]}, "patch": {"operationId": "api_app_games_partial_update", "description": "API principale du catalogue de jeux", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/GameCreateUpdate"}}], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/GameCreateUpdate"}}}, "tags": ["api"]}, "delete": {"operationId": "api_app_games_delete", "description": "API principale du catalogue de jeux", "parameters": [], "responses": {"204": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "description": "A unique integer value identifying this game.", "required": true, "type": "integer"}]}, "/api/app/games/{id}/download/": {"get": {"operationId": "api_app_games_download", "description": "Récupérer les liens de téléchargement (auth required)", "parameters": [], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/GameDownload"}}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "description": "A unique integer value identifying this game.", "required": true, "type": "integer"}]}, "/api/app/games/{id}/favorite/": {"post": {"operationId": "api_app_games_favorite", "description": "Ajouter aux favoris", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/GameDetail"}}], "responses": {"200": {"description": "Favorited"}, "201": {"description": "Favorite added"}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "description": "A unique integer value identifying this game.", "required": true, "type": "integer"}]}, "/api/app/games/{id}/like/": {"post": {"operationId": "api_app_games_like", "description": "Liker un jeu", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/GameDetail"}}], "responses": {"200": {"description": "Liked"}, "201": {"description": "Like added"}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "description": "A unique integer value identifying this game.", "required": true, "type": "integer"}]}, "/api/app/games/{id}/related/": {"get": {"operationId": "api_app_games_related", "description": "Jeux similaires pour le maillage interne SEO", "parameters": [{"name": "limit", "in": "query", "description": "Nombre max de jeux retournés (défaut: 6)", "type": "integer"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/GameList"}}}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "description": "A unique integer value identifying this game.", "required": true, "type": "integer"}]}, "/api/app/games/{id}/unfavorite/": {"post": {"operationId": "api_app_games_unfavorite", "description": "Retirer des favoris", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/GameDetail"}}], "responses": {"200": {"description": "Unfavorited"}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "description": "A unique integer value identifying this game.", "required": true, "type": "integer"}]}, "/api/app/games/{id}/unlike/": {"post": {"operationId": "api_app_games_unlike", "description": "Retirer le like", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/GameDetail"}}], "responses": {"200": {"description": "Unliked"}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "description": "A unique integer value identifying this game.", "required": true, "type": "integer"}]}, "/api/app/games/{id}/view/": {"post": {"operationId": "api_app_games_view", "description": "Incrémenter les vues (1 par user/24h)", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/GameDetail"}}], "responses": {"200": {"description": "View counted"}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "description": "A unique integer value identifying this game.", "required": true, "type": "integer"}]}, "/api/app/steam-search/": {"get": {"operationId": "api_app_steam-search_list", "description": "Recherche live sur le Steam Store, utilisée par le formulaire de suggestion\npour résoudre un titre tapé par l'utilisateur vers un App ID Steam.\nGET /api/app/steam-search/?q=<terme>", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/cinefuse/catalog/": {"get": {"operationId": "api_cinefuse_catalog_list", "description": "GET /auth/api/cinefuse/catalog/ — TOUT le catalogue CineFuse (toutes les pages,\npas juste la première), filtré aux entrées dont au moins une source vidéo vient\nde vidzy / fsvid / cdn.ohlatuile / cdn.novapulse.im / cinebig.\n\nRéponse VOLONTAIREMENT légère (slug + titre + poster seulement) — le launcher\ngarde tout le catalogue en mémoire pour la page Films & Séries, donc pas question\nd'y traîner l'arbre saisons→épisodes→sources ou les champs overview/backdrop.\nLe détail complet est chargé à la demande sur la fiche (movies/{slug}, tv/{slug}).\n\nBoucle sur /api/movies et /api/series avec limit=100 jusqu'à épuiser\ntotal_results. Résultat mis en cache 10 min.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/cinefuse/continue/": {"get": {"operationId": "api_cinefuse_continue_list", "description": "GET /auth/api/cinefuse/continue/ — non terminés (<95%), triés par vu récemment.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/cinefuse/history/": {"get": {"operationId": "api_cinefuse_history_list", "description": "GET /auth/api/cinefuse/history/ — tout ce qui a été regardé, terminé ou non.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/cinefuse/movies/{slug}/progress/": {"post": {"operationId": "api_cinefuse_movies_progress_create", "description": "POST /auth/api/cinefuse/movies/<slug>/progress/ — body {position, duration}.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/cinefuse/movies/{slug}/video/": {"get": {"operationId": "api_cinefuse_movies_video_list", "description": "GET /auth/api/cinefuse/movies/<slug>/video/ — sources + position de reprise.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/cinefuse/tv/{slug}/episode/{episode_id}/progress/": {"post": {"operationId": "api_cinefuse_tv_episode_progress_create", "description": "POST /auth/api/cinefuse/tv/<slug>/episode/<episode_id>/progress/ — body {position, duration}.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}, {"name": "episode_id", "in": "path", "required": true, "type": "string"}]}, "/api/cinefuse/tv/{slug}/episode/{episode_id}/video/": {"get": {"operationId": "api_cinefuse_tv_episode_video_list", "description": "GET /auth/api/cinefuse/tv/<slug>/episode/<episode_id>/video/ — pas d'endpoint\nstream dédié côté CineFuse pour les épisodes : les sources sont nichées dans\n/api/tv/{slug} -> seasons[].episodes[].video_links, on va les y chercher.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}, {"name": "episode_id", "in": "path", "required": true, "type": "string"}]}, "/api/cinefuse/{path}": {"get": {"operationId": "api_cinefuse_read", "summary": "GET /auth/api/cinefuse/<path>/ — proxy authentifié vers l'API CineFuse.", "description": "Le launcher appelle CETTE route avec le JWT JeuxCracks de l'utilisateur ;\nle backend ajoute la clé API CineFuse + le User-Agent obligatoire\n(Cloudflare renvoie 403 sans) et relaie la requête. La clé CINEFUSE_API_KEY\nne quitte JAMAIS le serveur — jamais distribuée dans le launcher (un .exe\nbundlé est extractible par n'importe qui).", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "path", "in": "path", "required": true, "type": "string"}]}, "/api/engine/games/": {"get": {"operationId": "api_engine_games_list", "description": "", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/engine/games/favorites/": {"get": {"operationId": "api_engine_games_favorites_list", "description": "Games favorited by the authenticated user, enriched from engine.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/engine/games/liked/": {"get": {"operationId": "api_engine_games_liked_list", "description": "Games liked by the authenticated user, enriched from engine.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/engine/games/{slug}/": {"get": {"operationId": "api_engine_games_read", "description": "Full game detail: JC-Engine data + social data merged.\nAuto-registers a view (max 1 per user/IP per 24h).", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/engine/games/{slug}/download/": {"get": {"operationId": "api_engine_games_download_list", "description": "Latest version with download links (auth required).\nAlso increments download counter.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/engine/games/{slug}/favorite/": {"post": {"operationId": "api_engine_games_favorite_create", "description": "Add to favorites.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/engine/games/{slug}/like/": {"post": {"operationId": "api_engine_games_like_create", "description": "Like a game.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/engine/games/{slug}/remote-download/": {"post": {"operationId": "api_engine_games_remote-download_create", "description": "POST /api/engine/games/<slug>/remote-download/ — avantage VIP : lance le\ntéléchargement depuis le site sur le launcher de l'utilisateur.\n\nLivré tout de suite si le launcher est connecté au WS (ws/gateway/), sinon\npersisté et livré automatiquement à sa prochaine ouverture (voir\nsocial.consumers.SocialConsumer._deliver_pending_downloads).", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/engine/games/{slug}/report/": {"post": {"operationId": "api_engine_games_report_create", "description": "Report a game.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/engine/games/{slug}/unfavorite/": {"post": {"operationId": "api_engine_games_unfavorite_create", "description": "Remove from favorites.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/engine/games/{slug}/unlike/": {"post": {"operationId": "api_engine_games_unlike_create", "description": "Remove like.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/engine/games/{slug}/versions/": {"get": {"operationId": "api_engine_games_versions_list", "description": "All versions of a game (proxy to engine).", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/engine/games/{slug}/view/": {"post": {"operationId": "api_engine_games_view_create", "description": "Register a view (max 1 per user/IP per 24h).", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/engine/health/": {"get": {"operationId": "api_engine_health_list", "description": "Proxy health + Django status.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/engine/reports/reasons/": {"get": {"operationId": "api_engine_reports_reasons_list", "description": "List all report reasons.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/engine/search/": {"get": {"operationId": "api_engine_search_list", "description": "Hybrid search: queries JC-Engine first, enriches with social data.\nQuery params: q (required), limit (default: 20)", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/engine/stats/": {"get": {"operationId": "api_engine_stats_list", "description": "Engine stats + social stats.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/gateway/callback/": {"post": {"operationId": "api_gateway_callback_create", "description": "POST /api/gateway/callback/\n★ URL à mettre dans le dashboard CryptoGate → onglet Webhooks / Callback URL ★\n→ https://api.jeuxcracks.fr/api/gateway/callback/\n\nCryptoGate POST ici à chaque changement de statut (confirming / paid / failed).", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/gateway/create-payment/": {"post": {"operationId": "api_gateway_create-payment_create", "description": "POST /api/gateway/create-payment/\nCrée une commande locale (pending) + un payment-link CryptoGate,\net renvoie l'URL de checkout où rediriger le client.\n\nBody attendu : { \"product\": \"premium_month\", \"email\": \"...\" (optionnel) }\n\n⚠️ SÉCURITÉ : le PRIX n'est JAMAIS lu depuis la requête. Le client envoie\nseulement le `product` (sku) ; le montant vient du catalogue serveur.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/gateway/products/": {"get": {"operationId": "api_gateway_products_list", "description": "GET /api/gateway/products/ — Catalogue des produits vendables (prix serveur).", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/liste_multilinks/": {"get": {"operationId": "api_liste_multilinks_list", "description": "", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/multilinks/create/": {"post": {"operationId": "api_multilinks_create_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/multilinks/{slug}/": {"get": {"operationId": "api_multilinks_read", "description": "", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/shop/checkout/": {"post": {"operationId": "api_shop_checkout_create", "description": "Créer une session Stripe Checkout. Body: { \"slug\": \"frame_neon_blue\" }", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/shop/equip/": {"post": {"operationId": "api_shop_equip_create", "description": "Équiper un item possédé. Body: { \"slug\": \"frame_neon_blue\" }", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/shop/equipment/": {"get": {"operationId": "api_shop_equipment_list", "description": "Retourne l'équipement actuel du user.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/shop/inventory/": {"get": {"operationId": "api_shop_inventory_list", "description": "Retourne l'inventaire du user connecté.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/shop/items/": {"get": {"operationId": "api_shop_items_list", "description": "Retourne tous les items actifs de la boutique.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/shop/items/{slug}/": {"get": {"operationId": "api_shop_items_read", "description": "Détail d'un item.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/api/shop/unequip/": {"post": {"operationId": "api_shop_unequip_create", "description": "Retirer un item. Body: { \"type\": \"avatar_frame\" }", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/social/chat/unread/": {"get": {"operationId": "api_social_chat_unread", "description": "Récupérer le nombre total de messages non lus et le détail par expéditeur.", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "object", "properties": {"total_unread": {"type": "integer"}, "by_sender": {"type": "array", "items": {"type": "object"}}}}}}, "tags": ["api"]}, "parameters": []}, "/api/social/chat/{id}/history/": {"get": {"operationId": "api_social_chat_history", "description": "Récupérer l'historique avec un ami (PK = User ID de l'ami).", "parameters": [{"name": "limit", "in": "query", "description": "Nombre de messages", "type": "integer"}, {"name": "offset", "in": "query", "description": "Décalage", "type": "integer"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/ChatMessage"}}}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/api/social/chat/{id}/mark_read/": {"post": {"operationId": "api_social_chat_mark_read", "description": "Marquer tous les messages d'un ami comme lus (PK = User ID de l'ami).", "parameters": [], "responses": {"200": {"description": "Messages marqués comme lus"}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/api/social/friends/block/": {"post": {"operationId": "api_social_friends_block", "description": "Bloquer un utilisateur par son ID.\nSi une relation existe, elle est mise à BLOCKED.\nSinon, une nouvelle relation BLOCKED est créée.", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"type": "object", "properties": {"user_id": {"type": "integer"}}}}], "responses": {"200": {"description": "Utilisateur bloqué"}, "400": {"description": "Erreur"}}, "tags": ["api"]}, "parameters": []}, "/api/social/friends/blocked/": {"get": {"operationId": "api_social_friends_blocked", "description": "Liste des utilisateurs bloqués", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/Friendship"}}}}, "tags": ["api"]}, "parameters": []}, "/api/social/friends/friends/": {"get": {"operationId": "api_social_friends_friends", "description": "Jeu de résultats: Liste des amis (Acceptés)", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/Friendship"}}}}, "tags": ["api"]}, "parameters": []}, "/api/social/friends/request/": {"post": {"operationId": "api_social_friends_request", "description": "Wrapper allowing to enhance a standard `HttpRequest` instance.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/social/friends/requests/": {"get": {"operationId": "api_social_friends_requests", "description": "Liste des demandes en attente (Reçues ou Envoyées)", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/Friendship"}}}}, "tags": ["api"]}, "parameters": []}, "/api/social/friends/{id}/remove/": {"delete": {"operationId": "api_social_friends_remove", "description": "Supprimer un ami (PK = ID de la Friendship).\nLes deux parties peuvent supprimer la relation.", "parameters": [], "responses": {"200": {"description": "Ami supprimé"}, "404": {"description": "Relation introuvable"}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/api/social/friends/{id}/respond/": {"post": {"operationId": "api_social_friends_respond", "description": "Répondre à une demande (ACCEPT / REJECT).\nPK est l'ID de la Friendship.", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"type": "object", "properties": {"action": {"type": "string", "enum": ["ACCEPT", "REJECT"]}}}}], "responses": {"200": {"description": "Updated"}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/api/social/friends/{id}/unblock/": {"post": {"operationId": "api_social_friends_unblock", "description": "Débloquer un utilisateur (PK = ID de la Friendship).\nSeul le bloqueur peut débloquer.", "parameters": [], "responses": {"200": {"description": "Utilisateur débloqué"}, "404": {"description": "Blocage introuvable"}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/api/social/inbox/all/": {"get": {"operationId": "api_social_inbox_all", "description": "Récupère toutes les notifications (lues et non lues)", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/UserNotification"}}}}, "tags": ["api"]}, "parameters": []}, "/api/social/inbox/broadcast/": {"post": {"operationId": "api_social_inbox_broadcast", "description": "Envoyer une notification à TOUS les utilisateurs (Admin/Staff uniquement).", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"required": ["title", "message"], "type": "object", "properties": {"title": {"type": "string"}, "message": {"type": "string"}, "link": {"type": "string"}, "type": {"type": "string", "enum": ["UPDATE", "PROMO", "SYSTEM", "SOCIAL"]}}}}], "responses": {"201": {"description": "Notifications créées pour tous les utilisateurs"}}, "tags": ["api"]}, "parameters": []}, "/api/social/inbox/create_notification/": {"post": {"operationId": "api_social_inbox_create_notification", "description": "Créer une notification pour un utilisateur (Admin/Staff uniquement).", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"required": ["user_id", "title", "message"], "type": "object", "properties": {"user_id": {"description": "ID de l'utilisateur cible", "type": "integer"}, "title": {"type": "string"}, "message": {"type": "string"}, "link": {"description": "Deep link (optionnel)", "type": "string"}, "type": {"type": "string", "enum": ["UPDATE", "PROMO", "SYSTEM", "SOCIAL"]}}}}], "responses": {"201": {"description": "", "schema": {"$ref": "#/definitions/UserNotification"}}, "403": {"description": "Non autorisé"}}, "tags": ["api"]}, "parameters": []}, "/api/social/inbox/mark-read/": {"post": {"operationId": "api_social_inbox_mark_read", "description": "Marquer des notifications comme lues.\nSi notification_ids est vide ou absent, marque TOUTES les notifications comme lues.", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"type": "object", "properties": {"notification_ids": {"description": "Liste des IDs de notifications à marquer comme lues", "type": "array", "items": {"type": "integer"}}}}}], "responses": {"200": {"description": "Notifications marquées comme lues"}}, "tags": ["api"]}, "parameters": []}, "/api/social/inbox/unread/": {"get": {"operationId": "api_social_inbox_unread", "description": "Récupère toutes les notifications non lues", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/UserNotification"}}}}, "tags": ["api"]}, "parameters": []}, "/api/social/inbox/{id}/delete/": {"delete": {"operationId": "api_social_inbox_delete", "description": "Supprimer une notification.", "parameters": [], "responses": {"200": {"description": "Notification supprimée"}, "404": {"description": "Introuvable"}}, "tags": ["api"]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/api/subscriptions/cancel/": {"post": {"operationId": "api_subscriptions_cancel_create", "summary": "Annuler l'abonnement", "description": "Annule l'abonnement.", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/Cancel"}}], "responses": {"200": {"description": "OK"}, "404": {"description": "No subscription"}}, "tags": ["Subscriptions"]}, "parameters": []}, "/api/subscriptions/change-billing/": {"post": {"operationId": "api_subscriptions_change-billing_create", "summary": "Changer la période de facturation", "description": "Change la période de facturation.", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/ChangeBilling"}}], "responses": {"200": {"description": "OK"}}, "tags": ["Subscriptions"]}, "parameters": []}, "/api/subscriptions/checkout/": {"post": {"operationId": "api_subscriptions_checkout_create", "summary": "Créer un paiement d'abonnement (CryptoGate)", "description": "Crée un paiement CryptoGate pour un abonnement (remplace Stripe).", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/Checkout"}}], "responses": {"200": {"description": "", "schema": {"type": "object", "properties": {"checkout_url": {"type": "string"}, "order_id": {"type": "string"}}}}, "400": {"description": "Bad Request"}}, "tags": ["Subscriptions"]}, "parameters": []}, "/api/subscriptions/donate/": {"post": {"operationId": "api_subscriptions_donate_create", "summary": "Faire un don libre", "description": "Créer un don libre — payment-link CryptoGate (montant libre choisi par le client).", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/Donate"}}], "responses": {"200": {"description": "", "schema": {"type": "object", "properties": {"checkout_url": {"type": "string"}, "order_id": {"type": "string"}, "session_id": {"description": "Alias de order_id (compat)", "type": "string"}}}}, "400": {"description": "Bad Request"}, "502": {"description": "Passerelle de paiement injoignable"}}, "tags": ["Donations"]}, "parameters": []}, "/api/subscriptions/donations/": {"get": {"operationId": "api_subscriptions_donations_list", "summary": "Historique des dons", "description": "Historique des dons de l'utilisateur.", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/Donation"}}}}, "tags": ["Donations"]}, "parameters": []}, "/api/subscriptions/downgrade/": {"post": {"operationId": "api_subscriptions_downgrade_create", "summary": "Downgrade de plan", "description": "Downgrade le plan (appliqué en fin de période).", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/Upgrade"}}], "responses": {"200": {"description": "OK"}}, "tags": ["Subscriptions"]}, "parameters": []}, "/api/subscriptions/gift/checkout/": {"post": {"operationId": "api_subscriptions_gift_checkout_create", "summary": "Offrir un abonnement (checkout CryptoGate)", "description": "POST /api/subscriptions/gift/checkout/ — crée un paiement CryptoGate PONCTUEL\npour offrir un abonnement (direct à un ami, ou code à transmettre).", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/GiftCheckout"}}], "responses": {"200": {"description": "OK"}, "400": {"description": "Bad Request"}, "502": {"description": "CryptoGate injoignable"}}, "tags": ["Gifts"]}, "parameters": []}, "/api/subscriptions/gift/mine/": {"get": {"operationId": "api_subscriptions_gift_mine_list", "summary": "Mes cadeaux achetés", "description": "GET /api/subscriptions/gift/mine/ — mes cadeaux achetés (retrouver un code).", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/Gift"}}}}, "tags": ["Gifts"]}, "parameters": []}, "/api/subscriptions/gift/redeem/": {"post": {"operationId": "api_subscriptions_gift_redeem_create", "summary": "Utiliser un code cadeau", "description": "POST /api/subscriptions/gift/redeem/ — active un code cadeau sur MON compte.", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/GiftRedeem"}}], "responses": {"200": {"description": "OK"}, "400": {"description": "Code invalide"}, "429": {"description": "Trop de tentatives"}}, "tags": ["Gifts"]}, "parameters": []}, "/api/subscriptions/invoices/": {"get": {"operationId": "api_subscriptions_invoices_list", "summary": "Historique des factures", "description": "Historique des factures.", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/Invoice"}}}}, "tags": ["Subscriptions"]}, "parameters": []}, "/api/subscriptions/plans/": {"get": {"operationId": "api_subscriptions_plans_list", "summary": "Liste des plans", "description": "Liste les plans d'abonnement disponibles.", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/SubscriptionPlan"}}}}, "tags": ["Subscriptions"]}, "parameters": []}, "/api/subscriptions/reactivate/": {"post": {"operationId": "api_subscriptions_reactivate_create", "summary": "Réactiver l'abonnement", "description": "Réactive un abonnement marqué pour annulation.", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["Subscriptions"]}, "parameters": []}, "/api/subscriptions/revenue/monthly/": {"get": {"operationId": "api_subscriptions_revenue_monthly_list", "summary": "Revenus du mois en cours", "description": "Revenus du mois en cours (abonnements + dons).", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "object", "properties": {"month": {"type": "string"}, "subscriptions_total": {"type": "number"}, "subscriptions_count": {"type": "integer"}, "donations_total": {"type": "number"}, "donations_count": {"type": "integer"}, "total": {"type": "number"}, "currency": {"type": "string"}}}}}, "tags": ["Revenue"]}, "parameters": []}, "/api/subscriptions/status/": {"get": {"operationId": "api_subscriptions_status_list", "summary": "État de l'abonnement", "description": "État de l'abonnement de l'utilisateur.", "parameters": [], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/UserSubscription"}}}, "tags": ["Subscriptions"]}, "parameters": []}, "/api/subscriptions/upgrade/": {"post": {"operationId": "api_subscriptions_upgrade_create", "summary": "Upgrade de plan", "description": "Upgrade le plan (proratisé).", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/Upgrade"}}], "responses": {"200": {"description": "OK"}}, "tags": ["Subscriptions"]}, "parameters": []}, "/api/support/staff/tickets/": {"get": {"operationId": "api_support_staff_tickets_list", "description": "", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/support/staff/tickets/{ticket_id}/": {"get": {"operationId": "api_support_staff_tickets_read", "description": "", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "delete": {"operationId": "api_support_staff_tickets_delete", "description": "", "parameters": [], "responses": {"204": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "ticket_id", "in": "path", "required": true, "type": "string"}]}, "/api/support/staff/tickets/{ticket_id}/reply/": {"post": {"operationId": "api_support_staff_tickets_reply_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "ticket_id", "in": "path", "required": true, "type": "string"}]}, "/api/support/staff/tickets/{ticket_id}/status/": {"post": {"operationId": "api_support_staff_tickets_status_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "ticket_id", "in": "path", "required": true, "type": "string"}]}, "/api/support/tickets/": {"get": {"operationId": "api_support_tickets_list", "description": "GET /api/support/tickets/ — Liste des tickets du user", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/support/tickets/create/": {"post": {"operationId": "api_support_tickets_create_create", "description": "POST /api/support/tickets/create/ — Créer un ticket", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/api/support/tickets/{ticket_id}/": {"get": {"operationId": "api_support_tickets_read", "description": "GET /api/support/tickets/{id}/ — Détail d'un ticket", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "ticket_id", "in": "path", "required": true, "type": "string"}]}, "/api/support/tickets/{ticket_id}/close/": {"post": {"operationId": "api_support_tickets_close_create", "description": "POST /api/support/tickets/{id}/close/", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "ticket_id", "in": "path", "required": true, "type": "string"}]}, "/api/support/tickets/{ticket_id}/reopen/": {"post": {"operationId": "api_support_tickets_reopen_create", "description": "POST /api/support/tickets/{id}/reopen/", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "ticket_id", "in": "path", "required": true, "type": "string"}]}, "/api/support/tickets/{ticket_id}/reply/": {"post": {"operationId": "api_support_tickets_reply_create", "description": "POST /api/support/tickets/{id}/reply/ — Répondre à un ticket", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": [{"name": "ticket_id", "in": "path", "required": true, "type": "string"}]}, "/api/telemetry/heartbeat/": {"post": {"operationId": "api_telemetry_heartbeat_create", "description": "", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"type": "object", "properties": {"session_uuid": {"type": "string"}}}}], "responses": {"200": {"description": "Updated"}}, "tags": ["api"]}, "parameters": []}, "/api/telemetry/shutdown/": {"post": {"operationId": "api_telemetry_shutdown_create", "description": "", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"type": "object", "properties": {"session_uuid": {"type": "string"}, "closed_cleanly": {"type": "boolean"}}}}], "responses": {"200": {"description": "Updated"}}, "tags": ["api"]}, "parameters": []}, "/api/telemetry/startup/": {"post": {"operationId": "api_telemetry_startup_create", "description": "", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"type": "object", "properties": {"session_uuid": {"type": "string"}, "app_version": {"type": "string"}, "startup_time_ms": {"type": "integer"}, "device": {"type": "object"}}}}], "responses": {"201": {"description": "Created"}}, "tags": ["api"]}, "parameters": []}, "/api/webhooks/shop/": {"post": {"operationId": "api_webhooks_shop_create", "description": "Webhook appelé par Stripe après paiement.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["api"]}, "parameters": []}, "/auth/api/cinebig/key-token/{id}/": {"get": {"operationId": "auth_api_cinebig_key-token_read", "description": "GET /auth/api/cinebig/key-token/<id>/ — key-token éphémère (~60s) pour le loader hls.js.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/auth/api/cinebig/play/{id}/": {"get": {"operationId": "auth_api_cinebig_play_read", "description": "GET /auth/api/cinebig/play/<id>/ — URL de lecture signée (?t=...).", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/auth/api/cinefuse/catalog/": {"get": {"operationId": "auth_api_cinefuse_catalog_list", "description": "GET /auth/api/cinefuse/catalog/ — TOUT le catalogue CineFuse (toutes les pages,\npas juste la première), filtré aux entrées dont au moins une source vidéo vient\nde vidzy / fsvid / cdn.ohlatuile / cdn.novapulse.im / cinebig.\n\nRéponse VOLONTAIREMENT légère (slug + titre + poster seulement) — le launcher\ngarde tout le catalogue en mémoire pour la page Films & Séries, donc pas question\nd'y traîner l'arbre saisons→épisodes→sources ou les champs overview/backdrop.\nLe détail complet est chargé à la demande sur la fiche (movies/{slug}, tv/{slug}).\n\nBoucle sur /api/movies et /api/series avec limit=100 jusqu'à épuiser\ntotal_results. Résultat mis en cache 10 min.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/cinefuse/continue/": {"get": {"operationId": "auth_api_cinefuse_continue_list", "description": "GET /auth/api/cinefuse/continue/ — non terminés (<95%), triés par vu récemment.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/cinefuse/history/": {"get": {"operationId": "auth_api_cinefuse_history_list", "description": "GET /auth/api/cinefuse/history/ — tout ce qui a été regardé, terminé ou non.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/cinefuse/movies/{slug}/progress/": {"post": {"operationId": "auth_api_cinefuse_movies_progress_create", "description": "POST /auth/api/cinefuse/movies/<slug>/progress/ — body {position, duration}.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["auth"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/auth/api/cinefuse/movies/{slug}/video/": {"get": {"operationId": "auth_api_cinefuse_movies_video_list", "description": "GET /auth/api/cinefuse/movies/<slug>/video/ — sources + position de reprise.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/auth/api/cinefuse/tv/{slug}/episode/{episode_id}/progress/": {"post": {"operationId": "auth_api_cinefuse_tv_episode_progress_create", "description": "POST /auth/api/cinefuse/tv/<slug>/episode/<episode_id>/progress/ — body {position, duration}.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["auth"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}, {"name": "episode_id", "in": "path", "required": true, "type": "string"}]}, "/auth/api/cinefuse/tv/{slug}/episode/{episode_id}/video/": {"get": {"operationId": "auth_api_cinefuse_tv_episode_video_list", "description": "GET /auth/api/cinefuse/tv/<slug>/episode/<episode_id>/video/ — pas d'endpoint\nstream dédié côté CineFuse pour les épisodes : les sources sont nichées dans\n/api/tv/{slug} -> seasons[].episodes[].video_links, on va les y chercher.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}, {"name": "episode_id", "in": "path", "required": true, "type": "string"}]}, "/auth/api/cinefuse/{path}": {"get": {"operationId": "auth_api_cinefuse_read", "summary": "GET /auth/api/cinefuse/<path>/ — proxy authentifié vers l'API CineFuse.", "description": "Le launcher appelle CETTE route avec le JWT JeuxCracks de l'utilisateur ;\nle backend ajoute la clé API CineFuse + le User-Agent obligatoire\n(Cloudflare renvoie 403 sans) et relaie la requête. La clé CINEFUSE_API_KEY\nne quitte JAMAIS le serveur — jamais distribuée dans le launcher (un .exe\nbundlé est extractible par n'importe qui).", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": [{"name": "path", "in": "path", "required": true, "type": "string"}]}, "/auth/api/create_user/": {"post": {"operationId": "auth_api_create_user_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/login/": {"post": {"operationId": "auth_api_login_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/suggestions/": {"get": {"operationId": "auth_api_suggestions_list", "description": "Page publique des suggestions : GET /auth/api/suggestions/\nFiltrable par statut : GET /auth/api/suggestions/?status=pending", "parameters": [{"name": "page", "in": "query", "description": "A page number within the paginated result set.", "required": false, "type": "integer"}], "responses": {"200": {"description": "", "schema": {"required": ["count", "results"], "type": "object", "properties": {"count": {"type": "integer"}, "next": {"type": "string", "format": "uri", "x-nullable": true}, "previous": {"type": "string", "format": "uri", "x-nullable": true}, "results": {"type": "array", "items": {"$ref": "#/definitions/SuggestionList"}}}}}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/token/": {"post": {"operationId": "auth_api_token_create", "description": "Takes a set of user credentials and returns an access and refresh JSON web\ntoken pair to prove the authentication of those credentials.", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/TokenObtainPair"}}], "responses": {"201": {"description": "", "schema": {"$ref": "#/definitions/TokenObtainPair"}}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/token/refresh/": {"post": {"operationId": "auth_api_token_refresh_create", "description": "Takes a refresh type JSON web token and returns an access type JSON web\ntoken if the refresh token is valid.", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/TokenRefresh"}}], "responses": {"201": {"description": "", "schema": {"$ref": "#/definitions/TokenRefresh"}}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/token/verify/": {"post": {"operationId": "auth_api_token_verify_create", "description": "Takes a token and indicates if it is valid.  This view provides no\ninformation about a token's fitness for a particular use.", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/TokenVerify"}}], "responses": {"201": {"description": "", "schema": {"$ref": "#/definitions/TokenVerify"}}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/user/me": {"get": {"operationId": "auth_api_user_me_list", "description": "", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/user/me/change": {"put": {"operationId": "auth_api_user_me_change_update", "description": "", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/user/me/delete": {"delete": {"operationId": "auth_api_user_me_delete_delete", "description": "", "parameters": [], "responses": {"204": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/user/me/fav": {"get": {"operationId": "auth_api_user_me_fav_list", "description": "", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/user/me/picture": {"post": {"operationId": "auth_api_user_me_picture_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/user/me/reset_password": {"post": {"operationId": "auth_api_user_me_reset_password_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/user/me/sug": {"post": {"operationId": "auth_api_user_me_sug_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/user/me/suggestion": {"post": {"operationId": "auth_api_user_me_suggestion_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/api/user/me/suggestion/quota/": {"get": {"operationId": "auth_api_user_me_suggestion_quota_list", "description": "GET /auth/api/user/me/suggestion/quota/ — suggestions restantes ce mois-ci.", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/cinefuse/unlink/": {"post": {"operationId": "auth_cinefuse_unlink_create", "description": "POST /auth/cinefuse/unlink/ — retire la liaison CineFuse du compte.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/auth/discord/unlink/": {"post": {"operationId": "auth_discord_unlink_create", "description": "POST /auth/discord/unlink/ — retire la liaison Discord du compte.", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["auth"]}, "parameters": []}, "/multilinks_B/api/create/": {"post": {"operationId": "multilinks_B_api_create_create", "description": "Crée une nouvelle page MultiLinks via l'API", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["multilinks_B"]}, "parameters": []}, "/multilinks_B/api/delete/{slug}/": {"delete": {"operationId": "multilinks_B_api_delete_delete", "description": "Supprime une page via l'API", "parameters": [], "responses": {"204": {"description": ""}}, "tags": ["multilinks_B"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/multilinks_B/api/links/{id}/": {"delete": {"operationId": "multilinks_B_api_links_delete", "description": "", "parameters": [], "responses": {"204": {"description": ""}}, "tags": ["multilinks_B"]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/multilinks_B/api/list/": {"get": {"operationId": "multilinks_B_api_list_list", "description": "Liste toutes les pages publiques ou les pages de l'utilisateur", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["multilinks_B"]}, "parameters": []}, "/multilinks_B/api/pages/": {"get": {"operationId": "multilinks_B_api_pages_list", "description": "", "parameters": [{"name": "page", "in": "query", "description": "A page number within the paginated result set.", "required": false, "type": "integer"}], "responses": {"200": {"description": "", "schema": {"required": ["count", "results"], "type": "object", "properties": {"count": {"type": "integer"}, "next": {"type": "string", "format": "uri", "x-nullable": true}, "previous": {"type": "string", "format": "uri", "x-nullable": true}, "results": {"type": "array", "items": {"$ref": "#/definitions/MultiLinkPage"}}}}}}, "tags": ["multilinks_B"]}, "post": {"operationId": "multilinks_B_api_pages_create", "description": "", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/MultiLinkPage"}}], "responses": {"201": {"description": "", "schema": {"$ref": "#/definitions/MultiLinkPage"}}}, "tags": ["multilinks_B"]}, "parameters": []}, "/multilinks_B/api/pages/{id}/": {"get": {"operationId": "multilinks_B_api_pages_read", "description": "", "parameters": [], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/MultiLinkPage"}}}, "tags": ["multilinks_B"]}, "put": {"operationId": "multilinks_B_api_pages_update", "description": "", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/MultiLinkPage"}}], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/MultiLinkPage"}}}, "tags": ["multilinks_B"]}, "patch": {"operationId": "multilinks_B_api_pages_partial_update", "description": "", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/MultiLinkPage"}}], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/MultiLinkPage"}}}, "tags": ["multilinks_B"]}, "delete": {"operationId": "multilinks_B_api_pages_delete", "description": "", "parameters": [], "responses": {"204": {"description": ""}}, "tags": ["multilinks_B"]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/multilinks_B/api/pages/{slug}/": {"get": {"operationId": "multilinks_B_api_pages_read", "description": "", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["multilinks_B"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/multilinks_B/api/pages/{slug}/links/": {"post": {"operationId": "multilinks_B_api_pages_links_create", "description": "", "parameters": [], "responses": {"201": {"description": ""}}, "tags": ["multilinks_B"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}, "/multilinks_B/api/update/{slug}/": {"put": {"operationId": "multilinks_B_api_update_update", "description": "Met à jour une page existante via l'API", "parameters": [], "responses": {"200": {"description": ""}}, "tags": ["multilinks_B"]}, "parameters": [{"name": "slug", "in": "path", "required": true, "type": "string"}]}}, "definitions": {"Category": {"required": ["name", "slug"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "name": {"title": "Name", "type": "string", "maxLength": 100, "minLength": 1}, "slug": {"title": "Slug", "type": "string", "format": "slug", "pattern": "^[-a-zA-Z0-9_]+$", "maxLength": 100, "minLength": 1}, "icon": {"title": "Icon", "type": "string", "maxLength": 50}, "games_count": {"title": "Games count", "type": "string", "readOnly": true}}}, "GameList": {"required": ["title", "slug"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "title": {"title": "Title", "type": "string", "maxLength": 255, "minLength": 1}, "slug": {"title": "Slug", "type": "string", "format": "slug", "pattern": "^[-a-zA-Z0-9_]+$", "maxLength": 255, "minLength": 1}, "header": {"title": "Header", "type": "string", "readOnly": true, "x-nullable": true, "format": "uri"}, "categories": {"type": "array", "items": {"type": "string"}, "readOnly": true, "uniqueItems": true}, "views": {"title": "Views", "type": "integer", "maximum": 2147483647, "minimum": 0}, "likes": {"title": "Likes", "type": "integer", "maximum": 2147483647, "minimum": 0}, "is_liked": {"title": "Is liked", "type": "string", "readOnly": true}, "is_favorited": {"title": "Is favorited", "type": "string", "readOnly": true}, "versions_count": {"title": "Versions count", "type": "string", "readOnly": true}, "latest_version": {"title": "Latest version", "type": "string", "readOnly": true}, "is_online": {"title": "Is online", "type": "boolean", "readOnly": true}, "published_at": {"title": "Published at", "type": "string", "format": "date-time", "readOnly": true}}}, "GameCreateUpdate": {"required": ["title", "slug"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "steam_id": {"title": "Steam id", "type": "string", "maxLength": 20, "x-nullable": true}, "title": {"title": "Title", "type": "string", "maxLength": 255, "minLength": 1}, "slug": {"title": "Slug", "type": "string", "format": "slug", "pattern": "^[-a-zA-Z0-9_]+$", "maxLength": 255, "minLength": 1}, "description": {"title": "Description", "type": "string"}, "description_short": {"title": "Description short", "type": "string", "maxLength": 500}, "description_fr": {"title": "Description fr", "description": "Description FR générée par IA (Claude)", "type": "string"}, "header": {"title": "Header", "type": "string", "readOnly": true, "x-nullable": true, "format": "uri"}, "background": {"title": "Background", "type": "string", "readOnly": true, "x-nullable": true, "format": "uri"}, "video": {"title": "Video", "type": "string", "format": "uri", "maxLength": 200}, "screenshots": {"title": "Screenshots", "type": "object"}, "developer": {"title": "Developer", "type": "string", "maxLength": 255}, "publisher": {"title": "Publisher", "type": "string", "maxLength": 255}, "requirements": {"title": "Requirements", "type": "object"}, "source": {"title": "Source", "type": "object"}, "views": {"title": "Views", "type": "integer", "maximum": 2147483647, "minimum": 0}, "likes": {"title": "Likes", "type": "integer", "maximum": 2147483647, "minimum": 0}, "favorites_count": {"title": "Favorites count", "type": "integer", "maximum": 2147483647, "minimum": 0}, "downloads_count": {"title": "Downloads count", "type": "integer", "maximum": 2147483647, "minimum": 0}, "release_date": {"title": "Release date", "type": "string", "format": "date", "x-nullable": true}, "published_at": {"title": "Published at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}, "is_published": {"title": "Is published", "type": "boolean"}, "categories": {"type": "array", "items": {"type": "integer"}, "uniqueItems": true}, "tags": {"type": "array", "items": {"type": "integer"}, "uniqueItems": true}}}, "Tag": {"required": ["name"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "name": {"title": "Name", "type": "string", "maxLength": 100, "minLength": 1}}}, "GameVersionPublic": {"required": ["source"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "source": {"title": "Source", "type": "string", "enum": ["onlinefix", "steamrip", "dodi", "fitgirl", "other"]}, "version": {"title": "Version", "type": "string", "maxLength": 100}, "size": {"title": "Size", "description": "Taille en octets", "type": "integer", "maximum": 9223372036854775807, "minimum": -9223372036854775808}, "size_formatted": {"title": "Size formatted", "type": "string", "readOnly": true, "minLength": 1}, "size_raw": {"title": "Size raw", "description": "Taille brute du JSON (ex: 49.5 GB)", "type": "string", "maxLength": 50}, "is_online": {"title": "Is online", "description": "Support multijoueur cracké", "type": "boolean"}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}}}, "GameDetail": {"required": ["title", "slug"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "steam_id": {"title": "Steam id", "type": "string", "maxLength": 20, "x-nullable": true}, "title": {"title": "Title", "type": "string", "maxLength": 255, "minLength": 1}, "slug": {"title": "Slug", "type": "string", "format": "slug", "pattern": "^[-a-zA-Z0-9_]+$", "maxLength": 255, "minLength": 1}, "description": {"title": "Description", "type": "string"}, "description_short": {"title": "Description short", "type": "string", "maxLength": 500}, "description_fr": {"title": "Description fr", "description": "Description FR générée par IA (Claude)", "type": "string"}, "header": {"title": "Header", "type": "string", "readOnly": true, "x-nullable": true, "format": "uri"}, "background": {"title": "Background", "type": "string", "readOnly": true, "x-nullable": true, "format": "uri"}, "video": {"title": "Video", "type": "string", "format": "uri", "maxLength": 200}, "screenshots": {"title": "Screenshots", "type": "object"}, "categories": {"type": "array", "items": {"$ref": "#/definitions/Category"}, "readOnly": true}, "tags": {"type": "array", "items": {"$ref": "#/definitions/Tag"}, "readOnly": true}, "developer": {"title": "Developer", "type": "string", "maxLength": 255}, "publisher": {"title": "Publisher", "type": "string", "maxLength": 255}, "requirements": {"title": "Requirements", "type": "object"}, "source": {"title": "Source", "type": "object"}, "views": {"title": "Views", "type": "integer", "maximum": 2147483647, "minimum": 0}, "likes": {"title": "Likes", "type": "integer", "maximum": 2147483647, "minimum": 0}, "favorites_count": {"title": "Favorites count", "type": "integer", "maximum": 2147483647, "minimum": 0}, "downloads_count": {"title": "Downloads count", "type": "integer", "maximum": 2147483647, "minimum": 0}, "release_date": {"title": "Release date", "type": "string", "format": "date", "x-nullable": true}, "published_at": {"title": "Published at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}, "is_liked": {"title": "Is liked", "type": "string", "readOnly": true}, "is_favorited": {"title": "Is favorited", "type": "string", "readOnly": true}, "versions": {"type": "array", "items": {"$ref": "#/definitions/GameVersionPublic"}, "readOnly": true}}}, "GameVersion": {"required": ["source"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "source": {"title": "Source", "type": "string", "enum": ["onlinefix", "steamrip", "dodi", "fitgirl", "other"]}, "version": {"title": "Version", "type": "string", "maxLength": 100}, "size": {"title": "Size", "description": "Taille en octets", "type": "integer", "maximum": 9223372036854775807, "minimum": -9223372036854775808}, "size_formatted": {"title": "Size formatted", "type": "string", "readOnly": true, "minLength": 1}, "size_raw": {"title": "Size raw", "description": "Taille brute du JSON (ex: 49.5 GB)", "type": "string", "maxLength": 50}, "is_online": {"title": "Is online", "description": "Support multijoueur cracké", "type": "boolean"}, "download_links": {"title": "Download links", "type": "string", "readOnly": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}}}, "GameDownload": {"required": ["title"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "title": {"title": "Title", "type": "string", "maxLength": 255, "minLength": 1}, "versions": {"type": "array", "items": {"$ref": "#/definitions/GameVersion"}, "readOnly": true}}}, "UserShort": {"required": ["pseudo", "email"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "pseudo": {"title": "Pseudo", "type": "string", "maxLength": 30, "minLength": 1}, "email": {"title": "Email", "type": "string", "format": "email", "maxLength": 254, "minLength": 1}, "profile_picture": {"title": "Profile picture", "type": "string", "readOnly": true}}}, "ChatMessage": {"required": ["content"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "sender": {"$ref": "#/definitions/UserShort"}, "receiver": {"$ref": "#/definitions/UserShort"}, "content": {"title": "Content", "type": "string", "minLength": 1}, "timestamp": {"title": "Timestamp", "type": "string", "format": "date-time", "readOnly": true}, "is_read": {"title": "Is read", "type": "boolean"}}}, "Friendship": {"type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "friend": {"title": "Friend", "type": "string", "readOnly": true}, "status": {"title": "Status", "type": "string", "enum": ["PENDING", "ACCEPTED", "BLOCKED"]}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}}}, "UserNotification": {"required": ["title", "message"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "title": {"title": "Title", "type": "string", "maxLength": 255, "minLength": 1}, "message": {"title": "Message", "type": "string", "minLength": 1}, "link": {"title": "Link", "type": "string", "maxLength": 512, "x-nullable": true}, "type": {"title": "Type", "type": "string", "enum": ["UPDATE", "PROMO", "SYSTEM", "SOCIAL"]}, "is_read": {"title": "Is read", "type": "boolean"}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}}}, "Cancel": {"type": "object", "properties": {"immediately": {"title": "Immediately", "description": "True = annulation immédiate, False = fin de période", "type": "boolean", "default": false}}}, "ChangeBilling": {"required": ["price_id"], "type": "object", "properties": {"price_id": {"title": "Price id", "description": "Stripe Price ID de la nouvelle période de facturation", "type": "string", "minLength": 1}}}, "Checkout": {"required": ["price_id"], "type": "object", "properties": {"price_id": {"title": "Price id", "description": "Stripe Price ID", "type": "string", "minLength": 1}}}, "Donate": {"required": ["amount"], "type": "object", "properties": {"amount": {"title": "Amount", "description": "Montant en centimes (minimum 100 = 1€)", "type": "integer", "minimum": 100}, "message": {"title": "Message", "description": "Message optionnel du donateur", "type": "string", "maxLength": 500}}}, "Donation": {"required": ["amount"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "amount": {"title": "Amount", "description": "Montant en centimes", "type": "integer", "maximum": 2147483647, "minimum": -2147483648}, "amount_formatted": {"title": "Amount formatted", "type": "string", "readOnly": true, "minLength": 1}, "currency": {"title": "Currency", "type": "string", "maxLength": 3, "minLength": 1}, "status": {"title": "Status", "type": "string", "enum": ["pending", "completed", "failed", "refunded"]}, "message": {"title": "Message", "description": "Message du donateur (optionnel)", "type": "string"}, "receipt_url": {"title": "Receipt url", "type": "string", "format": "uri", "maxLength": 500}, "username": {"title": "Username", "type": "string", "readOnly": true, "minLength": 1}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}}}, "Upgrade": {"required": ["price_id"], "type": "object", "properties": {"price_id": {"title": "Price id", "description": "Stripe Price ID du nouveau plan", "type": "string", "minLength": 1}}}, "GiftCheckout": {"required": ["plan", "duration"], "type": "object", "properties": {"plan": {"title": "Plan", "type": "string", "enum": ["supporter", "vip"]}, "duration": {"title": "Duration", "type": "integer", "enum": [1, 3, 6, 12]}, "recipient_user_id": {"title": "Recipient user id", "type": "integer", "x-nullable": true}, "message": {"title": "Message", "type": "string", "default": "", "maxLength": 280}, "anonymous": {"title": "Anonymous", "type": "boolean", "default": false}}}, "Gift": {"required": ["plan_type", "duration_days", "amount"], "type": "object", "properties": {"code": {"title": "Code", "type": "string", "readOnly": true, "minLength": 1, "x-nullable": true}, "plan_type": {"title": "Plan type", "type": "string", "maxLength": 10, "minLength": 1}, "duration_days": {"title": "Duration days", "type": "integer", "maximum": 2147483647, "minimum": -2147483648}, "amount": {"title": "Amount", "type": "string", "format": "decimal"}, "currency": {"title": "Currency", "type": "string", "maxLength": 3, "minLength": 1}, "status": {"title": "Status", "type": "string", "enum": ["pending", "paid", "redeemed", "failed"]}, "recipient_pseudo": {"title": "Recipient pseudo", "type": "string", "readOnly": true, "minLength": 1}, "message": {"title": "Message", "type": "string", "maxLength": 280}, "is_anonymous": {"title": "Is anonymous", "type": "boolean"}, "redeemed_at": {"title": "Redeemed at", "type": "string", "format": "date-time", "x-nullable": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}}}, "GiftRedeem": {"required": ["code"], "type": "object", "properties": {"code": {"title": "Code", "type": "string", "maxLength": 32, "minLength": 1}}}, "Invoice": {"required": ["stripe_invoice_id", "amount", "status"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "stripe_invoice_id": {"title": "Stripe invoice id", "type": "string", "maxLength": 255, "minLength": 1}, "amount": {"title": "Amount", "description": "Montant en centimes", "type": "integer", "maximum": 2147483647, "minimum": -2147483648}, "amount_formatted": {"title": "Amount formatted", "type": "string", "readOnly": true}, "currency": {"title": "Currency", "type": "string", "maxLength": 3, "minLength": 1}, "status": {"title": "Status", "type": "string", "maxLength": 30, "minLength": 1}, "invoice_url": {"title": "Invoice url", "type": "string", "format": "uri", "maxLength": 200}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}}}, "SubscriptionPlan": {"required": ["name", "plan_type", "billing_period", "stripe_price_id"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "name": {"title": "Name", "type": "string", "maxLength": 100, "minLength": 1}, "plan_type": {"title": "Plan type", "type": "string", "enum": ["basic", "pro"]}, "billing_period": {"title": "Billing period", "type": "string", "enum": ["monthly", "quarterly", "yearly"]}, "stripe_price_id": {"title": "Stripe price id", "type": "string", "maxLength": 255, "minLength": 1}, "is_active": {"title": "Is active", "type": "boolean"}}}, "UserSubscription": {"type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "plan": {"$ref": "#/definitions/SubscriptionPlan"}, "status": {"title": "Status", "type": "string", "enum": ["active", "past_due", "canceled", "trialing", "incomplete"]}, "stripe_subscription_id": {"title": "Stripe subscription id", "type": "string", "maxLength": 255, "x-nullable": true}, "current_period_start": {"title": "Current period start", "type": "string", "format": "date-time", "x-nullable": true}, "current_period_end": {"title": "Current period end", "type": "string", "format": "date-time", "x-nullable": true}, "source": {"title": "Source", "type": "string", "maxLength": 20}, "cancel_at_period_end": {"title": "Cancel at period end", "type": "boolean"}, "is_active_subscription": {"title": "Is active subscription", "type": "boolean", "readOnly": true}, "days_remaining": {"title": "Days remaining", "description": "Jours restants avant expiration. null si pas de date de fin (à vie / non défini).", "type": "string", "readOnly": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}}}, "SuggestionList": {"required": ["title"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "title": {"title": "Title", "type": "string", "maxLength": 255, "minLength": 1}, "steam_app_id": {"title": "Steam app id", "type": "string", "maxLength": 32, "x-nullable": true}, "steam_name": {"title": "Steam name", "type": "string", "maxLength": 255, "x-nullable": true}, "cover_url": {"title": "Cover url", "type": "string", "format": "uri", "maxLength": 500, "x-nullable": true}, "status": {"title": "Status", "type": "string", "enum": ["pending", "added", "rejected", "upcoming"]}, "suggested_by": {"title": "Suggested by", "type": "string", "readOnly": true, "minLength": 1}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}}}, "TokenObtainPair": {"required": ["email", "password"], "type": "object", "properties": {"email": {"title": "Email", "type": "string", "minLength": 1}, "password": {"title": "Password", "type": "string", "minLength": 1}}}, "TokenRefresh": {"required": ["refresh"], "type": "object", "properties": {"refresh": {"title": "Refresh", "type": "string", "minLength": 1}, "access": {"title": "Access", "type": "string", "readOnly": true, "minLength": 1}}}, "TokenVerify": {"required": ["token"], "type": "object", "properties": {"token": {"title": "Token", "type": "string", "minLength": 1}}}, "Link": {"required": ["title", "url"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "title": {"title": "Title", "type": "string", "maxLength": 200, "minLength": 1}, "url": {"title": "Url", "type": "string", "format": "uri", "maxLength": 200, "minLength": 1}, "order": {"title": "Order", "type": "integer", "maximum": 2147483647, "minimum": -2147483648}}}, "MultiLinkPage": {"required": ["title"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "title": {"title": "Title", "type": "string", "maxLength": 200, "minLength": 1}, "slug": {"title": "Slug", "type": "string", "format": "slug", "pattern": "^[-a-zA-Z0-9_]+$", "maxLength": 255}, "description": {"title": "Description", "type": "string", "x-nullable": true}, "views": {"title": "Views", "type": "integer", "maximum": 2147483647, "minimum": -2147483648}, "background_color": {"title": "Background color", "type": "string", "maxLength": 7, "minLength": 1}, "text_color": {"title": "Text color", "type": "string", "maxLength": 7, "minLength": 1}, "button_color": {"title": "Button color", "type": "string", "maxLength": 7, "minLength": 1}, "button_text_color": {"title": "Button text color", "type": "string", "maxLength": 7, "minLength": 1}, "accent_color": {"title": "Accent color", "type": "string", "maxLength": 7, "minLength": 1}, "layout_style": {"title": "Layout style", "type": "string", "enum": ["classic", "modern", "minimal", "cards", "gradient", "glass", "neon", "retro", "brutalist", "elegant"]}, "button_style": {"title": "Button style", "type": "string", "enum": ["filled", "outline", "soft", "glass", "gradient", "neon", "3d", "minimal", "shadow", "animated"]}, "show_social_icons": {"title": "Show social icons", "type": "boolean"}, "enable_animations": {"title": "Enable animations", "type": "boolean"}, "is_public": {"title": "Is public", "type": "boolean"}, "links": {"type": "array", "items": {"$ref": "#/definitions/Link"}, "readOnly": true}}}}}