Authentification
Émission et révocation de cookies de session, gestion des identifiants, vérification d'email et endpoints RGPD self-service sous /api/auth.
Authentification
L'API d'authentification émet et révoque les cookies de session, gère les identifiants, vérifie la propriété d'email et expose les endpoints RGPD self-service. Toutes les routes sont montées sous /api/auth et répondent en JSON sauf mention contraire.
Cookie de session
Les appels réussis à signup, login et password/change posent un cookie outsend_session :
| Attribut | Valeur |
|---|---|
| Nom | outsend_session |
| TTL | 7 jours (SESSION_DURATION_DAYS = 7) |
HttpOnly |
true |
Secure |
true (production) |
SameSite |
Lax |
Path |
/ |
Le cookie est un jeton signé lié à une ligne de sessions. Révoquer une session (logout, changement de mot de passe, suppression de compte) supprime la ligne côté serveur même si le cookie est rejoué.
Clés API
Authentification machine pour les connecteurs (Zapier, Make, n8n), les clients MCP et les scripts. Une clé agit au nom de son propriétaire, sur un périmètre fermé : elle atteint la surface d'API documentée, et rien d'autre.
Autorisé — et c'est la liste complète :
| Préfixe | Couvre |
|---|---|
/api/jobs |
créer, inspecter, piloter, exporter des jobs |
/api/estimate, /api/ef/ |
estimation de coût |
/api/pipelines |
composer et lancer des pipelines |
/api/veille |
surveillance récurrente |
/api/events |
le flux d'événements du compte |
/api/webhooks |
les endpoints de webhooks sortants |
/api/countries, /api/modules-registry |
données de référence |
GET /api/auth/me |
test de connexion |
Refusé avec 403 — tout le reste, par défaut. En particulier /api/admin/* (même pour un compte admin), la gestion du compte (mot de passe, suppression, export RGPD), la gestion des clés (une clé ne crée, ne liste ni ne révoque jamais de clés), l'assistant IA de l'application et ses plafonds de dépense, le feedback et l'onboarding.
La liste autorisée est le même objet, dans le code, que celui qui génère le document OpenAPI public : le périmètre réel d'une clé et ce qui est documenté ne peuvent pas diverger. Une nouvelle surface ne devient accessible aux clés qu'en étant ajoutée là-bas et documentée ici.
Format : osk_ + 40 caractères hex. Seule une empreinte SHA-256 est stockée côté serveur ; la clé complète est montrée une fois, à la création. Les clés se créent dans Réglages → Clés API ou via les endpoints ci-dessous (qui exigent une session navigateur — 403 avec une clé API).
Envoie la clé sur n'importe quelle requête, au choix :
Authorization: Bearer osk_...
X-API-Key: osk_...
Une clé révoquée ou appartenant à un compte désactivé reçoit 401.
POST /api/keys
Crée une clé. Auth : cookie de session uniquement. Limite : 10 / jour / utilisateur. Maximum 10 clés actives (400 au-delà).
Requête : { "name": "Zapier" } (1–60 caractères).
Réponse — 201 Created (seul moment où key est renvoyée) :
{ "id": 3, "key": "osk_…40 hex…", "name": "Zapier", "prefix": "osk_aaaaaaaaaaaa", "created_at": "2026-08-07 09:00:00" }
GET /api/keys
Liste les clés du compte — préfixes seulement, jamais de secret.
{ "keys": [ { "id": 3, "name": "Zapier", "prefix": "osk_aaaaaaaaaaaa", "created_at": "…", "last_used_at": "…", "revoked_at": null } ] }
last_used_at est rafraîchi au plus une fois par minute.
DELETE /api/keys/{id}
Révoque la clé (suppression logique — la ligne reste pour l'audit). Réponse : 204. Les intégrations qui l'utilisent cessent de fonctionner immédiatement.
Limites de débit et erreurs
Chaque endpoint applique des fenêtres par IP et par identité (voir Limites). Le dépassement renvoie 429 Too Many Requests avec un message en français contenant le délai de retry en secondes.
Toutes les erreurs suivent la forme FastAPI { "detail": "<message>" }. Codes génériques : 400 (payload invalide, jeton expiré, mauvais mot de passe actuel, échec captcha), 401 (identifiants erronés ou session manquante sur routes protégées), 429 (limite de débit). Les detail spécifiques sont listés en ligne ci-dessous.
POST /api/auth/signup
Crée un utilisateur, envoie l'email de bienvenue + vérification, et ouvre une session. Sans auth. Limite : 3 / heure / IP.
Corps de requête
| Champ | Type | Notes |
|---|---|---|
email |
string (email) | Requis. |
password |
string | 8 à 128 caractères, doit contenir une lettre ET un chiffre/symbole. |
invitation_code |
string | 1 à 64 caractères. L'alpha est sur invitation. |
accept_responsibility |
boolean | Doit valoir true. |
hcaptcha_token |
string ou null | Requis quand HCAPTCHA_SECRET est configuré. |
{
"email": "ada@example.com",
"password": "lovelace-1843",
"invitation_code": "ALPHA-7K2",
"accept_responsibility": true,
"hcaptcha_token": "10000000-aaaa-bbbb-cccc-000000000001"
}
Réponse — 200 OK
{
"ok": true,
"user": {
"id": 42,
"email": "ada@example.com",
"is_admin": false,
"is_active": true,
"email_verified": false,
"created_at": "2026-05-27T09:14:00Z"
}
}
Pose le cookie outsend_session.
Erreurs spécifiques
| Code | Detail |
|---|---|
400 |
Captcha invalide. Réessaie. |
400 |
Code invitation invalide |
400 |
Email existe déjà |
POST /api/auth/login
Valide les identifiants et ouvre une session. Sans auth. Limite : 5 / 15 min / IP et 5 / 15 min / email.
Corps de requête
| Champ | Type | Notes |
|---|---|---|
email |
string (email) | Requis. |
password |
string | 1 à 128 caractères. |
{ "email": "ada@example.com", "password": "lovelace-1843" }
Réponse — 200 OK
{ "ok": true, "user": { "id": 42, "email": "ada@example.com", "is_admin": false, "is_active": true, "email_verified": true, "created_at": "2026-05-27T09:14:00Z" } }
Pose le cookie outsend_session.
Erreurs spécifiques
| Code | Detail |
|---|---|
401 |
Email ou mot de passe incorrect |
401 |
Compte désactivé |
POST /api/auth/logout
Révoque la session courante et efface le cookie. Auth optionnelle. Corps vide. Réponse : 200 OK { "ok": true }.
GET /api/auth/me
Renvoie l'utilisateur authentifié.
{
"id": 42,
"email": "ada@example.com",
"is_admin": false,
"is_active": true,
"email_verified": true,
"created_at": "2026-05-27T09:14:00Z"
}
POST /api/auth/password/reset-request
Envoie un lien de réinitialisation à l'email si (et seulement si) il correspond à un utilisateur actif. La réponse est identique dans tous les cas pour prévenir l'énumération de comptes. Sans auth. Limite : 3 / heure / IP et 3 / heure / email (silencieux quand épuisé).
Corps de requête
{ "email": "ada@example.com" }
Réponse — 200 OK
{ "ok": true }
POST /api/auth/password/reset-confirm
Consomme un jeton de réinitialisation à usage unique et fixe le nouveau mot de passe. Révoque toutes les sessions existantes de l'utilisateur. Sans auth (le jeton fait office d'identifiant).
Corps de requête
| Champ | Type | Notes |
|---|---|---|
token |
string | 10 à 256 caractères, livré par email. |
new_password |
string | 8 à 128 caractères, lettre + chiffre/symbole. |
{ "token": "eyJ...", "new_password": "babbage-1822" }
Réponse — 200 OK
{ "ok": true }
Erreurs spécifiques
| Code | Detail |
|---|---|
400 |
Lien invalide ou expiré |
422 |
Complexité de mot de passe refusée par le validateur. |
POST /api/auth/password/change
Renouvelle le mot de passe d'un utilisateur connecté. Requiert le mot de passe actuel, révoque les autres sessions, émet un cookie frais. Limite : 5 / heure / utilisateur.
Corps de requête
| Champ | Type | Notes |
|---|---|---|
current_password |
string | 1 à 200 caractères. |
new_password |
string | 8 à 200 caractères, doit différer de l'actuel. |
{ "current_password": "lovelace-1843", "new_password": "babbage-1822" }
Réponse — 200 OK
{ "ok": true }
Pose un cookie outsend_session rafraîchi.
Erreurs spécifiques
| Code | Detail |
|---|---|
400 |
Mot de passe actuel incorrect |
400 |
Le nouveau mot de passe doit être différent de l'actuel |
POST /api/auth/email/verify
Consomme un jeton de vérification à usage unique et bascule email_verified à true. Sans auth.
Corps de requête
{ "token": "eyJ..." }
Réponse — 200 OK
{ "ok": true }
Erreur spécifique : 400 Lien de vérification invalide ou expiré.
POST /api/auth/email/resend-verify
Renvoie l'email de vérification à l'utilisateur authentifié. Idempotent si l'adresse est déjà vérifiée. Corps vide. Limite : 3 / heure / utilisateur.
Réponse — 200 OK
{ "ok": true }
ou, si déjà vérifié :
{ "ok": true, "already_verified": true }
DELETE /api/auth/me
Supprime définitivement le compte et tous les enregistrements possédés (jobs, pipelines, surveillances, sessions, jetons). Les fichiers de jobs sur disque sont purgés après le delete DB en cascade. Les fils de feedback sont anonymisés plutôt que supprimés.
Corps de requête
| Champ | Type | Notes |
|---|---|---|
confirm_email |
string | Doit égaler l'email de l'utilisateur (insensible à la casse). |
{ "confirm_email": "ada@example.com" }
Réponse — 204 No Content
Corps vide. Efface le cookie outsend_session.
Erreur spécifique : 400 Confirmation email incorrecte.
GET /api/auth/me/export
Endpoint de portabilité RGPD. Diffuse une archive ZIP contenant tous les enregistrements possédés par l'utilisateur.
Réponse — 200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="outsend-export-<local>-<YYYY-MM-DD>.zip"
Contenu de l'archive :
| Entrée | Contenu |
|---|---|
account.json |
Métadonnées du compte, sans secrets. |
jobs.json |
Tous les jobs avec métadonnées. |
jobs/<job_id>/* |
Sorties CSV/JSON pour chaque job done. |
pipelines.json |
Définitions de pipelines. |
veille.json |
recurring_scraps + historique des runs. |
manifest.txt |
Résumé lisible. |