Skip to content
Abid Ali Awan edited this page Oct 14, 2026 · 12 revisions

The app serves a JSON REST API plus one SSE stream. Every response body is a documented Pydantic model; this page walks through what each endpoint returns. Base URL when running locally: http://127.0.0.1:8000.

Run history and portfolio writes are scoped to an anonymous X-Client-ID header (the browser generates and stores one); without it, listings return empty.

Endpoints

Method Route Purpose
POST /api/analyze Start an analysis run for one or more tickers; incognito: true starts a market-only run (unattributed, nothing persisted, no portfolio access, no trading)
GET /api/discover Rank liquid growth companies with a research-grounded momentum score and return up to five candidates
GET /api/runs List saved analysis runs, newest first
DELETE /api/runs Clear the current browser's finished run history
GET /api/runs/{run_id} Read run status and complete results
GET /api/runs/{run_id}/events Stream live progress over SSE
POST /api/runs/{run_id}/cancel Cancel a running analysis, keeping finished ticker results (repeated requests are harmless)
POST /api/runs/{run_id}/discard Forget an incognito run (sent when its page closes): cancels it if still running and drops the in-memory copy; persisted runs are refused
POST /api/runs/{run_id}/chat Ask the portfolio manager follow-up questions about one ticker of a run
GET /api/broker/status Alpaca paper connection state (configured, enabled, caps); never carries credentials
GET /api/broker/account Mapped paper account snapshot (equity, cash, buying power, status); 503 with a setup hint when unconfigured. The paper account IS the portfolio: the manager and risk gate read their holdings from it
GET /api/broker/positions Open paper positions with live P&L
POST /api/broker/orders Place one paper order (run_id, ticker, side, notional, confirm: true); all guard rails run server-side
GET /api/broker/orders Orders this app placed, newest first; non-terminal rows reconcile against Alpaca on read
DELETE /api/broker/orders/{client_order_id} Cancel a non-terminal order; 422 passes through when it can no longer be canceled
GET /api/broker/equity Paper-account equity timeseries ({dates, equity}) for the performance card
GET /api/broker/performance Per filled order: return since fill and alpha vs SPY over the same window
GET /api/broker/sync Last reconciliation sweep (checked_at, in_sync, reconciled, drift): open orders at the broker this app did not place; backs the portfolio page's out-of-sync banner, refreshed at most once a minute
GET /api/price-history/{ticker} Six months of daily closes ({dates, closes}) for the price-context chart
GET /api/health Check configuration and provider status

Example: start an analysis

curl -X POST http://localhost:8000/api/analyze \
  -H "Content-Type: application/json" \
  -d '{"tickers":["NVDA","AMD"],"outlook":"short_term","depth":"medium"}'

The response is {run_id, tickers}; connect to /api/runs/{run_id}/events for progress, then read /api/runs/{run_id} for results.

The result object

Each ticker's entry in GET /api/runs/{run_id} (and in the ticker_completed SSE event's analysis field) carries:

Decision and trust state

  • decision, confidence: the final risk-adjusted call and its evidence strength.
  • manager_decision, manager_confidence: the manager's own pre-gate call, preserved so a gate override renders as Manager: BUY -> Final: HOLD.
  • manager_probability: the manager's stated probability of beating SPY over the decision-memory horizon (P1.1's frozen success event); absent for HOLD.
  • would_upgrade_if, would_downgrade_if: structured conditions for a different call, labeled as conditions, not alerts.
  • data_quality: a server-computed object with the data timestamp, expected/available/failed/skipped analysts, an outlook-specific staleness flag, and provider fallbacks.
  • providers, source_references: which provider produced each input, plus safe links to the underlying news articles and social threads.

Forecast

  • forecast_price_5d, forecast_change_5d_pct, forecast_method (timegpt-1 or the local trend fit).
  • forecast_band_pct: the ±1σ five-day move implied by the stock's own volatility, and forecast_z: the forecast as a multiple of that band. The manager prompt and the risk gate both consume this assessment.

Evidence

  • market, technical, fundamental, news, sentiment, forecast: one AgentResult per researcher (signal, confidence, summary); which ones ran depends on the depth tier.
  • bull, bear: the debate transcript (absent at Fast depth, which skips the debate).
  • judge: the debate judge's calibrated bull/bear strengths and verdict (Max depth only). Old runs may still carry the deprecated bull_rebuttal/bear_rebuttal fields.

Risk and cost

  • suggested_size_usd: the volatility-scaled position size.
  • risk_flags: why a BUY was downgraded or confidence capped, if it was.
  • token_usage: summed LLM tokens for this ticker's run.
  • cost_estimate: the estimated model cost (see Architecture), with per-role model breakdown and an honest cost unknown state for unpriced models.

Memory

  • past_decisions: graded prior calls on this ticker with realized return, SPY alpha, and a one-line verdict each.
  • previous: a compact snapshot of the earlier completed call on this ticker (run id, decision, evidence strength, analyst signals, forecast, data age, risk flags), or absent on a first analysis.
  • what_changed: one deterministic line per compared dimension versus previous (decision, evidence strength, analyst signals, 5-day forecast, data freshness, risk flags). Structured field diffs only, never an LLM; empty without previous.

SSE events

GET /api/runs/{run_id}/events streams text/event-stream with JSON messages of the form {"type": ..., "ticker": ..., ...}:

Event When Payload highlights
ticker_started a ticker's analysis begins ticker
ticker_data market data fetched price, company_name, sources
agent_started / agent_completed / agent_failed per-agent lifecycle agent, duration_s, signal, confidence, tokens
agent_token live reasoning chunk (only with STREAM_REASONING=1, live runs only) agent, text, truncated
ticker_completed one ticker finished full analysis object, decision, confidence
ticker_failed a ticker aborted (e.g. market data failure) error
analysis_completed terminal event, always emitted exactly once, including after cancellation status, duration_s

Discovery response

GET /api/discover?outlook=short_term returns the five ticker symbols, the screen thresholds, the ranking method, cache status, and cache_ttl_seconds (3,600). The screen snapshot is cached in memory for an hour; failed or incomplete snapshots are never cached.

Chat

POST /api/runs/{run_id}/chat takes {ticker, messages} (up to 20 turns, 2,000 chars each) and returns {ticker, answer, mock_mode}. The manager persona answers grounded in that run's research; failed tickers return 409, missing runs 404, and oversized history 422. On an incognito run the dossier is built without a portfolio lookup, so the chat knows only the market research; a discarded incognito run 404s like any missing run.

Clone this wiki locally