API CryptoSAS v1

API REST JSON sécurisée pour interagir avec votre coffre-fort numérique. Toutes les communications se font en HTTPS / TLS 1.3.

📄
Guide développeur — Chiffrement & Déchiffrement
Exemples Python complets pour chiffrer/déchiffrer vos fichiers via l'API, avec explications pas à pas.
Base URL
https://cryptosas.newfutur.com/api/v1
Format
application/json
TLS
1.3 uniquement

Authentification

Deux méthodes d'authentification sont acceptées :

JWT (Bearer Token)

Obtenez un token via POST /auth/login, renouvelez-le via POST /auth/refresh. Durée de vie : 15 minutes.

Authorization: Bearer <access_token>

Clé API

Générée depuis votre profil. Préfixée csk_. Scopes disponibles : read, write, delete.

Authorization: Bearer csk_<api_key>
Zero-Knowledge : le serveur ne voit jamais les fichiers en clair, ni les clés de chiffrement. Le chiffrement/déchiffrement s'effectue exclusivement dans le client (navigateur ou application).

Codes d'erreur

Code HTTPSignification
200Succès
201Ressource créée
400Requête invalide — paramètre manquant ou malformé
401Non authentifié — token manquant, expiré ou invalide
403Accès refusé — email non vérifié ou droits insuffisants
404Ressource introuvable
409Conflit — ressource déjà existante (ex : email déjà utilisé)
422Données invalides — erreurs de validation
429Trop de requêtes — rate limit atteint
500Erreur serveur interne

Toutes les réponses d'erreur ont la forme {"error": "message"}.

🔑 Authentification

POST /auth/register Créer un compte Public

Crée un nouveau compte utilisateur et envoie un lien de vérification par email. La connexion est impossible avant validation de l'email.

Corps de la requête (JSON sauf mention contraire)

emailstring (requis)
display_namestring 2–100 cars (requis)
passwordstring ≥10 cars (requis)
phone_mobilestring (optionnel)
encryption_mode"unified" | "per_file" (défaut: "unified")

Réponse

201 — {"message":"...","user":{...}}
POST /auth/login Se connecter Public

Authentifie l'utilisateur. Si le 2FA est activé, retourne un pending_token au lieu des tokens — à passer ensuite à /auth/2fa/verify.

Corps de la requête (JSON sauf mention contraire)

emailstring (requis)
passwordstring (requis)

Réponse

200 — {"access_token":"...","expires_in":900,"user":{...}} ou {"two_factor_required":true,"pending_token":"..."}
Rate-limit : 5 tentatives / 15 min par IP.
POST /auth/2fa/verify Vérifier le code 2FA Public

Vérifie un code TOTP ou un code reçu par email pour finaliser la connexion.

Corps de la requête (JSON sauf mention contraire)

pending_tokenstring (requis)
codestring 6 chiffres (requis)
method"totp" (défaut) | "email"

Réponse

200 — {"access_token":"...","expires_in":900,"user":{...}} + cookie cs_refresh
POST /auth/2fa/email-otp/send Envoyer un code 2FA par email Public

Génère et envoie un code OTP à 6 chiffres à l'adresse email du compte. Le code est valable 10 minutes.

Corps de la requête (JSON sauf mention contraire)

pending_tokenstring (requis)

Réponse

200 — {"masked_email":"n****6@g***.com"}
Rate-limit : 3 codes / 15 min.
GET /auth/verify-email?token= Vérifier l'adresse email Public

Valide le token reçu par email lors de l'inscription. Active le compte.

Paramètres URL / Query

