REST & WebSocket API

The local Forven HTTP and WebSocket API — base URL, the two authentication keys, the endpoint catalog by area, the live feed, response conventions, and the legacy path shim.

Forven runs a local FastAPI server. The web UI talks to it over HTTP on 127.0.0.1, and the same API is available to you for scripting, integrations, and diagnostics. This page is the developer reference: the base URL, how authentication works, the endpoint catalog grouped by area, the /ws/live WebSocket feed, and the deprecated paths.

This is a local-first API. By default it binds to loopback only, the keys live on your machine, and nothing is exposed to the internet. If you only use the UI you never touch this directly — but everything the app does, you can do over HTTP. AI clients can drive the research loop through the MCP server instead, which wraps the same endpoints as tools.

Forven is a research tool. The trading, risk, and metrics endpoints described here drive a validation process, not a profit engine. Any numbers they return are illustrative of process, not predictions or recommendations, and nothing here is financial advice. Paper is the supported mode; read going live safely before anything touches real capital.

Base URL

The server listens on http://127.0.0.1:8003 by default. Two environment variables change that:

  • FORVEN_PORT — the listen port (default 8003). A startup guard detects port collisions.
  • FORVEN_BIND_HOST — the bind address (default 127.0.0.1, loopback only). A non-loopback address refuses to start unless both keys below are set.

A DNS-rebinding guard rejects unexpected Host headers (extend it with FORVEN_ALLOWED_HOSTS). Browser calls are constrained by CORS (FORVEN_CORS_ORIGINS, default: the local UI origins) and by a cross-site request check on state-changing calls.

