FileTransfer

Référence de l'API

API FileTransfer

Référence complète des points d'entrée exposés par le serveur.

Base. Toutes les adresses sont relatives à l'origine du service, par exemple https://votre-domaine/upload.

Formats. Les réponses sont en JSON, sauf les points d'entrée qui servent un fichier ou une page HTML. Les corps de requête JSON attendent l'en-tête Content-Type: application/json.

Une seule adresse d'API. Toute l'administration passe par POST /admin/api, avec un champ action qui désigne l'opération. Les transferts de fichiers ont leurs propres adresses, parce qu'un navigateur doit pouvoir les suivre directement.

Flux. Dépôts et téléchargements sont traités en flux, sans limite de taille côté application. Le plafond éventuel vient du reverse proxy, voir Limites.

Chiffrement. Le stockage est chiffré, sans conséquence pour l'API : les tailles renvoyées sont celles du fichier d'origine, et les requêtes Range restent servies, donc la reprise de téléchargement et le déplacement dans une vidéo continuent de fonctionner.

Authentification

Les points d'entrée publics ne demandent rien. Tout ce qui relève de l'administration exige une session.

Une connexion réussie pose un cookie admin_session, HttpOnly et SameSite=Lax, marqué Secure derrière HTTPS. Il est inaccessible au JavaScript de la page : seule l'empreinte du jeton est conservée en base.

Envoyez ce cookie sur chaque appel. En fetch, cela signifie credentials: 'same-origin' ; avec curl, un fichier de cookies.

La session dure 7 jours et se prolonge à chaque usage. Sans cookie valable, les appels d'API répondent 401 et les pages redirigent vers /admin/login.

# Ouvrir une session
curl -c cookies.txt -X POST https://votre-domaine/admin/api \
     -H 'Content-Type: application/json' \
     -d '{"action":"login","username":"admin","password":"…"}'

# Réutiliser la session
curl -b cookies.txt -X POST https://votre-domaine/admin/api \
     -H 'Content-Type: application/json' \
     -d '{"action":"overview"}'

Si le compte exige une passkey en second facteur, login ne pose pas de cookie et répond {"status":"PASSKEY_REQUIRED","pending":"…"}. Il faut alors dérouler la cérémonie décrite dans Passkeys.

Points d'entrée publics

Accessibles sans authentification.

POST /upload

Dépose un fichier. Corps en multipart/form-data, champ file. Le contenu est écrit sur le disque au fil de la lecture : la taille n'est pas limitée par l'application.

Paramètre d'URLRôle
passwordFacultatif. Protège le fichier : son téléchargement exigera ce mot de passe.
curl -F "file=@rapport.pdf" https://votre-domaine/upload

{"id":"aB3xY9","size":184320,"ip":"203.0.113.7"}

Les noms commençant par . ou _ sont ignorés. Un transfert interrompu ne laisse aucun fichier partiel.

GET /{id}

Sans paramètre, sert la page de téléchargement. Un identifiant inconnu renvoie la page 404.

ParamètreEffet
jsonInfo=onlyRenvoie {"filename":…,"size":…} sans servir le fichier.
download=trueSert le fichier en pièce jointe.
preview=trueSert le fichier en affichage direct dans le navigateur.
passwordMot de passe du fichier, s'il est protégé.

Le mot de passe peut aussi voyager dans l'en-tête X-File-Password, ce que fait la page de téléchargement. En son absence ou s'il est faux, la réponse est 401.

curl "https://votre-domaine/aB3xY9?jsonInfo=only"
curl -H "X-File-Password: secret" -O -J "https://votre-domaine/aB3xY9?download=true"

Les requêtes Range sont acceptées : reprise de téléchargement et déplacement dans une vidéo fonctionnent.

Aperçu des liens — Open Graph

La page servie par /{id} porte les métadonnées du fichier, pour qu'un lien collé dans Discord, Slack ou iMessage s'affiche en vignette plutôt qu'en URL brute. Ces clients lisent les balises <meta> sans exécuter le JavaScript de la page.

Type de fichierBalises émises
Imageog:image, og:image:type, twitter:card=summary_large_image — la vignette est affichée
Vidéoog:video, og:video:type, twitter:card=player
Audioog:audio, og:audio:type
AutreCarte résumée : og:title, og:description

