Skip to content

API

JSON over HTTP, /api prefix, session cookie. /docs, /redoc and /openapi.json are disabled.

  • POST /api/login {password} ; POST /api/logout ; GET /api/me
  • POST /api/password {current, new}, change the admin password (new ≥ 8 characters). Requires a valid session and a correct current. Returns 409 if the ADMIN_PASSWORD env var is set (the env var always wins, so the password cannot be changed through the API). On success, the new hash is stored in data/admin.json, all other sessions are invalidated and a fresh session cookie is returned for the caller.
  • Servers: GET/POST /api/servers, GET/PUT/DELETE /api/servers/{id}, POST /api/servers/{id}/test Server = {id,name,imap_host,imap_port,imap_security:'ssl'|'starttls'|'none',verify_tls, root_folder:str|null,caldav_url:str|null,carddav_url:str|null,dav_enabled:bool,workers:int,notes, tuning:'auto'|'manual',builders:int|null} (manual: workers IMAP connections, builders builder processes, null = machine default; tuning omitted on creation = manual if workers is not 2 or 4 (earlier defaults) else auto, omitted on update = unchanged) (caldav_url/carddav_url: empty = .well-known auto-discovery, otherwise a template with {email}, {user}, {domain})
  • Accounts: GET /api/accounts?server_id=, POST /api/accounts {server_id,email,password,login?}, PUT/DELETE /api/accounts/{id}, POST /api/accounts/{id}/test → {imap:{ok,msg,quota},caldav:{ok,msg},carddav:{ok,msg}}, POST /api/accounts/import-csv (multipart file + server_id; columns email;password[;login], , or ;, optional header) → {created,updated,errors:[{line,msg}]} ; GET /api/accounts/csv-template. Account = {id,server_id,email,login,has_password,status:'new'|'ok'|'auth_failed'|'error',last_test, pst_id|null,options:{mail:bool,calendar:bool,contacts:bool},job:{...}|null}
  • PST upload (resumable): POST /api/uploads {filename,size,last_modified} → {id,chunk_size,received:[n...]} (same file = same upload, resume) PUT /api/uploads/{id}/chunks/{n} binary body, X-Chunk-Sha256 header → 200 / 422 if wrong hash GET /api/uploads/{id} → {id,filename,size,chunk_size,received:[...],status} POST /api/uploads/{id}/complete → starts validation (signature + scan); GET /api/psts, GET /api/psts/{id}, DELETE /api/psts/{id} ; GET /api/psts/{id}/preview?limit=20 (limit 1..200) → zip (.eml/.ics/.vcf per folder, sample spread across mails/appointments/contacts) generated by the engine in a subprocess (app.server.preview, 120 s timeout); 404 unknown, 409 if PST not valid, 500 {detail:"crash libpff pendant l'aperçu"} if the subprocess dies; PST = {id,filename,size,status:'uploading'|'validating'|'valid'|'invalid',scan:{...},error} PUT /api/accounts/{id}/pst {pst_id}
  • Jobs: POST /api/runs {account_ids:[...]} (queues), POST /api/jobs/{id}/pause|resume|stop|retry, GET /api/jobs?active=1, GET /api/jobs/{id} → {id,account_id,status:'queued'|'running'|'paused'|'stopping'|'stopped'|'done'|'done_with_errors'|'failed', phase:'precheck'|'mail'|'calendar'|'contacts'|'verify',progress:{mail:{done,total,errors},calendar:{...},contacts:{...}}, current_folder,rate,eta,started_at,finished_at,error,tuning:{mode,builders,connections,fallback}|null} GET /api/jobs/{id}/log?after= (lines), GET /api/jobs/{id}/report (JSON), GET /api/jobs/{id}/errors, POST /api/jobs/{id}/retry-errors
  • Real time: GET /api/events (SSE) emits job / upload / pst / account with the full object.
  • GET /api/health.