tokenstring — token de vérification (depuis l'email)

Réponse

200 — {"message":"Email vérifié avec succès."}
POST /auth/resend-verification Renvoyer le lien de vérification Public

Génère et envoie un nouveau lien de vérification email. Réponse identique que le compte existe ou non (anti-énumération).

Corps de la requête (JSON sauf mention contraire)

emailstring (requis)

Réponse

200 — {"message":"..."}
Rate-limit : 3 liens / heure.
POST /auth/refresh Rafraîchir le token Public

Échange le cookie cs_refresh contre un nouvel access token JWT. Rotation automatique du refresh token.

Réponse

200 — {"access_token":"...","expires_in":900,"user":{...}} + nouveau cookie cs_refresh
Le refresh token est transmis via cookie HttpOnly — ne pas l'inclure dans le corps.
POST /auth/logout Se déconnecter Public

Révoque le refresh token. Lit le cookie cs_refresh directement — aucun Bearer token requis.

Réponse

200 — {"message":"Déconnecté avec succès."}
GET /auth/me Profil courant 🔒 Auth

Retourne les informations de l'utilisateur authentifié.

Réponse

200 — {"user":{...}}

📁 Fichiers

Tous les endpoints de cette section requièrent un Bearer token (JWT ou clé API). Le contenu des fichiers est toujours chiffré côté client — le serveur ne reçoit que des blobs opaques.
GET /files Lister les fichiers 🔒 Auth

Retourne la liste des fichiers de l'utilisateur authentifié dans un dossier donné.

Paramètres URL / Query

folder_idUUID (optionnel) — omis ou vide pour la racine

Réponse

200 — {"files":[{"id":"...","filename":"...","size_original":1024,"kdf_salt":"hex","file_iv":"hex","encryption_mode":"unified","original_hash":"hex|null","timestamp_status":"none|pending|timestamped","timestamp_at":"datetime|null","created_at":"..."}]}
POST /files Uploader un fichier chiffré 🔒 Auth

Reçoit un blob chiffré (AES-256-GCM) avec ses paramètres cryptographiques. Le chiffrement doit être effectué côté client avant l'envoi.

Corps de la requête (JSON sauf mention contraire)

blobbinary (multipart) — blob chiffré (requis)
filenamestring — nom original du fichier (requis)
kdf_salthex 32 chars — sel PBKDF2 (requis)
file_ivhex 24 chars — IV AES-GCM (requis)
size_originalinteger — taille avant chiffrement en octets (requis)
encryption_mode"unified" | "per_file" (requis)
original_hashhex 64 chars SHA-256 — empreinte du fichier original (recommandé)
folder_idUUID (optionnel)

Réponse

201 — {"file":{...}}
Content-Type : multipart/form-data. La requête est un formulaire, pas du JSON.
GET /files/{id} Télécharger un fichier 🔒 Auth

Retourne le blob chiffré avec les paramètres cryptographiques dans les headers HTTP.

Paramètres URL / Query

idUUID du fichier (requis)

Headers de réponse

X-KDF-Salthex — sel PBKDF2
X-File-IVhex — IV AES-GCM
X-FilenameURL-encoded — nom original
X-MimetypeURL-encoded — type MIME
X-Encryption-Modeunified | per_file
X-Size-Originalinteger — taille originale en octets
X-Original-Hashhex SHA-256 | vide — empreinte du fichier original

Réponse

200 — blob binaire (application/octet-stream)
PATCH /files/{id} Renommer / déplacer 🔒 Auth

Modifie le nom et/ou le dossier parent d'un fichier.

Paramètres URL / Query

idUUID du fichier (requis)

Corps de la requête (JSON sauf mention contraire)

filenamestring (optionnel)
folder_idUUID | null (optionnel)

Réponse

200 — {"file":{...}}
DELETE /files/{id} Supprimer un fichier 🔒 Auth

Supprime définitivement le blob chiffré et l'entrée en base. Le quota est mis à jour.

Paramètres URL / Query

idUUID du fichier (requis)

Réponse

200 — {"message":"Fichier supprimé."}
POST /files/upload-plain Uploader un fichier en clair (chiffrement serveur) 🔒 Auth

⚠️ Mode non zero-knowledge. Le fichier est transmis en clair vers le serveur (protégé par TLS) et chiffré par le serveur avant stockage. À utiliser uniquement lorsque le client ne peut pas effectuer le chiffrement.
Algorithme identique au mode client : PBKDF2-SHA256 (600 000 it.) + AES-256-GCM. Les fichiers restent compatibles avec le déchiffrement client-side.

Corps de la requête (JSON sauf mention contraire)

filebinary (multipart) — fichier en clair (requis)
vault_passwordstring — mot de passe de chiffrement (requis, jamais stocké)
filenamestring — nom du fichier (optionnel, défaut : nom de l'upload)
folder_idUUID (optionnel)

Réponse

201 — {"file":{...}} — encryption_mode sera "server"
Taille max : 100 Mo. Content-Type : multipart/form-data.
POST /files/{id}/decrypt Télécharger un fichier déchiffré (déchiffrement serveur) 🔒 Auth

⚠️ Mode non zero-knowledge. Le serveur déchiffre le blob en mémoire et retourne le fichier original en clair. L'utilisateur doit fournir le mot de passe utilisé lors du chiffrement. Le mot de passe n'est jamais stocké.
Fonctionne pour tous les modes (unified, per_file, server). Si un original_hash est stocké, l'intégrité est vérifiée avant la réponse.

Paramètres URL / Query

idUUID du fichier (requis)

Corps de la requête (JSON sauf mention contraire)

vault_passwordstring — mot de passe du coffre-fort (requis)

Headers de réponse

Content-Typetype MIME original
Content-Dispositionattachment; filename*=UTF-8''<nom>
Content-Lengthtaille en octets du fichier déchiffré
X-Original-HashSHA-256 hex du fichier (si stocké)
Cache-Controlno-store, no-cache, must-revalidate

Réponse

200 — contenu binaire du fichier original déchiffré
Taille max : 100 Mo. Retourne 401 si le mot de passe est incorrect.

🗂️ Dossiers

GET /folders Lister les dossiers 🔒 Auth

Retourne tous les dossiers de l'utilisateur (arborescence complète).

Réponse

200 — {"folders":[{"id":"...","parent_id":"uuid|null","name":"...","created_at":"..."}]}
POST /folders Créer un dossier 🔒 Auth

Crée un nouveau dossier. Le nom est chiffré côté serveur avec la clé applicative.

Corps de la requête (JSON sauf mention contraire)

namestring (requis)
parent_idUUID | null (optionnel)

Réponse

201 — {"folder":{...}}
PATCH /folders/{id} Renommer / déplacer 🔒 Auth

Modifie le nom et/ou le dossier parent.

Paramètres URL / Query

idUUID du dossier (requis)

Corps de la requête (JSON sauf mention contraire)

namestring (optionnel)
parent_idUUID | null (optionnel)

Réponse

200 — {"folder":{...}}
DELETE /folders/{id} Supprimer un dossier 🔒 Auth

Supprime le dossier et tous ses sous-dossiers. Les fichiers contenus sont supprimés (cascade).

Paramètres URL / Query

idUUID du dossier (requis)

Réponse

200 — {"message":"Dossier supprimé."}

👤 Profil

GET /profile Obtenir le profil 🔒 Auth

Retourne les informations du profil utilisateur.

Réponse

200 — {"user":{"id":"...","email":"...","display_name":"...","totp_enabled":bool,"email_verified":bool,"encryption_mode":"...","storage_used":int,"storage_quota":int,"storage_percent":float}}
POST /profile/password Changer le mot de passe 🔒 Auth

Modifie le mot de passe de connexion. Révoque toutes les sessions existantes.

Corps de la requête (JSON sauf mention contraire)

current_passwordstring (requis)
new_passwordstring ≥10 cars (requis)
confirm_passwordstring (requis)

Réponse

200 — {"message":"Mot de passe modifié."}
GET /profile/2fa/setup Initier le setup 2FA 🔒 Auth

Génère un nouveau secret TOTP et l'URI otpauth:// pour affichage QR code côté client. Ne sauvegarde pas encore le secret.

Réponse

200 — {"secret":"BASE32SECRET","otpauth_uri":"otpauth://totp/..."}
POST /profile/2fa/enable Activer le 2FA 🔒 Auth

Valide et active le 2FA TOTP. Accepte un code TOTP ou un code reçu par email.

Corps de la requête (JSON sauf mention contraire)

secretstring BASE32 (requis)
codestring 6 chiffres — code TOTP (requis si method=totp)
method"totp" (défaut) | "email"
email_otp_codestring 6 chiffres (requis si method=email)

Réponse

200 — {"message":"2FA activé avec succès."}
POST /profile/2fa/disable Désactiver le 2FA 🔒 Auth

Désactive le 2FA après vérification du code TOTP courant.

Corps de la requête (JSON sauf mention contraire)

codestring 6 chiffres (requis)

Réponse

200 — {"message":"2FA désactivé."}
POST /profile/2fa/email-otp/send Envoyer un code OTP pour l'activation 🔒 Auth

Envoie un code OTP par email pour valider l'activation du 2FA sans code TOTP.

Réponse

200 — {"masked_email":"n****6@g***.com"}
Rate-limit : 3 codes / 15 min.

🗝️ Clés API

GET /apikeys Lister les clés API 🔒 Auth

Retourne toutes les clés API de l'utilisateur (sans les valeurs brutes).

Réponse

200 — {"keys":[{"id":"...","name":"...","scopes":["read","write"],"last_used_at":"...","expires_at":"...","created_at":"..."}]}
POST /apikeys Créer une clé API 🔒 Auth

Génère une nouvelle clé API. La valeur brute (csk_...) n'est affichée qu'une seule fois.

Corps de la requête (JSON sauf mention contraire)

namestring (requis)
scopesarray ["read","write","delete"] (requis)
expires_atdatetime (optionnel)

Réponse

201 — {"key":{"id":"...","raw_key":"csk_...","name":"...","scopes":[...]}}
La clé brute n'est jamais stockée — conservez-la immédiatement.
POST /apikeys/{id}/regenerate Régénérer une clé 🔒 Auth

Invalide la clé existante et génère une nouvelle valeur. La nouvelle clé brute n'est affichée qu'une seule fois.

Paramètres URL / Query

idUUID de la clé (requis)

Réponse

200 — {"key":{"id":"...","raw_key":"csk_...","name":"...","scopes":[...]}}
DELETE /apikeys/{id} Révoquer une clé 🔒 Auth

Supprime définitivement la clé API. Toutes les requêtes utilisant cette clé seront rejetées.

Paramètres URL / Query

idUUID de la clé (requis)

Réponse

200 — {"message":"Clé API révoquée."}

📊 Stockage

GET /storage/usage Quota utilisé / disponible 🔒 Auth

Retourne l'utilisation du stockage de l'utilisateur en temps réel.

Réponse

200 — {"used":1048576,"quota":5368709120,"percent":0.02,"used_fmt":"1 Mo","quota_fmt":"5 Go"}