Un fichier protégé par mot de passe n'expose aucune URL d'aperçu : seulement son nom, sa taille et la mention de la protection. L'aperçu serait sinon accessible sans le mot de passe.

<meta property="og:title" content="rapport.pdf">
<meta property="og:description" content="1.67 Mo">
<meta property="og:image" content="https://votre-domaine/aB3xY9?preview=true">

GET /  ·  /index  ·  /api

Page de dépôt, son alias, et la présente page.

Pages d'administration

AdresseDescription
/adminRedirige vers le tableau de bord.
/admin/loginConnexion. Redirige vers le tableau de bord si une session est déjà ouverte.
/admin/registerCréation d'un compte à partir d'un code d'invitation.
/admin/dashboardTableau de bord. Redirige vers la connexion sans session.

Actions de /admin/api

Toutes en POST, corps JSON contenant au minimum action. Session requise, sauf login et register.

Session et compte

ActionChampsRéponse
loginusername ou email, passwordPose le cookie de session. PASSKEY_REQUIRED + pending si un second facteur est exigé.
registerusername, email, password, firstName, lastName, inviteCodeCrée le compte et ouvre la session. Mot de passe de 8 caractères minimum.
logout—Révoque la session courante et efface le cookie.
me—Compte connecté, nombre de passkeys, usage du cloud personnel.
change_passwordcurrentPassword, newPasswordChange le mot de passe et déconnecte les autres appareils.
set_auth_policyauthPolicypassword, passkey_or_password ou password_and_passkey. Exige une passkey enregistrée pour les deux dernières.
sessions_list—Sessions actives du compte, celle en cours marquée current.
session_revokesessionIDDéconnecte une session précise.
sessions_revoke_others—Déconnecte tous les autres appareils.
passkeys_list—Passkeys du compte.
passkey_renamecredID, credNameRenomme une passkey.
passkey_deletecredIDRévoque une passkey. Retirer la dernière ramène le compte au mot de passe seul.

Fichiers publics

ActionChampsRéponse
list_filessearch ; offset et limit en paramètres d'URL{files, total}. La recherche porte sur le nom, l'identifiant et l'IP de dépôt, et accepte les jokers * et ?.
renamefileID, newFileNameRenomme le fichier sur le disque et en base.
change_idfileID, newFileIDChange l'identifiant public, donc le lien de partage.
deletefileIDSupprime le fichier et son enregistrement.
overview—Compteurs de l'instance.
storage—Occupation et plafond de stockage.

Cloud personnel

Cloisonné par compte : les requêtes filtrent sur le propriétaire, un administrateur ne peut pas atteindre l'espace d'un autre.

ActionChampsRéponse
personal_listfolder{folder, folders, files} du dossier demandé.
personal_createfolder, fileNameCrée un fichier vide.
personal_renamefileID, newFileNameRenomme un fichier.
personal_movefileID, folderDéplace un fichier vers un autre dossier.
personal_deletefileIDSupprime un fichier.
personal_sharefileID, sharePasswordPublie le fichier dans l'espace public. Renvoie {id, url, protected}. Mot de passe vide pour un lien libre.
folder_createfolderCrée un dossier, même vide.
folder_renamefolder, newFileNameRenomme un dossier ; sous-dossiers et fichiers suivent.
folder_deletefolderSupprime un dossier et tout son contenu. Renvoie le nombre de fichiers supprimés.

Administrateurs, invitations, journal

ActionChampsRéponse
admins_list—Comptes, méthode de connexion, passkeys, sessions.
admin_deleteadminIDSupprime un compte avec ses sessions et passkeys. Ni son propre compte, ni le dernier.
invites_list—Codes d'invitation et leur état.
invite_create—Génère un code à usage unique.
invite_deletetokenSupprime un code non utilisé.
audit_listcategory, level, search, offset, limit{entries, total}. Catégories : auth, upload, download, file, personal, admin, system. Niveaux : info, warn, error.
bans_list—Bannissements et réglages en vigueur.
ban_createipAddr, minutes, reasonBannit une adresse. Refusé si elle est sur la liste blanche.
ban_revokeipAddrLève un bannissement et remet le compteur de tentatives à zéro.
ban_settings_savethreshold, window, minutes, allowlistRègle le bannissement automatique.
admin_createtarget : prénom, nom, identifiant, e-mail, mot de passeCrée un compte sans invitation.
admin_updateadminID, targetModifie l'état civil et les identifiants d'un compte.
admin_set_passwordadminID, target.passwordImpose un mot de passe et ferme les sessions du compte.
audit_stats—Nombre d'évènements par catégorie sur 24 heures.