Almost every route is under the /api prefix. The WebSocket alias /ws/live and the /verdict/* routes are the exceptions.

Authentication

Forven has two keys with different privilege levels, both set through environment variables.

KeyHeaderGrants
FORVEN_API_KEYx-api-key or Authorization: Bearer <key>Baseline access, checked on every request.
FORVEN_OPERATOR_KEYx-operator-keyOperator access. Required by most routers — strategies, backtesting, the gauntlet, paper, agents, approvals, the brain, settings, system controls, and more.

How the two layers stack

  1. The API-key middleware runs before routing and checks FORVEN_API_KEY on every request except /api/health, /api/webhooks/*, /api/shutdown, and OPTIONS. A mismatch returns 401.
  2. The operator check is applied to whole routers (and a few individual routes, such as force-close). It validates FORVEN_OPERATOR_KEY and returns 401 if the key is missing or wrong.

With no keys set, both layers pass everything through and the backend logs a warning at startup. That is fine for a single user on loopback. Set FORVEN_AUTH_REQUIRED=true to make the server refuse to start unless both keys are set; do that for anything exposed beyond localhost.

# Operator-gated endpoint: send both keys
$h = @{
  "x-api-key"      = $env:FORVEN_API_KEY
  "x-operator-key" = $env:FORVEN_OPERATOR_KEY
}
Invoke-RestMethod -Uri "http://127.0.0.1:8003/api/strategies" -Headers $h

Routes without the operator gate

These need at most the baseline key:

  • GET /api/health and GET /health — liveness, no key at all.
  • POST /api/shutdown — graceful shutdown, loopback only, no key; used by the launcher.
  • /api/webhooks/* — no key, but HMAC-checked; off unless FORVEN_GITHUB_WEBHOOK_SECRET is set.
  • Read-only status and dashboard routes (/api/system/status, /api/system/heartbeat, /api/regime, /api/risk, /api/dashboard/*, trade reads), plus diagnostics and health reads.

Endpoint catalog

The API surface is large — about 500 routes across roughly forty routers. The tables group them by area with representative endpoints. Within an area the pattern is consistent: GET to read, POST/PUT/PATCH to change, DELETE to remove.

System, status & control

MethodPathPurpose
GET/api/healthLiveness check (no auth).
GET/api/system/status · /api/system/heartbeatSystem summary; daemon heartbeat with risk and equity data.
GET/api/dashboard · /api/dashboard/live-fleet · /api/dashboard/paper-fleetThe dashboard summary, and what each live (or paper) strategy is doing right now. Other /api/dashboard/* routes serve summary panels.
GET/api/regime · /api/riskCurrent market regimes; risk state and limits.
GET POST/api/system/modeRead or set the autonomy mode (manual / semi_auto / auto).
POST/api/system/stop · /api/system/startSet or clear the system pause — a live-trading halt.
POST/api/system/generation/pause · /resumePause or resume new-strategy generation only.
POST/api/execution-modeSet the global execution-mode label. Accepts paper only.
POST/api/emergency-haltClose every open live position at market and halt trading.
POST/api/kill-switch/reset · /api/system/trading/resetReset the drawdown kill-switch; or clear the pause, kill-switch, and daily-loss halt together.
POST/api/system/exchange/reconcileReconcile positions and orders with the exchange.
GET PATCH/api/scheduler · /api/scheduler/{job_id}List scheduler jobs; enable, disable, or re-time one.
GET POST/api/system/update/check · /api/system/update/applyCheck for and apply an in-app update. See updating.
GET POST/api/system/factory-reset/categories · /api/system/factory-resetList and run factory-reset categories. See maintenance.

See the risk page for what the halts do and Operations for the controls in the UI.

Strategies, lifecycle & pipeline

The stages are quick_screen → gauntlet → paper → live_graduated; the graveyard is archived, rejected, and backtest_failed. A strategy that cannot be fairly tested is archived with an untestable: reason. (The old research_only "Parked" stage is retired; its strategies were moved to the graveyard.) The marketing site calls the paper stage a "candidate"; the API always says paper. Strategies can move back as well as forward, but every forward move goes through the promotion gates, and by default live is never entered without a typed GO LIVE confirmation and a notional ceiling.

MethodPathPurpose
GET/api/strategiesList strategies by status or stage; paged.
GET/api/strategies/{id}/containerOne strategy with its latest evidence.
POST/api/strategies/{id}/promoteAttempt a promotion; blocked gates come back as structured failed_gates.
POST/api/lifecycle/transitionMove a strategy between stages.
GET/api/lifecycle/strategies/{id}/readiness · /paper-live-readinessThe promotion checklist for the next hop, ending in the real gate as a dry run. The gauntlet → paper report adds the door in force and the pool (paper_door, paper_pool); the paper → live report adds the live-gate settings and the sequential test's state (live_gate, live_evidence).
GET/api/lifecycle/pipeline/explain · /api/lifecycle/strategies/{id}/explainWhy each strategy is where it is — the data behind the pipeline board.
GET/api/lifecycle/paper-poolPaper occupancy and limits, the evidence-ranked queue of strategies waiting for a slot, and the door into paper in force.
GET/api/lifecycle/paper-pool/readmit-candidates?days=&limit=Recent archives the research door would have admitted (defaults: 30 days, 100 rows). A report; nothing is moved.
POST/api/lifecycle/paper-pool/requeueBody {"strategy_ids": [...]}, at most 100. Sends each archive back to the quick screen for a fresh gauntlet run under today's settings. Strategies still in the pipeline and unknown ids are reported and left alone.
GET POST/api/lifecycle/paper-pool/live-recheckHow live strategies fare against the current live gate. GET reads the stored report; POST re-computes it. Report only — it never demotes anything.
GET POST/api/strategies/{id}/execution-check · /execution-check/restore · /execution-check/acceptCompare a paper or live strategy's settings with what was validated; restore the validated settings, or (live only, with a reason) accept a backtest as the new baseline.
GET POST/api/strategies/{id}/breadthRead or run the breadth test: the frozen rule on 15 coins over sealed research data. Its verdict ranks the paper queue, and by default going live needs a finished, current run whose verdict isn't home_only.
PUT/api/strategies/{id}/live-ceilingSet or clear the go-live notional ceiling (null clears it).
GET PUT/api/settings/pipelineRead or change pipeline settings. See configuration.
GET POST/api/pipeline/thresholdsRead or change the gate thresholds.
GET/api/strategies/{id}/export · POST /api/strategies/importExport or import a strategy.

Strategy Creator & backtesting

MethodPathPurpose
GET/api/indicatorsThe indicator catalog behind the Strategy Creator.
POST/api/backtests/preview · /preview-chartSignal preview: entry and exit counts, data coverage, chart markers.
POST/api/backtests/preview-heatmap · /preview-markets · /preview-sensitivityThe Strategy Creator's Heatmap, Markets and Stress test tabs for an unsaved design (the stress test nudges each knob ±10% and ±25%).
POST/api/backtests/strategy-heatmap · /strategy-marketsThe same views for a saved strategy (the strategy page's Sensitivity section).
POST/api/backtests/nl-to-spec · /nl-edit-specAI assist: draft a strategy spec from plain English, or propose a plain-English change to one.
POST/api/backtests/send-to-forgeSend a design into the pipeline as a new quick_screen strategy.
GET POST/api/strategy-library · /api/strategy-library/{id}Your saved Strategy Creator designs.
GET/api/backtests/defaultsWhat each blank Manual Backtest field resolves to (costs, capital, leverage, window), and the held-back data cutoff.
POST/api/backtesting/runRun a backtest. Windows end at the held-back data cutoff.
POST/api/backtesting/optimizeParameter search.
GET/api/backtesting/runs · /api/results · /api/results/{id}Recent runs; paged results; one full result with its trade ledger.
POST/api/robustness/{test}/submit · GET /api/robustness/results/{id}Submit a persisted robustness test (walk-forward, monte-carlo, param-jitter, cost-stress, regime-split) and poll it.
GET POST/api/robustness/holdout/{id} · /api/robustness/holdout/submitRead a strategy's held-back test, or submit its one-shot run.
POST/api/gauntlet/strategies/{id}/workflow · GET /api/gauntlet/workflows/{id}Create or read a gauntlet workflow with per-step status.
POST/api/gauntlet/workflows/{id}/resume · /cancel · /api/gauntlet/steps/{id}/retryResume, cancel, or retry.
POST/api/strategy-guard/scanStatic safety scan of strategy code (no execution).
POST/verdict/run · GET /verdict/guideRun the verdict battery on a result; test descriptions and thresholds.

Interrupted gauntlet workflows are recovered at startup. See backtesting for a worked example.

AI Drop Zone

MethodPathPurpose
GET/api/ai-dropzone/contextWorkspace paths, the strategy template, datasets, and gotchas.
POST/api/strategies/intake/register-fileRegister a strategy file written into the workspace. Returns the strategy at quick_screen, or archived with an untestable_reason to fix.
GET POST/api/ai-dropzone/sessionsList or open Drop Zone sessions.
POST/api/ai-dropzone/sessions/{id}/closeClose a session.

The MCP tools reference maps each tool onto these endpoints. See AI Drop Zone.

Trades & paper trading

MethodPathPurpose
GET/api/trades/open · /api/trades/recent · /api/tradesOpen trades, recent trades, and the full ledger.
GET/api/trades/statsAggregate trade statistics.
POST/api/trades/{id}/force-closeForce-close a position (operator). Returns 502 if the close fails at the exchange.
POST/api/trades/{id}/mark-failedRecord a trade as failed and free its capital (operator).
GET/api/strategies/{id}/live-signals · /live-indicators · /live-markersChart series and entry/exit markers.
GET/api/paper/sessions · /api/paper/summaryPaper sessions and a roll-up. Add include_deployed=true&only_deployed=true for the live sessions.
GET/api/paper/sessions/{id}/trades · /chart · /markersOne session's trades and chart data.
POST/api/paper/sessions/{id}/close-position · /partial-close · /flipManual position controls. On a paper session they fill locally; on a live (deployed) session they place real orders on HyperLiquid, and a new live open must pass the risk gates.
GET/api/trading/journal · /api/trading/fills · /api/trading/market-contextThe trading desk: decisions and refusals, fills, and the funding / open-interest / premium strip.
POST/api/paper/service/start · /stopStart or stop the paper service.

force-close returns 502 Bad Gateway (not 400) on failure to signal that the position may still be open on the exchange. Re-check with GET /api/trades/open afterward. Paper positions are simulated in-app and never touch an exchange.

By default a paper strategy never promotes to live on its own. See paper trading.

Ideas, data & skills

MethodPathPurpose
POST/api/ideas · /api/ideas/preview_urlSubmit an idea (text and/or a source URL) for the Strategy Developer to build strategies from; preview a URL first.
GET/api/ideas/{id}One idea: thesis, mechanism, what would disprove it, and its strategies.
POST/api/data/readiness · GET /api/data/readiness/strategy/{id}Data readiness: is the data a strategy or idea needs stored, fit and current?
GET/api/data/catalog · /api/data/series/{symbol}/{timeframe}The stored series, and one series in detail (coverage, gaps, freshness, provenance).
GET POST/api/data/sla · /api/data/sla/refresh · /api/data/sla/freezeFreshness SLA census; refresh or freeze series.
GET POST/api/data/acquire/* · /api/data/venues · /api/data/history/extendThe Get data wizard: targets, estimate, downloads, file import; venues; extend history.
GET POST/api/data/jobs · /api/data/jobs/{id}/cancel · /retryDownload jobs.
GET POST/api/data/storage · /api/data/trash · /api/data/delete/check · /api/data/deleteDisk and lake use, the trash (restore or purge), and safe deletes that first show what uses the data.
GET/api/data/log · /api/data/log/exportYour data actions and incidents.
GET POST/api/data/universe · /api/data/universe/config · /seed · /refreshThe research universe.
GET/api/datasets · /api/data/coverageDataset catalog; coverage by symbol and timeframe.
POST/api/fetch · /api/data/backfillFetch or backfill market data.
POST/api/upload/csv/preview · /api/upload/csvImport your own OHLCV CSV.
GET/api/quant-skills · /api/skillsQuant skills: the curated insights, and the skill catalog with history.

The old /api/hypotheses/* endpoints are gone. See managing market data and data sources.

Agents, the assistant & approvals

MethodPathPurpose
GET/api/agents · /api/agents/{id}List agents; read one.
GET/api/agents/fleet · /api/agents/activity · /api/agents/yieldThe Agents Overview: each agent's state and runs over a window, the latest finished runs, and what the agents' strategies reached.
PATCH/api/agents/{id} · /api/agents/{id}/modelUpdate an agent, or its model.
GET PUT/api/model-policyThe global model-routing policy.
GET/api/agents/model-options · /api/agents/provider-health · /api/agents/spendAvailable models, provider health, and spend.
GET POST DELETE/api/auth/providers · /api/auth/providers/{provider}Connect, test, or disconnect a model provider.
GET PUT/api/agents/{id}/toolsets · /api/agents/{id}/toolsets/{context}Per-agent tool overrides by context.
POST/api/assistant/threads · /api/assistant/threads/{id}/sendStart an assistant thread; send a message (streamed).
POST/api/assistant/threads/{id}/actions/{action_id}/confirmConfirm an action the assistant proposed.
GET PUT/api/assistant/cost-capThe per-conversation spend cap.
POST/api/deepdive/threads · /api/deepdive/threads/{id}/sendStrategy deep-dive threads (streamed).
GET/api/approvalsList approvals.
POST/api/approvals/{id}/approve · /deny · /reviseAct on an approval. Approving a go-live needs confirm: "GO LIVE" and live_notional_ceiling_usd in the body.
GET PUT/api/approvals/modesApproval modes, deadlines, and escalation.

Agents never place trades or task each other directly. See agents and models & providers.

Brain, routines & tasks

MethodPathPurpose
GET/api/brain/overview · /api/brain/decisionsBrain state and its decision log.
GET PUT/api/brain/memoryThe brain's working notes.
POST/api/brain/chatQueue a brain prompt — returns 202 with a task_id.
GET POST/api/routinesList or create routines.
POST/api/routines/{id}/run · /pause · /resumeRun now, pause, or resume a routine.
GET/api/agent-tasks · /api/tasks/{id}/transcriptAgent runs (shown under Agents → Runs) and a run's transcript.

MCP servers for agents

MethodPathPurpose
GET POST/api/mcp/serversList or register an external MCP server (stdio or http).
GET PUT DELETE/api/mcp/servers/{name}Read, update, or remove one.
POST/api/mcp/servers/{name}/test · GET /api/mcp/servers/{name}/toolsTest it; list its tools.
GET POST DELETE/api/mcp/agents/{id}/grantsGrant or revoke an agent's access.

See external MCP servers for your agents.

Bot Factory

MethodPathPurpose
GET POST/api/bot-factory/botsList or create bots.
PUT DELETE/api/bot-factory/bots/{id}Update or delete a bot.
POST/api/bot-factory/bots/{id}/start · /stop · /cloneStart, stop, or clone.
POST/api/bot-factory/kill-allStop every running bot.
GET/api/bot-factory/bots/{id}/trades · /stats · /positions · /decisionsLedger, stats, open positions, decision log.
GET POST DELETE/api/bot-factory/templatesPersona templates.

Bots run on paper by default, as isolated subprocesses (on Windows, inside a low-integrity sandbox). Arming one for live is per-bot, needs a typed confirmation and a notional ceiling, and is unsupported. See the Bot Factory.

Universe books (experimental)

MethodPathPurpose
GET/api/universe/books · /api/universe/books/{name}/researchThe paper universe books and their sealed-history research.
POST/api/universe/books/{name}/reset · /api/universe/tickReset a book's forward paper record; run a tick now.

These return 404 unless the portfolio layer is on (Settings → System → Experimental features). See universe books.

Settings, notifications & diagnostics

MethodPathPurpose
GET/api/settings · PUT /api/settings/{section}Read all settings; update a section.
GET POST DELETE/api/settings/api-keysData-source credentials (Polygon and others).
GET PUT/api/profileOperator profile.
GET/api/notifications · /api/notifications/groupedThe notification inbox.
POST/api/notifications/{id}/acknowledge · /acknowledge-allAcknowledge one or all.
GET PUT/api/notifications/preferencesPer-event pop-up and Discord switches, and sidebar badges.
GET/api/diagnostics/snapshotHealth checks and the 24-hour cost roll-up.
GET POST/api/diagnostics/resumable · /api/diagnostics/resumable/{id}/resumeInterrupted runs (Resumable Runs), and resuming one.
GET/api/health/status · /api/health/alertsComponent health and recent alerts.

See notifications, diagnostics, and health monitoring.

WebSocket live feed

The live feed streams price ticks, fills, indicator updates, and regime changes. Two routes share one handler:

  • ws://127.0.0.1:8003/api/ws/live — the primary endpoint.
  • ws://127.0.0.1:8003/ws/live — an alias.

Use the feed to drive live charts instead of polling the trade endpoints.

# Quick check that the WebSocket route is reachable (requires the wscat npm package)
wscat --connect "ws://127.0.0.1:8003/ws/live"

Response and error conventions

  • 202 Accepted means queued work. POST /api/brain/chat returns a task_id; poll GET /api/brain/chat/{task_id}, which keeps returning 202 while the task runs.
  • 502 from force-close signals a possibly still-open position — re-verify, never assume.
  • Promotion refusals are data, not errors. A blocked promotion returns structured failed_gates, each with an actionable hint. Some refusals are capacity or pending evidence, not a verdict — paper_queue_full (waiting for a paper slot), breadth_pending, multi_coin_live_review — and leave the strategy where it is.
  • 429 means you hit the rate limit (default 600 requests a minute per client; health and WebSocket paths are exempt).
  • 404 on /api/lab/regime/* means the optional Regime Lab is off (FORVEN_ENABLE_REGIME_LAB).

Legacy paths

Older integrations used /api/forven/*. A compatibility shim still rewrites those requests to /api/*, and responses carry Deprecation and Sunset headers. The announced sunset date (June 30, 2026) has passed: the shim may be removed in any release. The legacy WebSocket paths (/api/forven/ws/live, /forven/ws/live) follow the same rule.

Migrate by dropping the forven segment: /api/forven/strategies becomes /api/strategies. Nothing else changes.

Caveats

  • The operator key is the real gate. Most useful routes need it; the baseline key alone gets 401 on them.
  • Unauthenticated by default on loopback. Set both keys (and FORVEN_AUTH_REQUIRED=true) before binding to anything else — a non-loopback bind without them refuses to start.
  • Some reads are intentionally lighter (status, dashboard, diagnostics, health). Don't take their availability as a sign that all routes are open.
  • The execution-mode endpoint only accepts paper. Real orders come from strategies at the Live stage and live-armed bots, and reaching the Live stage takes a typed GO LIVE with a notional ceiling.

Forven is a research tool. The endpoints here surface a disciplined validation process; results are not predictive and nothing here is financial advice.