HTTP API reference
Deux modes d'authentification, entierement locaux — aucune dependance a un portail SSO externe (voir packages/backend/src/auth.ts) :
- Cookie de session (browser, dashboard web) — pose par
POST /auth/loginou/auth/signup. HttpOnly + Secure + SameSite=Lax, jamais lu par du JS. Envoye automatiquement par le navigateur (credentials: "include"), 30 jours glissants. Authorization: Bearer icm_xxx(CLI / MCP) — generee depuis le dashboard, longue duree, scopee au user.
Les endpoints retournent 401 si ni cookie ni bearer valide, 403 si le compte est desactive. Les donnees sont scopees a l'utilisateur authentifie.
Auth
POST /auth/signup Body: { email, password }. Pose le cookie de
session. 409 si l'email existe deja.
POST /auth/login Body: { email, password }. Pose le cookie de
session. Meme message d'erreur (401
invalid_credentials) que l'email soit inconnu ou
le mot de passe faux — pas d'enumeration.
POST /auth/logout Efface le cookie de session. Jamais 401 (idempotent).
POST /auth/forgot-password
Body: { email }. Toujours 202, meme reponse que
l'email existe ou non. Envoie un lien de
reinitialisation (60 min, usage unique).
POST /auth/reset-password Body: { token, newPassword }. Definit un premier
mot de passe local OU en reinitialise un existant
(memes semantiques — voir docs/security).
POST /auth/change-password
Body: { currentPassword, newPassword }. Session
uniquement. Deconnecte toutes les autres sessions.
GET /auth/me Returns { user, via: "session" | "api_key" }.
DELETE /auth/account Body: { password }. Session uniquement, irreversible.
GET /auth/account/export Export RGPD (JSON, ciphertexts inclus).API keys
GET /api-keys
POST /api-keys Body: { name, expiresInDays? }
Returns the bearer token ONCE in the response.
DELETE /api-keys/:idObjects (encrypted content envelopes)
PUT /objects/:hash Body: application/octet-stream
Server verifies sha256(body) === :hash.
GET /objects/:hash → application/octet-stream
HEAD /objects/:hash Existence checkWraps (encrypted CEK envelopes)
PUT /wraps/:hash Body: 66 bytes (the wrap envelope).
The matching object must already exist.
GET /wraps/:hash
DELETE /wraps/:hash Session only (dashboard) — 403 with an API key.
No legitimate client ever calls this; kept for
future admin use, not exposed to long-lived
MCP/CLI API keys.Refs (CAS-protected pointers)
GET /refs/:name
PUT /refs/:name Body: { hash, expect: string | null }
"expect" is the etag CAS — null to create.
Also accepts If-Match header.
DELETE /refs/:name Requires If-Match header. Session only (dashboard)
— 403 with an API key (same rationale as
DELETE /wraps/:hash above).Commits (parent-link index)
PUT /commits/:hash Body: { parent: hash | null }
The commit object must already exist.
GET /commits?from=hash&limit=N
Walks the parent chain.
GET /commits/:hash Single commit metadata.Health
GET /health Public, no auth.