VEEMANDocs
DocumentationSupportOpen Dashboard

Getting started

  • Introduction
  • Quick start
  • Core concepts

Importing data

  • Supported formats
  • How import works
  • Splitting a file
  • Troubleshooting

Building your portfolio

  • Workspace & equity
  • Weights & capital
  • Weekday filter
  • Library
  • Variants & comparison
  • History (undo/redo)
  • Shared spaces

Analytics

  • Metrics reference
  • Charts (deep-dive)
  • Monthly P&L
  • Correlations
  • Strategy comparison
  • Monte Carlo
  • Equity Control
  • Optimization
  • Veeman AI

Reference

  • Keyboard & command palette
  • Exporting data
  • Settings

Technical

  • Architecture
  • API reference
  • Security
  • Your data & privacy
  • Risk disclosure
← PreviousArchitectureNext →Security

API reference

VEEMAN's frontend talks to a FastAPI backend over a REST API. This page documents that surface for transparency.

Internal API

This API exists to serve the VEEMAN web app. It is authentication-gated, scoped to your user, and not a public, versioned contract — endpoints may change without notice. There is no public API key programme.

Authentication

Every request carries a Supabase JWT as Authorization: Bearer <token> (or, in local development, a backend-signed cookie). The backend verifies it and resolves your user_id; unauthenticated requests are rejected. See Security.

Auth

POST/api/auth/login
Local-dev login; sets the session cookie.
POST/api/auth/logout
Clears the session.
GET/api/auth/me
The current identity.

Sessions & strategies

POST/api/analysis/upload
Upload one or more CSVs; creates a session.
GET/api/analysis/sessions
List your sessions.
GET/api/analysis/session/{sid}
Session detail (strategies, parameters, per-strategy sizing).
PATCH/api/analysis/session/{sid}
Update parameters (capital, mode, max daily risk, compounding).
PUT/api/analysis/session/{sid}/strategies
Update weights / visibility / per-strategy sizing (mode, SL, Cap %, min/max), and/or the arrangement — the optional order field lists the strategy names from first row to last.
PATCH/api/analysis/session/{sid}/strategies/{name}/rename
Rename a strategy in the session.
DELETE/api/analysis/session/{sid}/strategies/{name}
Remove a strategy from the session.
POST/api/analysis/session/{sid}/strategies/delete
Remove several strategies at once — names lists them. Deleting a selection is one gesture: one call, one Timeline entry (so a single undo brings them all back), one recomputation. Unknown or repeated names are ignored; an empty list is a no-op. Groups left without members are pruned, as with the single delete.
PUT/api/analysis/session/{sid}/groups/order
Arrangement of the group frames in the rail: order lists the group ids from first to last. It moves whole sleeves and never touches the strategies' own order. Tolerant: unknown ids are ignored, groups you leave out keep their current relative position at the end.
POST/api/analysis/session/{sid}/groups/{gid}/merge
Merge a sleeve into one independent strategy carrying its daily P/L as reported (weights, group size, sizing, costs and weekdays already applied). name defaults to the group's name; consolidate: false keeps the group and adds the new leg muted (active it would count the same P/L twice), consolidate: true removes the merged members and activates the new leg. Only visible members are merged — muted ones are never deleted. One Timeline entry for the whole gesture. 422 if the group is unknown or has nothing active.
DELETE/api/analysis/session/{sid}
Delete the session — and its draft.

Session drafts (autosave)

Every session is mirrored to a draft continuously; GET /session/{sid} rebuilds a session from its draft automatically when it is no longer in memory, so a client that keeps its session id needs none of these. They exist for the case where that id is gone (another browser, cleared storage). See Core concepts.

GET/api/analysis/session/{sid}/draft
Timestamp of the last autosave (saved_at); also returned as draft_saved_at on the session payload.
GET/api/analysis/drafts
Your recoverable drafts, newest first (summaries only — no series). Drafts whose data record is unreadable are omitted rather than listed as unopenable.
POST/api/analysis/drafts/{sid}/resume
Restore a draft and return the session (same session_id).
DELETE/api/analysis/drafts/{sid}
Discard a draft, and its session if still live.

404 and 503 mean different things on a session route. 404 is a verdict: no such session, and no draft to rebuild it from — a client holding that id should drop it. 503 (with Retry-After) means the opposite: the draft exists, but storage could not be reached just now. Keep the session id and retry — discarding it on a 503 would throw away the only pointer to work that is still there. A single failed read is retried internally, so a 503 only surfaces when storage is unavailable for longer than one attempt.

Restoring a draft never counts against the per-user session limit: reopening your own work is not the same as starting something new.

Analytics

