REST API FR - Kheopsian/Hydranos GitHub Wiki
S'applique à Hydranos 4.4.
Pour scripter Hydranos : toutes les routes de l'API native (/api/*) en 4.4, celles qui fonctionnent, celles qui sont des bouchons, celles qui ont été retirées, des exemples curl. L'API compatible qBittorrent (/api/v2/*) est documentée sur Shim qBittorrent & automatisation, et l'endpoint MCP sur Serveur MCP.
Cette page est la carte. Les corps complets des requêtes et des réponses sont dans le fichier docs/API.md du dépôt ; les pages liées depuis chaque section expliquent ce que font les réglages.
Un seul port, 8199 par défaut ([daemon] api_port), sert l'interface web, /api, le shim qBittorrent et /mcp. Les exemples utilisent :
export HY=http://hydranos.example.org:8199
export KEY=YOUR_API_KEYLes corps et les réponses sont en JSON, sauf mention contraire dans une ligne. Les réponses de plus de 32 octets sont compressées en gzip quand le client l'accepte (curl --compressed).
Il n'existe qu'un seul identifiant, la clé API ([daemon] api_key, 48 caractères hexadécimaux, générée au premier démarrage). Où la trouver, comment la renouveler et comment exposer Hydranos sans risque : Sécurité & accès.
| Comment la clé circule | Exemple | Remarques |
|---|---|---|
En-tête X-Api-Key
|
-H "X-Api-Key: $KEY" |
La méthode normale. |
Paramètre de requête apikey
|
"$HY/api/status?apikey=$KEY" |
Pour les clients qui ne peuvent pas définir d'en-têtes. Finit dans les journaux du proxy. |
Cookie de session SID
|
issu de POST /api/v2/auth/login
|
Formulaire username + password (mot de passe admin ou clé API). Ouvre toute l'API native. Expire après 3600 s d'inactivité ; perdu au redémarrage. |
Authorization: Bearer |
-H "Authorization: Bearer $KEY" |
Accepté par /mcp uniquement. |
POST /api/login (JSON {"username","password"}) ne pose pas de cookie : il renvoie {"api_key": "..."}, que l'interface web envoie ensuite en X-Api-Key. Un api_key vide dans la configuration refuse tous les appelants.
Formes de refus (testez le code de statut, pas le texte) :
| Où | Statut | Corps |
|---|---|---|
/api/* (presque toutes les routes) |
401 |
{"error":"Invalid or missing API key"} |
/api/selection/*, /api/network/egress
|
401 |
{"error":"unauthorized"} |
/api/v2/* (shim qBittorrent) |
403 |
texte brut Forbidden. (Sonarr et Radarr attendent un 403 avant la connexion) |
/mcp |
401 |
JSON comme ci-dessus + en-tête WWW-Authenticate: Bearer
|
POST /api/nodes/register |
401 |
{"error":"enrolment token unknown, already used, or expired"} |
POST /api/setup |
409 dès qu'un admin existe ; 403 si le pair de la socket n'est ni en loopback ni sur un réseau privé, ou si un pair privé (un reverse proxy) désigne un client public dans X-Forwarded-For
|
JSON |
Routes publiques (sans clé) : /health, /metrics, /, /static/*, /changelog.md, /install.sh, GET|POST /api/setup, POST /api/login, GET /api/startup, POST /api/v2/auth/login, POST /api/v2/auth/logout, POST /api/nodes/register (jeton d'enrôlement à la place de la clé), et POST /api/auth/api-key/confirm (la clé en attente d'une rotation à la place de la clé actuelle, voir Nœuds).
Le port s'ouvre avant que le catalogue soit chargé. Tant que le chargement n'est pas fini, seuls /, /static/*, /health ("status":"starting", 200), /metrics, GET /api/startup et GET /api/setup répondent. Tout autre chemin, /api/v2/* et /mcp compris, répond 503 avec Retry-After: 5 et {"error":"Hydranos is starting (<phase>): N of M torrents restored","startup":{…}} ; une autre méthode sur l'un des chemins ci-dessus (par exemple POST /api/setup) n'est pas routée et est refusée. Interrogez GET /api/startup jusqu'à "ready":true, ou réessayez après Retry-After. Les phases : Exploiter Hydranos.
Les erreurs sont du JSON {"error": "<message>"}, parfois avec d'autres champs :
-
400: champ invalide ou manquant (les corps stricts nomment le champ inconnu). -
404:{"error":"torrent not found"}, ou moteur/nœud/job inexistant. -
405: le chemin existe, mais pas avec cette méthode (par exemplePOST /api/race/settingsdepuis la 4.4). -
409: refusé à cause de l'état. Les déplacements de données ajoutent"reason"(hardlinks,space,shared,destination_taken, …) et unplan; une sélection par filtre qui a grossi répond"reason":"grew"avec le nouveaucount; ajouter un torrent déjà présent répond 409. -
410: une route 3.x retirée en 4.4 ; le corps nomme la remplaçante (Routes retirées en 4.4). -
503+Retry-After: 5: démarrage en cours (ci-dessus).
POST /api/torrents répond {"error","targets"} avec un statut qui dit pourquoi :
| Statut | Quand |
|---|---|
400 |
Corps qui n'est pas du JSON ; pas exactement un seul champ parmi torrent_path, torrent_url, magnet_uri ; engine ou mode inconnu ; .torrent illisible ou non récupéré (l'URL apparaît sous la forme <url> : elle peut contenir une passkey) ; pas de chemin de sauvegarde (aucun envoyé, aucune catégorie qui en a un) ; magnet invalide (y compris un info hash mal formé, absent ou uniquement v2). |
404 |
torrent_path n'existe pas sur l'hôte Hydranos. |
409 |
Déjà ajouté (torrent already added), et les autres refus : race disk full: … et, avec [dedup] path_collision = "refuse", N file(s) of this torrent are already another torrent's with other bytes …. |
500 |
Une panne du store seulement (store: …). |
POST /api/torrents/upload répond aux mêmes refus par un 400, et par 409 pour déjà ajouté. Testez la classe du statut, et lisez error pour la raison.
-
:info_hashest le hash v1 hexadécimal de 40 caractères. Certaines routes résolvent un préfixe plus court et agissent sur la première correspondance : envoyez toujours le hash complet. - Les moteurs sont adressés par identifiant sous
/api/engines/:id/...;/api/race/...et/api/hoard/...sont des alias pour les deux moteurs qui existent toujours. Exception :GET /api/race/torrentsliste tous les moteurs de rôle race. - Le même torrent peut être dans plusieurs moteurs (une copie par moteur). Les routes de torrent choisissent une copie avec
?engine=<id>. L'ancienne graphie?agent=(un nom de la 3.x) est aussi acceptée :localou vide signifie la valeur par défaut,local-<id>signifie le moteur<id>. - Les lignes de liste portent une étiquette dans le champ
agent(nom historique) :local-<engine>pour une copie locale,<node>-<engine>pour une ligne fusionnée depuis un nœud déclaré. Les routes par torrent répondent 404 pour une ligne de nœud ;/api/selection/*relaie l'action au nœud qui la détient.
Statut (champs : Supervision) :
curl -s -H "X-Api-Key: $KEY" "$HY/api/status"Les 100 premiers torrents hoard de la catégorie tv, les plus récents d'abord (filtre et pagination côté serveur) :
curl -s --compressed -H "X-Api-Key: $KEY" \
"$HY/api/hoard/page?category=tv&limit=100&sort=added_time"Créer une catégorie (il n'y a pas de chemin de sauvegarde par défaut, les ajouts en ont donc besoin d'un) :
curl -s -H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"name":"tv","save_path":"/data/tv","mode":"hoard"}' "$HY/api/categories"Ajouter un fichier .torrent avec une catégorie (multipart) :
curl -s -H "X-Api-Key: $KEY" \
-F "[email protected]" -F "category=tv" "$HY/api/torrents/upload"Ajoutez -F "seed_mode=true" pour seeder des données déjà sur disque sans les hacher (mode seed ; risques : Ajouter des torrents & données existantes).
Arrêter tous les torrents hoard de la catégorie old (une action groupée par filtre ; comptez d'abord, envoyez le compte comme expect) :
N=$(curl -s -H "X-Api-Key: $KEY" "$HY/api/hoard/page?category=old&limit=1" | jq .filtered)
curl -s -H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d "{\"selection\":{\"filter\":\"category=old\",\"view\":\"hoard\",\"expect\":$N},\"params\":{}}" \
"$HY/api/selection/stop"
# 202 {"job":"...","total":N} -> poll GET /api/selection/jobs/<job>Statut : ✓ fonctionne · ◐ fonctionne avec une réserve. Les routes bouchons n'apparaissent que dans Bouchons et routes retirées en 4.4.
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/api/torrents/upload |
POST multipart | Ajoute un .torrent. Partie fichier torrents, torrent ou file ; champs category, savepath/save_path, tags, engine ou mode (race/hoard), paused/stopped, skip_checking/seed_mode/skip_recheck, create_subfolder. Corps limité à 2 Mo. |
✓ |
/api/torrents |
POST JSON | Ajoute depuis exactement un champ parmi torrent_path (un fichier sur l'hôte Hydranos), torrent_url (récupéré par Hydranos, par la sortie du démon) ou magnet_uri ; plus category, save_path, tags, engine ou mode, stopped, seed_mode (ou skip_recheck), create_subfolder (par défaut [daemon] create_torrent_folder). Magnet → 202 {"info_hash","status":"resolving"}, avec seed_mode et stopped appliqués une fois résolu. Codes de statut : Erreurs ci-dessus. |
◐ certains refus sont des 500 |
/api/torrents/:info_hash |
DELETE | Supprime. ?delete_files=true efface les données ; ?engine= supprime une copie, sinon toutes. Les fichiers qu'un autre torrent lit encore sont gardés. Retire aussi un torrent qu'un moteur fait tourner sans ligne dans le store. |
✓ |
/api/torrents/:info_hash/{files,torrent} |
GET | Liste des fichiers (index, path, size, done, progress, priority, plus sequential, first_last_piece, complete) ; les octets du .torrent depuis le store. |
✓ |
/api/torrents/:info_hash/download-order |
GET, POST | Nouveau en 4.4. Priorités des fichiers (1, 6, 7 ; 0 → 409), sequential, first_last_piece (Ordre de téléchargement). |
✓ |
/api/torrents/:info_hash/limits |
GET, POST | Nouveau en 4.4. Plafonds de débit propres {"up_kib","down_kib"} (0 = aucun), en direct et enregistrés. |
✓ |
/api/torrents/:info_hash/share-limits |
GET, POST | Nouveau en 4.4. ratio_limit, seeding_time_limit, inactive_seeding_time_limit propres (-2 = ceux du moteur, -1 = aucun). |
✓ |
/api/torrents/:info_hash/trackers |
GET, POST | Lire / modifier. POST {"op":"add"|"remove","urls":[...]}, {"op":"replace","from","to"} ou {"op":"set","tiers":[ ["u1"], ["u2"] ]}. .../add-tracker prend {"url"}. |
✓ |
/api/torrents/:info_hash/reannounce |
POST | Annonce immédiate, une seule copie : celle de ?engine=, sinon le premier moteur qui la détient. 429 pendant le délai de 60 s. |
✓ |
/api/torrents/:info_hash/peers |
POST |
{"peers":["203.0.113.5:16172"]} : se connecter à ces pairs. |
✓ |
/api/torrents/:info_hash/copy |
POST |
{"engine":"vpn1"} : ajoute une seconde copie dans un autre moteur, mêmes fichiers. 409 tant que la source n'est pas complète ou est en cours de vérification. |
✓ |
/api/torrents/:info_hash/engine |
POST |
{"engine":"vpn1"} : déplace le torrent vers un autre moteur, les fichiers restent en place. ?engine= désigne la copie source. La cible reprend l'état de la source (pièces, trackers, compteurs, arrêté) avant que la source ne le lâche ; si l'un des deux refuse, rien ne change. |
✓ |
/api/torrents/:info_hash/graduate |
POST |
{"engine","category","save_path","allow_breaking_hardlinks":false} : met en file un job graduate (déplacement des données + changement de moteur). save_path vaut par défaut celui de la catégorie. Mêmes contrôles qu'un changement de catégorie (409 avec reason). |
✓ |
/api/torrents/add-defaults |
GET |
{"create_subfolder","skip_recheck"} : les valeurs de départ de l'onglet d'ajout (create_subfolder = [daemon] create_torrent_folder ; skip_recheck toujours false). |
✓ |
/api/torrents/export |
POST form |
format=zip|txt|csv, selection (JSON) ou hashes, strip_trackers=1. Renvoie un téléchargement en flux. |
✓ |
/api/{hoard,race}/torrents/:info_hash |
GET | Une ligne avec le détail en direct. | ✓ |
/api/{hoard,race}/torrents/:info_hash/category |
POST |
{"category","move_files":false,"allow_breaking_hardlinks":false}. Avec move_files, 202 + job (ou une graduation si le mode diffère). |
✓ |
/api/{hoard,race}/torrents/:info_hash/location |
POST |
Déplacer vers un dossier (Set location) : {"location":"/abs/path","allow_breaking_hardlinks":false}. 202 + job quand des octets bougent, 200 "moved":false s'ils y sont déjà. |
✓ |
/api/{hoard,race}/torrents/:info_hash/move-preview |
GET | Ce que ferait un déplacement, sans le faire. | ✓ |
/api/{hoard,race}/torrents/:info_hash/tags |
POST |
{"tags":[...]} remplace tout l'ensemble. |
✓ |
/api/{hoard,race}/torrents/:info_hash/{pause,resume} |
POST | Arrête / démarre un torrent. | ✓ |
/api/hoard/torrents/:info_hash/{pin,unpin} |
POST | Forcer le téléchargement (démarré, passe outre la file de téléchargement) / arrêter de forcer. | ✓ |
/api/hoard/torrents/:info_hash/verify |
POST | Revérification (?engine= choisit la copie), protégée (fichiers partagés). |
✓ |
/api/race/torrents/:info_hash/purge |
POST | Supprime la copie du moteur race avec ses fichiers (les fichiers qu'un autre torrent lit sont gardés) ; les autres copies ne sont pas touchées. 404 torrent not in race. Moteurs race supplémentaires : DELETE /api/torrents/:info_hash?engine=<id>. |
✓ |
/api/race/timeline/:info_hash, /api/trackers
|
GET | Chronologie race ; tableau de l'onglet Trackers. | ✓ |
Comment un ajout choisit son moteur et son chemin de sauvegarde : Catégories & routage. Sans engine ni mode, c'est la catégorie qui décide. create_subfolder donne à un torrent à fichier unique un dossier à lui, au nom du torrent ; il n'est pas appliqué aux magnets sur cette route.
Chaque ligne /api/engines/:id/... répond aussi en /api/hoard/... et /api/race/..., sauf pinned, pause-all et resume-all (alias hoard uniquement) et rate-limits, share-limits (sans alias : utilisez /api/engines/race/… ou /api/engines/hoard/…).
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/api/engines |
GET | Moteurs locaux (id, role, listen_port, torrents…), chacun avec ses stats en direct (états, débits, pairs, annonces, plafonds, listening, held…). |
✓ |
/api/engines |
POST |
{"id","role":"race"|"hoard","listen_port","bind_interface"} : ajoute un moteur supplémentaire à la configuration. Répond restart_required: true. Un bind_interface non vide hors Linux → 400. |
✓ (après redémarrage) |
/api/engines/:id |
DELETE | Retire un moteur supplémentaire de la configuration. 409 avec le compte tant qu'il détient des torrents ; race/hoard → 400. Un moteur vide garde son listener jusqu'au redémarrage. |
✓ (après redémarrage) |
/api/engines/:id/page |
GET | Liste paginée (voir ci-dessous). | ✓ |
/api/engines/:id/torrents |
GET | Le moteur en un seul tableau. Sans filtre, offset/limit sont ignorés ; avec un filtre, ils ne le sont pas (voir ci-dessous). |
✓ |
/api/engines/:id/pinned |
GET | Hashes en téléchargement forcé. | ✓ |
/api/engines/:id/pause |
POST |
{"hashes":[...],"paused":true} : arrête/démarre des hashes exacts. |
✓ |
/api/engines/:id/torrents/bulk |
POST |
{"action":"stop"|"start","hashes":[...],"exclude":[...],"all":false}. Champs inconnus → 400 ; un hashes vide ne veut pas dire « tous ». |
✓ |
/api/engines/:id/{pause-all,resume-all} |
POST | Arrête / démarre tous les torrents du moteur. | ✓ |
/api/engines/:id/listen-port |
POST |
{"port":16172} : déplace TCP et uTP à chaud, les annonces suivent, écrit dans la configuration. Port impossible à attacher, déjà pris, ou fixé par gluetun/WireGuard → 409 ; moteur hors réseau → 503. |
✓ |
/api/engines/:id/dial-limits |
POST |
{"max_dials_per_sec","max_connections"} (0 = illimité) : à chaud et écrit dans la configuration. |
✓ |
/api/engines/:id/rate-limits |
GET, POST | Nouveau en 4.4. {"upload_kib","download_kib"} (0 = illimité), en direct et enregistrés. |
✓ |
/api/engines/:id/share-limits |
GET, POST | Nouveau en 4.4. max_ratio, max_seeding_time, max_inactive_seeding_time (-1 = désactivé, minutes), share_limit_action. |
✓ |
/api/hoard/stats |
GET | Totaux. | ✓ |
/api/hoard/download-slots |
GET |
active_downloads configuré ; les autres compteurs valent 0. |
◐ |
/api/race/settings |
GET | Écho des réglages race (upload_rate_limit/download_rate_limit = plafonds configurés, octets/s). GET seulement depuis la 4.4. |
◐ |
/api/startup-pause, /api/startup-pause/release
|
GET, POST |
{"held":[engines],"holding"} ; POST lève la retenue (released). Avec start_paused, un moteur retenu ne se connecte à personne et n'annonce rien jusqu'à sa libération. |
✓ |
Ce que font la file d'attente, les limites de partage et les limites de débit : File d'attente, limites de partage et de débit.
Paramètres de pagination de .../page : offset (par défaut 0), limit (par défaut 500, borné entre 1 et 5000), sort (un champ de ligne, par défaut added_time), order=asc (décroissant par défaut), facets=1 (ajoute les comptes par catégorie/tag/tracker), fields=hash (hashes seulement). Filtres : search (mots combinés en ET, ou un préfixe de hash hexadécimal de 6 caractères ou plus), category, tag, tracker, error_class et leurs variantes _not (listes séparées par des virgules, __none__ = sans valeur), state (un état de ligne comme seeding, ou __active__, __error__, __tracker_err__, __pinned__). La réponse est {"total","filtered","offset","limit","rows","facets"}. Une page fusionne aussi les autres moteurs locaux du même rôle et les lignes des nœuds déclarés. Depuis la 4.4, les mêmes filtres s'appliquent aussi aux routes de liste complète GET /api/{hoard,race}/torrents et /api/engines/:id/torrents ; sans filtre, elles renvoient le moteur entier (/api/race/torrents : tous les moteurs de rôle race) et ignorent offset/limit. Avec un filtre, n'envoyez pas offset/limit : un limit inférieur à 5000 réduit la réponse à une seule page.
Bug connu en 4.4. Sur une route de liste complète, un filtre plus un
offset(aveclimitabsent ou à 5000 et plus) boucle sans fin dès que 5000 lignes correspondent à partir de cet offset : la route pagine en interne en ajoutant son propreoffset, celui de l'appelant vient en premier et l'emporte, donc la fenêtre n'avance jamais.
POST /api/selection/:action exécute une action sur de nombreux torrents sous forme de tâche groupée en mémoire (le menu contextuel de l'interface web l'utilise). Elle répond 202 {"job","total"} ; interrogez GET /api/selection/jobs/:id (conservé 1 h après la fin, perdu au redémarrage). POST /api/selection/jobs/:id/cancel arrête entre deux torrents. Ces tâches ne sont pas les jobs persistants de l'onglet Jobs : voir Jobs, actions groupées & déplacement.
Corps : {"selection": ..., "params": {...}}, strict (clés inconnues → 400).
- Par lignes :
"selection":{"items":[{"hash":"<40 hex>","agent":"local-hoard"}]}. Chaque ligne agit sur sa propre copie (le moteur de son étiquetteagent). - Par filtre :
"selection":{"filter":"category=tv&state=seeding","view":"hoard","expect":<count>},"exclude":[items]facultatif.filterne prend que les clés de filtre listées sous Listes et moteurs ;viewest un identifiant de moteur (par défauthoard) ;expectest obligatoire.
| Action | params |
|---|---|
stop, start, pin, unpin, reannounce, recheck
|
{} (recheck couvre aussi les copies race) |
tags |
{"tags":["a"],"op":"add"|"remove"} |
category |
{"category","move_files":false,"allow_breaking_hardlinks":false} |
location |
{"location":"/abs/path","allow_breaking_hardlinks":false} |
remove |
{"delete_files":false} |
copy, move-engine
|
{"engine":"vpn1"} |
handoff |
{"node","engine","then":"keep"|"remove"} |
node-fetch |
{"node","from_engine","engine"} |
node-move |
{"node","engine"} |
limits (4.4) |
{"up_kib","down_kib"} : les plafonds de débit propres de chaque torrent. |
share_limits (4.4) |
{"ratio_limit","seeding_time_limit","inactive_seeding_time_limit"}. |
download_order (4.4) |
{"sequential","first_last_piece"} (les priorités de fichiers sont par torrent, sur download-order). |
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/api/categories |
GET, POST | Lister / créer {"name","save_path","mode":"race"|"hoard","graduate_to","transit"} → 201. mode insensible à la casse, race par défaut, autre valeur → 400 ; nom déjà pris → 409. |
✓ |
/api/categories/:name |
PUT, DELETE | Mettre à jour : les champs envoyés remplacent ceux enregistrés, les autres (mode compris) sont gardés ; un name différent dans le corps la renomme, réétiquette ses torrents (relabelled ; 409 si le nom est pris) et renomme chaque référence à elle (followed : nombres de rss_rules, watch_folders, workflows, magnets, jobs) / supprimer : l'étiquette est retirée de ses torrents (cleared). |
✓ |
/api/categories/orphans |
GET | Étiquettes portées par des torrents qui ne correspondent à aucune catégorie : [{"name","torrents","mode","save_path"}]. |
✓ |
/api/tags |
GET | Tags. | ✓ |
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/api/announce/{health,policy}, /api/announce/errors?host=
|
GET | Santé des trackers, politique en vigueur, détail des erreurs. | ✓ |
/api/announce/ip-modes |
GET, POST |
{"host","mode"} famille IP par tracker. |
✓ |
/api/announce/passkeys |
GET, POST |
{"host","passkey"} (une passkey vide efface). |
✓ |
/api/announce/min-seed |
POST |
{"host","hours"} ou {"host","clear":true}. |
✓ |
/api/announce/{mute,hidden} |
POST |
{"host","muted"} / {"host","hidden"} ou {"hosts":[...],"hidden"}. |
✓ |
Signification de chaque réglage : Trackers & annonces.
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/api/workflows |
GET, POST | Lister / créer ou remplacer un workflow. | ✓ |
/api/workflows/:id, /api/workflows/:id/run
|
DELETE, POST | Supprimer ; exécuter maintenant (?dry=1 : exécution à blanc). |
✓ |
/api/workflows/{fields,activity,links}, .../preview
|
GET, POST | Champs de l'éditeur, journal d'activité, état des liens ; POST preview : torrents qu'un brouillon toucherait. | ✓ |
/api/jobs, /api/jobs/:id
|
GET | Jobs persistants (?limit=, par défaut 100) ; un job. |
✓ |
/api/jobs/:id |
DELETE | Annuler : cancelled (en file, ou un déplacement vers un nœud en état waiting) ou cancelling (une graduation en cours, annulée et défaite) ; un autre déplacement en cours → 409 (il va jusqu'au bout) ; identifiant inconnu → 404. |
✓ |
Corps : Workflows, Jobs, actions groupées & déplacement.
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/api/drain/{status,history,graduations} |
GET | Volumes, drains passés, graduations en cours. | ✓ |
/api/drain/now?volume=, /api/drain/policy
|
POST | Drainer maintenant ; {"volume","enabled","high_watermark","low_watermark"} ou {"volume","inherit":true}, plus en option quota_gb (capacité déclarée, en 10^9 octets, 0 la retire) et trim_after_drain (booléen), chacun seul ou avec l'une ou l'autre forme. |
✓ |
Voir Drain race & graduation.
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/api/nodes |
GET, POST | Lister (sondés en direct) / déclarer {"name","url","api_key"}. |
✓ |
/api/nodes/test |
POST | Sonder sans enregistrer. | ✓ |
/api/nodes/:name |
DELETE, PATCH | Oublier un nœud (la machine distante n'est pas touchée) / le modifier (4.4) : n'importe lesquels de {"name","url","api_key"} ; une nouvelle URL ou clé est d'abord sondée (400 si elle ne répond pas), un nom déjà pris → 409, les déplacements en attente suivent un renommage. |
✓ |
/api/nodes/:name/rotate-key |
POST | Nouveau en 4.4 (nœud en 4.4). Le nœud reçoit une nouvelle clé, enregistrée ici et renvoyée une seule fois ; l'ancienne est refusée. 502 avec la raison si le nœud a refusé (il garde son ancienne clé). | ✓ |
/api/auth/api-key/rotate, .../confirm
|
POST | Côté nœud d'une rotation : une clé en attente (10 min) / l'adopter, en s'authentifiant avec cette clé (écrite dans [daemon] api_key). |
✓ |
/api/nodes/enrol, /api/nodes/register
|
POST | Jeton à usage unique + commande d'installation ; appelé par la nouvelle machine avec le jeton. | ✓ |
/api/nodes/:name/{handoff,fetch,move-engine} |
POST | Pousser / rapatrier / déplacer entre les moteurs de ce nœud (corps : Nœuds & plusieurs machines). | ✓ |
/node/:name/open |
GET | Redirige vers l'interface du nœud avec sa clé. | ✓ |
/install.sh |
GET | Script d'enrôlement (public). | ✓ |
Les anciennes routes 3.x /api/agents* ont été retirées en 4.4 : tout chemin et toute méthode sous /api/agents répondent 410 Gone avec "see":["/api/engines","/api/nodes"]. Utilisez /api/engines pour les moteurs de cette machine et /api/nodes pour les autres machines (Mettre à jour depuis la 3.x).
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/api/magnets, /api/magnets/:hash, /api/magnets/:hash/retry
|
GET, DELETE, POST | Magnets en résolution ou en échec ; abandonner ; réessayer. | ✓ |
/api/watch |
GET, PUT | Dossiers surveillés. PUT prend la liste complète [{"path","category","engine","paused","enabled"}] ; chemin absolu et existant, la catégorie doit exister. |
✓ |
/api/import/qbit/{preview,start}, .../{status,events}
|
POST, GET | Import depuis une instance qBittorrent ; progression (events est en SSE). |
✓ |
/api/import/transmission/{upload,preview,start} |
POST | Import depuis Transmission (upload multipart, jusqu'à 4 GiB). |
✓ |
/api/import/retry |
POST | Nouveau en 4.4. Sans corps ; relance ce que le dernier import a raté, avec les mêmes choix, et répond {"job_id","torrents"} (le nouveau job, les torrents relancés) ; 404 aucun import, 409 un import en cours, 400 rien à relancer ou la connexion à qBittorrent a échoué (la relance reste disponible). |
✓ |
/api/import/check-paths |
POST |
{"paths":[...]} : quels chemins cet hôte voit. |
✓ |
/api/provenance |
GET | D'où la bibliothèque a été importée ; écrit par chaque import qBittorrent ou Transmission qui a ajouté au moins un torrent. | ✓ |
/api/dedup/config, /api/dedup/stats
|
POST, GET |
{"enabled":true} (redémarrer pour appliquer) ; compteurs des données en double. |
✓ |
Assistant d'import : Migrer depuis qBittorrent. Magnets, dossiers surveillés, dédup : Ajouter des torrents & données existantes.
Nouveau en 4.4. Flux, dossiers et règles de téléchargement ; une règle est le document de règle de qBittorrent (rss/setRule). Les routes /api/v2/rss/* des clients qBittorrent atteignent les mêmes flux et les mêmes règles.
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/api/rss |
GET | Tout ce que montre l'onglet RSS : réglages, feeds, folders, rules. |
✓ |
/api/rss/feeds, /api/rss/feeds/:id
|
GET, POST / PATCH, DELETE | Lister, ajouter {"url","path","refresh_secs"} (409 si déjà pris) / modifier ; retirer. |
✓ |
/api/rss/feeds/:id/{refresh,articles,read,download}, /api/rss/refresh
|
POST, GET | Récupérer maintenant ; articles ; marquer comme lu ; ajouter un article à la main ; tout récupérer (202). | ✓ |
/api/rss/folders |
POST |
{"path"}. |
✓ |
/api/rss/rules, /api/rss/rules/:name, .../rename
|
GET, PUT, DELETE, POST | Lister ; créer ou remplacer (400 pour une regex ou un filtre d'épisodes invalide) ; retirer ; renommer. | ✓ |
/api/rss/rules/:name/matching, /api/rss/preview
|
GET, POST | Ce qu'une règle enregistrée, ou un brouillon, prendrait parmi les articles déjà récupérés. N'ajoute rien. | ✓ |
Règles, filtres et sort d'un article : RSS et téléchargements automatiques.
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/api/network/{interfaces,engines}, /api/public-ip
|
GET | Interfaces actives ; IP de sortie par moteur (?refresh=1) ; IP de sortie du processus. |
✓ |
/api/network/mode |
GET, POST | Onglet Réseau. POST écrit les clés du mode choisi et retire celles des autres modes ; restart_required. bind_interface hors Linux → 400. |
✓ |
/api/network/egress |
GET, POST | Nouveau en 4.4. Le kill switch (armed, pourquoi, moteurs bloqués) et la sortie des requêtes propres du démon (auto, direct, proxy, engine:<id>). |
✓ |
/api/network/wireguard, .../configs, .../configs/:name, .../engines
|
GET, POST, DELETE, POST | WireGuard géré : état et tunnels actifs ; téléverser un .conf de fournisseur ; en retirer un ; affecter les moteurs (tunnel, direct, none). |
✓ (Linux) |
/api/network/check |
POST | Test de fuite par moteur : fail avec LEAK: quand un moteur censé sortir par une interface ou un proxy montre l'adresse de la route par défaut. |
✓ |
/api/port-forward |
GET | Par moteur : port tenu, inbound_peers, reachable (yes/no/unproven), qui redirige le port. |
✓ |
/api/ipfilter |
GET, PUT | État / {"enabled","sources":[...],"refresh_hours"}. |
✓ |
/api/ipfilter/bans, /api/ipfilter/reload
|
POST, DELETE | Bannir {"ip","reason"} / débannir {"ip"} ; POST reload recharge les listes de blocage. |
✓ |
Corps : docs/API.md. Les modes et l'onglet Réseau : Réseau : ports & redirection ; kill switch et sortie du démon : VPN & sortie réseau ; tunnels : WireGuard géré.
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/api/setup |
GET, POST | Premier démarrage : {"needs_setup",...} / créer l'admin {"username","password"} (8 caractères ou plus) → clé API. Public. |
✓ |
/api/login |
POST |
{"username","password"} → {"api_key"}. Public. |
✓ |
/api/auth/password |
POST |
{"password"} (8 caractères ou plus) : enregistré haché dans [auth] password_hash. |
✓ |
/api/settings |
GET, POST | Toute la configuration en JSON, clé API comprise. Les mots de passe SOCKS5 et la clé d'API gluetun valent ******** (renvoyer le masque garde la valeur enregistrée) ; une URL announce_proxy (avec un éventuel user:pass) est encore renvoyée en clair / {"changes":[{"section","key","value"}]} ne modifie que des clés existantes, sauf les clés de moteur à chaud de [race]/[hoard] (débits, choker, file d'attente, limites de partage ; enable_lsd au prochain démarrage), créées si elles manquent. Répond applied_live, restart_required. |
✓ |
/api/settings/reset |
POST | Remet les valeurs par défaut (garde l'identifiant de connexion, la clé, le dossier de données). | ✓ |
/api/settings/restart, /api/restart
|
POST | Répond, puis s'arrête proprement (comme sur SIGTERM : stopped envoyé aux trackers, état de reprise écrit) et quitte avec le code 75 pour que le superviseur redémarre (Exploiter Hydranos). |
✓ |
/api/fs/browse?path= |
GET | Liste les dossiers sur l'hôte Hydranos. | ✓ |
/api/update-check |
GET | Nouvelle version disponible. | ✓ |
Mot de passe oublié : hydranos reset-password sur l'hôte (Sécurité & accès).
| Route | Méthode | Rôle | Statut |
|---|---|---|---|
/health |
GET | Public. status healthy (200), degraded (200 : un moteur sans listener, retenu par start_paused ou bloqué par le kill switch), unhealthy (503 : le store ne répond pas, ou aucun moteur en ligne n'écoute), starting (200) ; plus checks et problems. |
✓ |
/metrics |
GET | Public, Prometheus, par moteur (séries : Métriques Prometheus). | ✓ |
/api/startup |
GET | Public. {"ready","phase","total","restored","engines","uptime"} (Pendant le démarrage d'Hydranos). |
✓ |
/api/status |
GET | Chiffres de l'en-tête et de la Vue d'ensemble. | ✓ |
/api/events |
GET | Flux SSE d'instantanés de statut. Se termine de lui-même quand le démon s'arrête. | ✓ |
/api/logs, /api/logs/stream
|
GET | Le tampon circulaire en mémoire (2000 dernières lignes), filtré côté serveur : level (minimum), module, q, since (5m, 1h, 2d ou Unix s), after (un seq), limit ; un filtre illisible → 400. Suivi en SSE avec les mêmes filtres. |
✓ |
/api/stats/baseline |
GET, POST | Base des compteurs à vie {"total_uploaded","total_downloaded"}. |
✓ |
/api/health/anomalies |
GET | Rapport d'anomalies : contrôles des torrents par une passe de fond toutes les 5 min (generated_at), comptes en direct des trackers, annonces, moteurs et disques. |
✓ |
/api/benchmark/{records,range,current,race-events}, .../trackers/{current,range}
|
GET | Données de benchmark, statistiques des trackers. | ✓ |
/api/benchmark/{engines,compare}, .../race-snapshots/:info_hash
|
GET | Échantillons des moteurs supplémentaires ; comparaison A/B ; instantanés de la chronologie race. | ✓ |
/api/vpn-speedtest/run, .../{latest,history}
|
POST, GET | Test iperf3 (400 non configuré, 409 un test en cours, 502 erreur iperf3) ; résultats enregistrés. | ✓ |
Champs de /api/status, /api/benchmark/current, .../trackers/current et /api/health/anomalies : docs/API.md › Monitoring. /api/status ne couvre que race et hoard (moteurs supplémentaires : stats de /api/engines) ; dans /api/benchmark/current, *_announce_rate, *_announce_fail_rate, race_avg_share et hoard_session_uploaded valent toujours 0.
Ce que rapporte chaque route de supervision : Supervision & journaux.
Ces routes répondent mais ne font pas ce que leur nom indique :
| Route | Ce qu'elle répond | À utiliser à la place |
|---|---|---|
GET /api/hoard/download-slots |
active_downloads configuré et des zéros. |
active_downloads dans la configuration, lu à chaud (File d'attente, limites de partage et de débit). |
GET /api/arr-cleanup/scan |
Un scan vide ("candidates":null,"count":0). |
— |
Routes retirées en 4.4. C'étaient des bouchons jusqu'à la 4.3 (une réponse en forme de succès qui ne faisait rien) et aucun écran ne les appelait. Un chemin retiré répond 404 ; une méthode retirée sur un chemin qui garde son GET répond 405 ; les routes 3.x répondent 410 avec un corps qui nomme la remplaçante.
| Route | Depuis la 4.4 | À utiliser à la place |
|---|---|---|
POST|DELETE /api/hoard/download-slots |
405 |
active_downloads dans la configuration, lu à chaud. |
POST /api/race/settings |
405 |
POST /api/settings ou POST /api/engines/race/rate-limits. |
GET|POST /api/opt/flags, GET /api/race/choking
|
404 | — |
POST /api/hoard/verify-downloading |
404 |
POST /api/selection/recheck. |
POST /api/hoard/restart-stuck |
404 |
stop puis start via /api/selection/*. |
POST /api/arr-cleanup/execute |
404 | — |
/api/agents, /api/agents/* (toutes méthodes) |
410, "see":["/api/engines","/api/nodes"]
|
/api/engines, /api/nodes. |
/api/jobs/move-remote (toutes méthodes) |
410, "see":["/api/selection/handoff",…]
|
POST /api/selection/handoff. |
Les autres routes listées comme bouchons ou constantes sur la page 4.3 fonctionnent en 4.4 (lignes ci-dessus).