Transferts de fichiers

Adresses distinctes de /admin/api, pour qu'un navigateur puisse les suivre directement. Session requise.

GET /admin/download?id=…

Télécharge un fichier public depuis l'administration. Le mot de passe éventuel du fichier n'est pas demandé : c'est un privilège d'administration assumé, et chaque accès de ce type est inscrit au journal avec le nom du compte.

POST /admin/personal/upload?folder=…

Dépose un fichier dans le cloud personnel. multipart/form-data, champ file. Sans limite de taille côté application.

GET /admin/personal/download?id=…

Sert un fichier personnel. preview=true le renvoie en affichage direct avec son vrai type MIME, ce qu'utilisent la prévisualisation des médias et l'éditeur.

GET /admin/personal/zip?folder=…

Renvoie un dossier et ses sous-dossiers sous forme d'archive zip, construite en flux, sans fichier temporaire ni tampon mémoire. L'arborescence relative au dossier demandé est conservée.

POST /admin/personal/save?id=…

Remplace le contenu d'un fichier personnel. Corps brut, 2 Mio maximum. L'écriture passe par un fichier temporaire suivi d'un renommage : une sauvegarde interrompue ou refusée laisse l'original intact.

Passkeys (WebAuthn)

Chaque cérémonie se déroule en deux appels. Le jeton ceremony rendu par begin est à usage unique et expire au bout de cinq minutes.

AdresseDescription
POST /admin/webauthn/register/beginSession requise. Renvoie {ceremony, options}. Une clé résidente est exigée, condition pour que les gestionnaires de mots de passe la conservent comme passkey.
POST /admin/webauthn/register/finish?ceremony=…&name=…Session requise. Corps : la réponse d'attestation du navigateur. Enregistrer la première passkey bascule le compte en passkey_or_password.
POST /admin/webauthn/login/beginSans session. Cérémonie découvrable, sans identifiant. Avec ?pending=…, second facteur après un mot de passe accepté.
POST /admin/webauthn/login/finish?ceremony=…Corps : la réponse d'assertion. Pose le cookie de session. Ajouter &pending=… pour clore une connexion à deux facteurs.

Erreurs

Une erreur renvoie un code HTTP explicite et un corps {"error":"…"} en français.

CodeSignification
400Requête mal formée, champ manquant ou valeur refusée.
401Session absente ou expirée ; ou mot de passe de fichier manquant ou faux.
403La méthode de connexion du compte n'autorise pas ce moyen d'authentification.
404Fichier ou ressource introuvable.
409Nom d'utilisateur ou adresse e-mail déjà pris.
413Contenu trop volumineux. Souvent renvoyé par le reverse proxy, pas par l'application.
500Erreur du serveur. Le journal en conserve la cause.

Limites

Taille des transferts. L'application n'impose aucun plafond : le corps de la requête est écrit sur le disque au fil de sa lecture. En pratique, c'est le reverse proxy qui limite. Sous Nginx, client_max_body_size 0 lève la limite et proxy_request_buffering off évite de recopier tout le fichier sur le disque du proxy avant transmission.

Éditeur de texte. 2 Mio, côté serveur comme côté navigateur.

Sessions. 7 jours, prolongées à chaque usage.

Journal. Conservé 90 jours par défaut, réglable par AUDIT_RETENTION_DAYS.

Chiffrement. Les fichiers sont chiffrés sur le disque en AES-256-GCM, et compressés en zstd lorsque le contenu s'y prête. Tout est transparent pour l'API : les tailles annoncées et les octets servis sont ceux du fichier d'origine. Le chiffrement protège contre un disque volé ou une sauvegarde qui fuite, pas contre quelqu'un qui contrôle le serveur, puisque la clé s'y trouve. Le mot de passe d'un fichier protège son lien de partage, pas son contenu vis-à-vis de l'administrateur de la machine.