GET/api/analysis/session/{sid}/equity
Aggregated equity curve (with sizing flags/warnings when dynamic sizing is active).
GET/api/analysis/session/{sid}/metrics
Performance & risk metrics. Optional window_from/window_to (inclusive ISO days) + rebase scope them to the framed period.
GET/api/analysis/session/{sid}/rolling
Moving-window return distributions (1w→1y) of the current portfolio.
GET/api/analysis/session/{sid}/allocation
Per-trade allocation rows of the sized legs (empty when all strategies are fixed).
GET/api/analysis/session/{sid}/monthly
Monthly P/L grid. Takes the same window_from/window_to/rebase as the metrics, so the grid and the ledger describe the same period.
GET/api/analysis/session/{sid}/strategies/metrics
Per-strategy register (standard set + trade-level options metrics). Same window_from/window_to/rebase: each leg is clipped and re-anchored with its own factor, returned alongside as window_factors.
GET/api/analysis/session/{sid}/weekday/{name}/stats
Per-weekday statistics of one strategy. Optional window_from/window_to clip them to the framed period (no rebase: one-contract dollars).
GET/api/analysis/session/{sid}/weekday/{name}/series
Per-weekday cumulative equity and drawdown. Same window parameters; inside a window the curves restart from zero on its first day.
POST/api/analysis/session/{sid}/montecarlo
Run a Monte Carlo simulation (with dynamic sizing active it re-runs the allocation per path; block_size weekly/monthly/quarterly, block bootstrap only).
POST/api/analysis/session/{sid}/equity-control
Start an Equity Control diagnosis — returns a job_id.
GET/api/analysis/session/{sid}/equity-control/{job_id}
Poll an Equity Control job (running / done / error).
POST/api/analysis/session/{sid}/walkforward
Start the walk-forward weekday matrix (one Equity Control diagnosis per strategy × weekday cell) — returns a job_id. Legacy module: retired from the UI, still served for direct callers.
GET/api/analysis/session/{sid}/walkforward/{job_id}
Poll a walk-forward job (running / done / error). Legacy.
POST/api/analysis/session/{sid}/correlation
Correlation matrix.

Session history (undo / redo / recall)

GET/api/analysis/session/{sid}/timeline
The change list of the session: nodes (newest first), the live path, cursor and undo/redo flags. Each node carries the metrics of that version over the full history.
GET/api/analysis/session/{sid}/timeline/window
The same nodes' metrics over the framed period ({node_id: metrics}), each recomputed from its own recipe with the engine that computes the live session. Takes the same window_from/window_to/rebase as the metrics; {} without a window, where the frozen numbers already are the view.
POST/api/analysis/session/{sid}/timeline/undo
Step back one change (also /redo) — rewrites the live session and returns it with the new history state.
POST/api/analysis/session/{sid}/timeline/recall
Jump to any node by seq or node_id, abandoned branches included.

History is in-memory and volatile by design — see History.

Library, variants & risk sizing

GET/api/analysis/portfolio/saved
Saved portfolios (also POST / DELETE).
GET/api/analysis/strategies/saved
Saved strategies (also POST / DELETE).
GET/api/analysis/variants
List / freeze / restore variants.
POST/api/analysis/variants/{vid}/scratch
Open a variant's working copy — a real session you then edit with the normal /session/{sid}/… routes (also DELETE to close it).
POST/api/analysis/variants/{vid}/commit
Re-freeze the variant from its working copy: recipe, equity, drawdown and metrics recomputed, identity unchanged.
GET/api/analysis/variants/{vid}/window
Metrics + curves of a variant over the framed period, computed with the same per-leg recomposition as the live session.
POST/api/analysis/proporzionatore/run
Start a Risk Sizing run — returns a job_id.
POST/api/analysis/proporzionatore/montecarlo
Start a Risk Sizing Monte Carlo — returns a job_id.
GET/api/analysis/proporzionatore/jobs/{job_id}
Poll a Risk Sizing job (running / done / error).

Naming

In the codebase and API these endpoints are still called proporzionatore. They power the standalone Risk Sizing engine, retained as legacy — the same risk/margin engine now runs inline in the workspace as per-strategy sizing.

Shared spaces

Every route above is scope-aware: send the header X-Veeman-Space: {space_id} and it reads and writes inside that space instead of your personal library. Without the header nothing changes. Only shared kinds follow the header — drafts, settings and jobs stay personal in every case.

GET/api/spaces
Your spaces (also POST to create).
GET/api/spaces/{id}
Roster, invites and your role (also PATCH to rename, DELETE to remove).
POST/api/spaces/{id}/invites
Create an invite (also DELETE /{token} to revoke, POST /{token}/accept to join).
PATCH/api/spaces/{id}/members/{uid}
Change a member's role (also DELETE to remove or leave).
POST/api/spaces/{id}/transfer
Hand ownership to another member.
POST/api/spaces/{id}/copy-in
Copy an object from your library into the space (copy-out for the reverse).
GET/api/spaces/{id}/activity
Saves, restores and roster events, newest first.
GET/api/spaces/{id}/comments/{kind}/{name}
Comment thread on an object (also POST and DELETE); /comment-counts returns them all at once.
POST/api/spaces/{id}/lease/{kind}/{name}
Take or renew the turn on an object (also GET and DELETE).
GET/api/versions/{kind}/{name}
Version history of a shared object.
GET/api/versions/{kind}/{name}/{rev}
One version, with its heavy series recomposed.
POST/api/versions/{kind}/{name}/{rev}/restore
Restore that content as a new version.
GET/api/versions
The space trash: objects deleted but recoverable.

If-Match, or the last writer wins

Inside a space, send If-Match: {rev} with the revision you started from on any update. Without it a late save silently overwrites whoever saved in between. With it the server answers 409 carrying the current revision and its author, so the client can offer Reload or Save as a copy. An optional X-Veeman-Note header becomes that version's message.

Simulations run as background jobs

Both Risk Sizing simulations (the run and its Monte Carlo) execute on the server, decoupled from the HTTP request: the POST returns a job_id immediately and the client polls the jobs endpoint. The run keeps going while your phone screen is off or the tab is in the background, and the recipe is persisted so a mid-run backend restart re-runs it transparently. The session Monte Carlo simulation works the same way.