{"openapi":"3.1.0","info":{"title":"Investi API","version":"1.0.0","description":"Read-only personal investing research API. Numbers are computed server side and are identical across web, MCP and extension. Market data is delayed unless your own connected Schwab account supplies real-time quotes. Investi never places, modifies or cancels orders."},"servers":[{"url":"/api/v1"}],"paths":{"/portfolio-revision":{"get":{"summary":"Small owner-scoped revision token for positions, basis corrections and sync health; optional account filter. No portfolio rebuild or market fetch. The app refreshes on change","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/cost-basis":{"get":{"summary":"Missing transaction basis and owner corrections since the reporting start date","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"put":{"summary":"Session only: save an audited total USD cost basis correction. Body: executionId, totalBasis, optional acquiredOn (YYYY-MM-DD or null). Recalculates ledger reports; imported records stay intact","tags":["Portfolio"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Session only: remove a basis correction. Body: executionId. Removal is audited","tags":["Portfolio"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/research-refresh":{"get":{"summary":"Automatic seven-day research queue: pending count, failed awaiting retry, latest completion","tags":["Research"],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/search":{"get":{"summary":"Search securities by ticker or company name (?q=)","tags":["Market"],"security":[{"bearer":["market:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/quotes":{"get":{"summary":"Delayed quotes for ?symbols=A,B,C","tags":["Market"],"security":[{"bearer":["market:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/stream":{"get":{"summary":"Server-sent events quote stream (?symbols=): real-time Schwab Streamer ticks, at most one per symbol every 500 ms, for a connected Schwab account; delayed Nasdaq otherwise","tags":["Market"],"security":[{"bearer":["market:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/securities/{ticker}/history":{"get":{"summary":"Daily split-adjusted bars (?range=5D|1M|3M|6M|1Y|5Y|ALL, default 1Y). `freshness.bars` gives the fetch time, the last bar date (`through`) and `stale` when a completed session has no bar yet","tags":["Market"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["market:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"freshness":{"$ref":"#/components/schemas/DataFreshness"}}}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/securities/{ticker}/intraday":{"get":{"summary":"Intraday prints for the latest session","tags":["Market"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["market:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/securities/{ticker}/report":{"get":{"summary":"Canonical report.v2 (same object the MCP tools and extension use). `freshness` stamps every dataset; `priceSetup.lowProvisional` and `provisionalNote` mark a 52-week low taken from the live quote until the daily bar lands","tags":["Research"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyReport"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/securities/{ticker}/intel":{"get":{"summary":"Compact hover intel (intel.v1) for the extension and hover cards. Answers within ~800 ms: market sections that miss the budget are served stale (with their own as-of) or empty and listed in `pending`; ask again shortly to fill them in. Server-Timing reports where the time went. ?expanded=1 adds intraday, open lots, recent fills and round trips; ?insights=1 adds `insights` (EPS actual vs estimate, next report, price target low/average/high, monthly buy/hold/sell history). `freshness` stamps the quote, bars, analyst data, catalysts (with insights), orders and fills per source; `range` folds the live quote into the 52-week low (`lowProvisional`, `lowAge`, `barsThrough`) and its `pctAboveLow` is never negative. `logoUrl` is the company logo on this origin (`GET /api/logos/{ticker}`, same credentials, market:read).","tags":["Research"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"freshness":{"$ref":"#/components/schemas/DataFreshness"}}}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/securities/{ticker}/catalysts":{"get":{"summary":"Catalysts: dated, sourced news, analyst, insider, short interest, filing, earnings, dividend and macro events, newest first, with the session reaction; slow sources listed in pending. News must name the company or print the ticker in a stock context. `freshness.catalysts` stamps the feed","tags":["Research"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"description":"Comma list: earnings, dividend, macro, filing, analyst, insider, short_interest, news","schema":{"type":"string"}},{"name":"since","in":"query","required":false,"description":"ISO date (New York day, inclusive) or date-time","schema":{"type":"string"}},{"name":"until","in":"query","required":false,"description":"ISO date (New York day, inclusive) or date-time","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1 to 80","schema":{"type":"integer"}}],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"freshness":{"$ref":"#/components/schemas/DataFreshness"}}}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/securities/{ticker}/explain":{"post":{"summary":"Plain-language explanation of the current report (needs an AI provider configured)","tags":["Research"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["research:read"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/ai/page":{"post":{"summary":"AI analysis of one app screen for its owner; a token also needs portfolio:read, since every screen's figures include your holdings. Body { path, refresh?, facts? } where path is a screen such as /portfolio or /research/AAPL. Returns { headline, action: { verb, detail, why } | null, points[], next, caveats[], facts[], model, generatedAt, basis[], cached }, written from the figures that screen shows and the owner's own records. With facts: true, returns only { page, path, facts[] } from the server's rules, no provider needed. 404 for a path that is not a screen, 503 ai_not_configured without an AI provider, 429 after 30 fresh analyses in 10 minutes. Answers are cached 10 minutes per screen and data","tags":["Research"],"security":[{"bearer":["research:read"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/securities/{ticker}/override":{"post":{"summary":"Record a verdict override with rationale; it carries across fresh analyses (report userVerdict) until cleared","tags":["Research"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Clear your verdict on a name (imported or manual): writes a revision without it so it stops carrying forward; the engine's verdict becomes current. Returns { cleared, was, verdict }","tags":["Research"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/securities/{ticker}/checks":{"get":{"summary":"Your saved answers to the manual checks for this ticker: [{ checkId: manual.kodak | manual.legal | manual.revealed, answer: PASS | FAIL | UNKNOWN, note, answeredAt, expiresAt, active }]. Active answers feed the verdict until expiresAt","tags":["Research"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"put":{"summary":"Save one answer. Body { checkId, answer, note?, expiresAt? (YYYY-MM-DD, default 90 days, at most two years) }. Kodak or legal FAIL makes the verdict RED; revealed FAIL caps it at YELLOW; revealed PASS (known) lifts the earnings-reaction cap when saved after the report","tags":["Research"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete one saved answer (?checkId=manual.kodak|manual.legal|manual.revealed)","tags":["Research"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/ai/chat":{"post":{"summary":"Ask about an app screen; a token also needs portfolio:read. Body { path, message, uploadIds?, stream? }. Returns { threadId, user, assistant, changes, proposals, missingUploads, model }; with stream: true, newline-delimited JSON events (delta, then done or error). Uses the screen's figures, the thread, the account's playbook and memory and attached uploads; file text is data, never instructions. Memory and playbook changes apply only with workspace:write when the owner's own words ask for them, otherwise they are returned as proposals. 60 messages per 10 minutes. Research only: never places orders","tags":["Research"],"security":[{"bearer":["research:read"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"get":{"summary":"The open chat thread for ?path= with its messages (a token also needs portfolio:read)","tags":["Research"],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Close the chat thread for ?path= (New thread); it is kept but no longer shown","tags":["Research"],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/ai/chat/confirm":{"post":{"summary":"Confirm or dismiss one proposed memory or playbook change on an answer. Body { messageId, index, decision: apply | dismiss }","tags":["Research"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/uploads":{"get":{"summary":"Your uploads, newest first, with the limits for the next upload (maxBytes, directAboveBytes, prefix)","tags":["Uploads"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Upload one file (multipart field file, up to 20 MB). Checked from its bytes and routed in the same request: broker exports to the importers, screener exports to candidates, strategy documents to the playbook, anything else summarized and attachable in chat. Returns { upload, duplicate }; the same file twice is one upload","tags":["Uploads"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/uploads/token":{"post":{"summary":"Session only: a Vercel Blob client-upload token for files over 4 MB, limited to your own folder","tags":["Uploads"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/uploads/complete":{"post":{"summary":"After a direct upload: { pathname, fileName }. Checks and routes the stored file","tags":["Uploads"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/uploads/{id}":{"get":{"summary":"One upload with its summary and the first 20,000 characters of extracted text","tags":["Uploads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"{ action: playbook } reads a stored document as a strategy","tags":["Uploads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete the file and its memory lines; imported records stay","tags":["Uploads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/playbook":{"get":{"summary":"Current playbook (or ?version=N), its versions, and each proposed settings change against the current value","tags":["Uploads"],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"put":{"summary":"Save { rules, note? } as a new playbook version","tags":["Uploads"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Empty the playbook as a new version","tags":["Uploads"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/playbook/apply":{"post":{"summary":"Session only: { ruleId } applies one proposed settings change through the strategy-rules checks (new policy version)","tags":["Uploads"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/memory":{"get":{"summary":"Memory lines, newest first (?deleted=1 adds removed ones), and mode: local or supermemory","tags":["Uploads"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"{ text } adds a line; { action: undo_clear, at } restores what a clear removed","tags":["Uploads"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Clear memory; returns { removed, at } for the undo","tags":["Uploads"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/memory/{id}":{"patch":{"summary":"{ text } edits a memory line","tags":["Uploads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Remove a memory line (undoable)","tags":["Uploads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"{ action: restore } undoes a removal","tags":["Uploads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/securities/{ticker}/valuation":{"get":{"summary":"Saved DCF assumptions","tags":["Research"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"put":{"summary":"Save DCF assumptions","tags":["Research"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/portfolio":{"get":{"summary":"Positions (costBasis is Schwab-reported where a sync or positions file exists and drives unrealized; reconstructedBasis is rebuilt from fills; basisCheck flags a difference over 1% or $100), KPIs (buyingPower from Schwab balances, lastInterestCharge with the debit it was charged on, ordersStale), the canonical P/L breakdown (pnl) and basisReconciliation. Each position's `record.check` is reconciled only when the broker snapshot is LIVE or DELAYED and fills are synced through it, otherwise unverified with a note. `broker` gives positions and balances freshness separately from quotes (state, observedAt, ageMs, reconciliation: verified, unverified or unreconciled). `connection` is the Schwab state from finished sync runs: LIVE, DELAYED, STALE, FAILED or REAUTH_REQUIRED. `freshness` stamps quotes, orders, fills, balances and positions per source and the Schwab sync","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"freshness":{"$ref":"#/components/schemas/DataFreshness"}}}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/framework/regime":{"get":{"summary":"Market regime switch: IWM vs its moving average plus your recent fills, with the 3-session rule","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/framework/risk":{"get":{"summary":"Framework risk: crash-cap ratio, concentration clusters, unrealized-loss band, underwater age","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/framework/weekly":{"get":{"summary":"Weekly review: realized on average cost, exits, new positions, losers, orders on RED or FLAGGED names, reportingToday, reportingThisWeek, estimatedDates, heldThroughPrint and earningsBlackout (working buys, GTC and GTC+EXT, on names reporting within earningsSoonDays)","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/digest":{"get":{"summary":"Weekly digest: P/L breakdown, open-orders summary, order risk sweep and the weekly review in one document (also needs portfolio:read), with `connection` (the Schwab state from finished sync runs) and `broker` (share-count freshness and reconciliation). The same document the Sunday webhook delivers","tags":["Portfolio"],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/actions":{"get":{"summary":"Action list (same object as the /actions screen and the get_action_list MCP tool): GTC+EXT orders to switch to plain GTC before earnings, open orders on RED or FLAGGED names, held names reporting within earningsSoonDays, cap and cluster breaches, and the crash-cap ratio with the chosen level and the ratio if every open buy fills. Each order carries the broker's order number; schwabOrderStatusUrl is the Schwab page where the user changes it. Read-only: Investi never places, changes or cancels orders","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/actions/{key}/state":{"post":{"summary":"Mark an action list item done, snoozed (returns on the next trading day), dismissed, open (show again) or undo (restore the state before the last change). Body: { state }. key is items[].key from GET /actions. Done and dismissed hold until the item's facts change; a replaced order has a new key. Investi-only: never touches an order at the broker","tags":["Portfolio"],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/transactions":{"get":{"summary":"Ledger transactions (cursor paginated). `freshness.fills` per source: last import or sync (observedAt) and the newest fill (through)","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"freshness":{"$ref":"#/components/schemas/DataFreshness"}}}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/round-trips":{"get":{"summary":"Flat-to-flat round trips with realized P/L","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/sold":{"get":{"summary":"What was sold on a New York date (?date=YYYY-MM-DD, default today): one row per symbol and account from Schwab transactions and imports, with the day's close, left on table, shares still held, re-buy order and fills; `session` marks weekends and NYSE holidays (no session) and gives the adjacent trading days","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/holdings":{"get":{"summary":"Every held position as one row: Schwab-basis avg cost, value, unrealized, lot ages and lots, verdict and reason, earnings, ex-dividend, 52-week range, analyst targets, nearest working orders, sector, concentration bucket, dividends received, breakeven distance, probe flag; plus a summary (totals, count under water, underwater over 60 days, five largest losers)","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/orders":{"get":{"summary":"Working orders (mirrored or recorded, never sent to a broker) as rows with last, distance, notional, session, earnings, verdict; a summary counting orders per flag (earnings, verdict, stale, far, duplicate; never on probe orders); opt-in include=flags,research for each row's flags, age, verdict at entry and research fields (account, sector, ex-dividend, 52-week low, analyst target); a summary plus one page (default 50, max 200). `freshness.orders` per source: the oldest confirmation among working orders","tags":["Portfolio"],"parameters":[{"name":"status","in":"query","required":false,"description":"working (default) or all","schema":{"type":"string"}},{"name":"ticker","in":"query","required":false,"description":"Comma list","schema":{"type":"string"}},{"name":"side","in":"query","required":false,"description":"BUY or SELL","schema":{"type":"string"}},{"name":"session","in":"query","required":false,"description":"GTC, GTC_EXT, DAY or OTHER","schema":{"type":"string"}},{"name":"minNotional","in":"query","required":false,"description":"USD","schema":{"type":"number"}},{"name":"earningsWithinDays","in":"query","required":false,"description":"Only names reporting within N days","schema":{"type":"integer"}},{"name":"verdict","in":"query","required":false,"description":"Comma list: GREEN, YELLOW, RED, FLAGGED, DORMANT, NONE","schema":{"type":"string"}},{"name":"flag","in":"query","required":false,"description":"Comma list: earnings, verdict, stale, far, duplicate","schema":{"type":"string"}},{"name":"include","in":"query","required":false,"description":"Comma list: flags, research","schema":{"type":"string"}},{"name":"mode","in":"query","required":false,"description":"both (default), summary or orders","schema":{"type":"string"}},{"name":"sort","in":"query","required":false,"description":"notional (default), ticker, distance, earnings, entered","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1 to 200, default 50","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"nextCursor from the previous page","schema":{"type":"string"}},{"name":"offset","in":"query","required":false,"description":"Row offset","schema":{"type":"integer"}}],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"freshness":{"$ref":"#/components/schemas/DataFreshness"}}}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Record an order you placed elsewhere","tags":["Portfolio"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/orders/sweep":{"get":{"summary":"Order risk sweep: one suggested action per working order (cancel, switch to plain GTC, review the gate, OK), most urgent first. Research text only; Investi never changes orders","tags":["Portfolio"],"parameters":[{"name":"earningsSoonDays","in":"query","required":false,"description":"Default: the policy's earnings call-out","schema":{"type":"integer"}},{"name":"gateTolerancePct","in":"query","required":false,"description":"Default 1","schema":{"type":"number"}},{"name":"includeOk","in":"query","required":false,"description":"Include OK rows","schema":{"type":"boolean"}},{"name":"ticker","in":"query","required":false,"description":"Comma list","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1 to 200, default 50","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"nextCursor","schema":{"type":"string"}},{"name":"offset","in":"query","required":false,"description":"Row offset","schema":{"type":"integer"}}],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/orders/{id}":{"patch":{"summary":"Update a recorded order's status","tags":["Portfolio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/imports":{"get":{"summary":"Import batches","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Import Schwab CSV/JSON, generic CSV or positions CSV","tags":["Portfolio"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/imports/verdicts":{"post":{"summary":"Import a verdict tracker (multipart field file, CSV or XLSX; columns Ticker, Verdict, optional Date and Notes). Verdicts GREEN, YELLOW, RED, DORMANT or FLAGGED, any case, common synonyms accepted. Stored as evaluations with source imported (verdict as the override, note as rationale). Returns { format, rows, inserted, duplicates, accepted[], skipped[{ row, ticker, reason }], warnings[], byVerdict }","tags":["Portfolio"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/imports/{id}":{"delete":{"summary":"Delete an import batch and its transactions","tags":["Portfolio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/export/{kind}":{"get":{"summary":"CSV export of the ledger: kind is fills, lots (lot matches) or round-trips","tags":["Portfolio"],"parameters":[{"name":"kind","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/schwab":{"get":{"summary":"Schwab connection: configuration, `sync` (state LIVE, DELAYED, STALE, FAILED or REAUTH_REQUIRED computed from finished runs only, last good sync, per-account last good sync, re-authorization warning from day 6) and `runs` (the last 12, each with trigger, start, finish, status and per-endpoint HTTP code, item count and attempts)","tags":["Portfolio"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Sync now (app session only; read-only GETs): the full run plus five yearly windows of transactions (the one-time backfill). Returns status ok, partial, failed or busy (another run is open; a fresh sync follows it) with counts and per-endpoint HTTP codes. Scheduled runs: every minute in market hours, every 5 minutes in extended hours, and a full run at 09:00 and 20:05 New York time","tags":["Portfolio"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Disconnect Schwab and delete stored tokens","tags":["Portfolio"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/screener/runs":{"get":{"summary":"Recent screener runs","tags":["Screener"],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Start a resumable 52-week-low screener run","tags":["Screener"],"security":[{"bearer":["research:read"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/screener/runs/{id}":{"get":{"summary":"Run progress","tags":["Screener"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/screener/runs/{id}/step":{"post":{"summary":"Advance a run by one batch","tags":["Screener"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["research:read"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/screener/candidates":{"get":{"summary":"Candidates with state (NEW/CHANGED/OWNED/...)","tags":["Screener"],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/screener/analyze":{"post":{"summary":"Evaluate queued candidates against the policy","tags":["Screener"],"security":[{"bearer":["research:read"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/screens":{"get":{"summary":"Saved screens","tags":["Screener"],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Save a screen","tags":["Screener"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/screens/{id}":{"delete":{"summary":"Delete a saved screen","tags":["Screener"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/screens/import":{"post":{"summary":"Upload a screener CSV export (multipart `file` field, or the CSV as a text/csv body with ?fileName=). The source is detected from the header: Finviz (No., Ticker, Company), Schwab Stock Screener (Symbol) or other (Ticker). Title lines and footers are skipped. Returns { id, source, rowCount, skipped, tickers }; every row becomes a candidate under upload:<source>. 400 unrecognized_csv when no Symbol or Ticker column or no ticker rows are found, 413 over 5 MB","tags":["Screener"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/candidates":{"get":{"summary":"New candidate entrants from near low (within your distance of the 52-week low, 10% by default), big drop (down 10%+ today, $2B+, positive TTM net income and operating margin), Strict 1 (Finviz screen recomputed from SEC facts; all eleven filters pass) and uploaded screener exports. ?source=near_low|big_drop|strict|upload, ?sinceDays=N (first seen within N days), ?verdict=GREEN|YELLOW|RED|FLAGGED|DORMANT|NONE, ?includeDismissed=true, ?newOnly=false (also names seen before and evaluated, and owned names), ?limit (max 200) and ?page. Returns { entrants[], total, counts, newDays, lastVisit, page, nextPage }; each entrant has sources[] with firstSeenAt, price, changePct, pctAboveLow, verdict (null when not yet evaluated), owned, isNew, reentered, reason, strict (eleven checks, each pass, fail or unknown) and drop (the gate's checks)","tags":["Screener"],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/candidates/{ticker}/dismiss":{"post":{"summary":"Dismiss a candidate. Remembered with the lower of its last price and 52-week low as refPrice; it comes back, marked new, if it trades below refPrice. Returns { ticker, refPrice }; 404 when the ticker is not among your candidates","tags":["Screener"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Undo a dismissal. Returns { ticker, restored }","tags":["Screener"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/simulate":{"post":{"summary":"What-if trade simulation (nothing is sent anywhere)","tags":["Risk"],"security":[{"bearer":["simulate"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/stress":{"get":{"summary":"Standard stress scenarios on the portfolio. Each result carries maintenanceRequirement (rate x gross positions), marginCall (max(0, requirement - equity)) and forcedLiquidation (marginCall / rate: market value to sell to restore the requirement), all null until a maintenance rate is known. `margin` says which rate was used (user-entered or Schwab's reported requirement) and `formulas` states each formula","tags":["Risk"],"security":[{"bearer":["simulate"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Custom stress scenario","tags":["Risk"],"security":[{"bearer":["simulate"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/tax/summary":{"get":{"summary":"Realized short-term and long-term by tax year (?year=YYYY to filter), wash sales detected in the same account and instrument with the disallowed loss and the replacement lots whose basis rises, and the one-year and long-term-from dates of every open lot. Estimates, not tax advice","tags":["Tax"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/tax/harvest":{"get":{"summary":"Loss-harvest candidates before Dec 31: open lots under water with the unrealized loss, days held, one-year date, term if sold today, wash-sale risk from buys in the last 30 days, working buy orders, and an estimated tax saving at your entered rates (Settings). Estimates, not tax advice","tags":["Tax"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/options/chain/{ticker}":{"get":{"summary":"Call option chain (expiries up to 90 days) for a ticker you hold, from your own Schwab market data, cached one minute. state is ok, not_connected (\"Connect Schwab for option chains\"), reconnect, rate_limited or unavailable; no other source is used","tags":["Options"],"parameters":[{"name":"ticker","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/options/covered-calls":{"get":{"summary":"Covered-call screen for held names with 100+ shares: calls with strike at or above average cost expiring before the next earnings date, with premium (mid), premium % of position value, annualized and open interest. Names without an upcoming earnings date are skipped with a reason. Investi never places orders","tags":["Options"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/watchlists":{"get":{"summary":"Watchlists","tags":["Workspace"],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Add or remove a watchlist symbol","tags":["Workspace"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/alerts":{"get":{"summary":"Alerts, the enriched list with triggered counts (items), and recent trigger events (?evaluate=1 checks them first)","tags":["Workspace"],"parameters":[{"name":"evaluate","in":"query","required":false,"description":"1 to evaluate first","schema":{"type":"string"}},{"name":"ticker","in":"query","required":false,"description":"One ticker","schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"description":"price_below, price_above or near_low","schema":{"type":"string"}}],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create an alert; it is evaluated at once and reports whether it already triggered","tags":["Workspace"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"patch":{"summary":"Mark all triggered alert events read","tags":["Workspace"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/alerts/near-low":{"post":{"summary":"Create one near-52-week-low alert per ticker (body: { tickers, pctWithinLow = 3 }), skipping duplicates and reporting them","tags":["Workspace"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/alerts/{id}":{"delete":{"summary":"Delete an alert (404 when it is not yours)","tags":["Workspace"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/notes":{"get":{"summary":"Notes, pinned first then newest","tags":["Workspace"],"parameters":[{"name":"ticker","in":"query","required":false,"description":"One ticker","schema":{"type":"string"}},{"name":"kind","in":"query","required":false,"description":"note, decision or thesis","schema":{"type":"string"}},{"name":"since","in":"query","required":false,"description":"ISO date or date-time","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1 to 300, default 300","schema":{"type":"integer"}}],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a note","tags":["Workspace"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/notes/{id}":{"patch":{"summary":"Pin or unpin a note (body: { pinned: boolean })","tags":["Workspace"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a note","tags":["Workspace"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/policy":{"get":{"summary":"Current versioned strategy policy","tags":["Workspace"],"security":[{"bearer":["research:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"put":{"summary":"Save a new policy version","tags":["Workspace"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/settings":{"get":{"summary":"User preferences","tags":["Workspace"],"security":[{"bearer":["portfolio:read"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"put":{"summary":"Update preferences (app session only), including crashCapLevel: strict, loose or null","tags":["Workspace"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/sample":{"post":{"summary":"Load the labeled sample portfolio","tags":["Workspace"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Remove the sample portfolio","tags":["Workspace"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/webhooks":{"get":{"summary":"Digest webhooks (secrets never returned, only a hint). Also needs portfolio:read and research:read","tags":["Access"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Register an HTTPS URL for the weekly digest (body: { url }); the signing secret is returned once. Also needs portfolio:read and research:read; revoking the registering token pauses it","tags":["Access"],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/webhooks/{id}":{"delete":{"summary":"Remove a webhook","tags":["Access"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/webhooks/{id}/test":{"post":{"summary":"Send this week's digest now as a digest.test event. Also needs portfolio:read and research:read","tags":["Access"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"bearer":["workspace:write"]},{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/tokens":{"get":{"summary":"Personal access tokens and connected apps (session only)","tags":["Access"],"security":[{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a personal access token (shown once)","tags":["Access"],"security":[{"session":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/tokens/{id}":{"delete":{"summary":"Revoke a token","tags":["Access"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"session":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Personal access token (Settings, Connections) or OAuth access token. Scopes: market:read, portfolio:read, research:read, workspace:write, simulate."},"session":{"type":"apiKey","in":"cookie","name":"investi_session"}},"schemas":{"CompanyReport":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"schemaVersion":{"type":"string","const":"report.v2"},"reportId":{"type":"string"},"generatedAt":{"type":"string"},"identity":{"type":"object","properties":{"instrumentId":{"type":"string"},"ticker":{"type":"string"},"issuer":{"type":"string"},"exchange":{"type":["string","null"]},"sector":{"type":["string","null"]},"industry":{"type":["string","null"]},"cik":{"type":["string","null"]}},"required":["instrumentId","ticker","issuer","exchange","sector","industry","cik"],"additionalProperties":false},"quote":{"type":"object","properties":{"last":{"type":["number","null"]},"change":{"type":["number","null"]},"changePct":{"type":["number","null"]},"marketTime":{"type":["string","null"]},"observedAt":{"type":"string"},"session":{"type":"string"},"provider":{"type":"string"},"freshness":{"type":"string"}},"required":["last","change","changePct","marketTime","observedAt","session","provider","freshness"],"additionalProperties":false},"tradingHistory":{"type":"object","properties":{"coverageStart":{"type":["string","null"]},"coverageEnd":{"type":["string","null"]},"realizedPnl":{"type":"number"},"unknownBasisProceeds":{"type":"number"},"roundTripsClosed":{"type":"number"},"roundTripsOpen":{"type":"number"},"buyCount":{"type":"number"},"sellCount":{"type":"number"},"openQuantity":{"type":"number"},"avgOpenPrice":{"type":["number","null"]},"lastBuy":{"anyOf":[{"type":"object","properties":{"date":{"type":"string"},"price":{"type":"number"},"quantity":{"type":"number"}},"required":["date","price","quantity"],"additionalProperties":false},{"type":"null"}]},"lastSell":{"anyOf":[{"type":"object","properties":{"date":{"type":"string"},"price":{"type":"number"},"quantity":{"type":"number"}},"required":["date","price","quantity"],"additionalProperties":false},{"type":"null"}]},"openOrders":{"type":"array","items":{"type":"object","properties":{"side":{"type":"string"},"quantity":{"type":"number"},"limitPrice":{"type":["number","null"]},"duration":{"type":"string"},"status":{"type":"string"},"expiresAt":{"type":["string","null"]}},"required":["side","quantity","limitPrice","duration","status","expiresAt"],"additionalProperties":false}},"lotMethod":{"type":"string"},"sources":{"type":"array","items":{"type":"string"}}},"required":["coverageStart","coverageEnd","realizedPnl","unknownBasisProceeds","roundTripsClosed","roundTripsOpen","buyCount","sellCount","openQuantity","avgOpenPrice","lastBuy","lastSell","openOrders","lotMethod","sources"],"additionalProperties":false},"businessQuality":{"type":"object","properties":{"fiscalYear":{"type":["string","null"]},"revenue":{"type":["number","null"]},"revenuePriorYear":{"type":["number","null"]},"netIncome":{"type":["number","null"]},"operatingCashFlow":{"type":["number","null"]},"totalLiabilities":{"type":["number","null"]},"shareholdersEquity":{"type":["number","null"]},"liabilitiesToEquity":{"type":["number","null"]},"freeCashFlow":{"type":["number","null"]},"netDebt":{"type":["number","null"]},"ebitda":{"type":["number","null"]},"netDebtToEbitda":{"type":["number","null"]},"source":{"type":"string"},"filedAt":{"type":["string","null"]}},"required":["fiscalYear","revenue","revenuePriorYear","netIncome","operatingCashFlow","totalLiabilities","shareholdersEquity","liabilitiesToEquity","freeCashFlow","netDebt","ebitda","netDebtToEbitda","source","filedAt"],"additionalProperties":false},"priceSetup":{"type":"object","properties":{"low52":{"type":["number","null"]},"low52Date":{"type":["string","null"]},"high52":{"type":["number","null"]},"high52Date":{"type":["string","null"]},"pctAboveLow":{"type":["number","null"]},"atr14Pct":{"type":["number","null"]},"recentNewLows":{"type":["number","null"]},"lastNewLow":{"type":["string","null"]},"sma50":{"type":["number","null"]},"sma50Direction":{"type":"string"},"avgDollarVolume30":{"type":["number","null"]},"includesExtendedHours":{"type":"boolean"},"definitions":{"type":"string"},"barsThrough":{"type":["string","null"]},"lowProvisional":{"type":"boolean"},"provisionalNote":{"type":["string","null"]}},"required":["low52","low52Date","high52","high52Date","pctAboveLow","atr14Pct","recentNewLows","lastNewLow","sma50","sma50Direction","avgDollarVolume30","includesExtendedHours","definitions"],"additionalProperties":false},"catalysts":{"type":"object","properties":{"nextEarningsDate":{"type":["string","null"]},"daysToEarnings":{"type":["number","null"]},"recentFilings":{"type":"array","items":{"type":"object","properties":{"form":{"type":"string"},"filedAt":{"type":"string"},"description":{"type":"string"},"url":{"type":"string"}},"required":["form","filedAt","description","url"],"additionalProperties":false}},"items":{"default":[],"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["earnings","dividend","macro","filing","analyst","insider","short_interest","news"]},"at":{"type":"string"},"upcoming":{"type":"boolean"},"title":{"type":"string"},"detail":{"type":["string","null"]},"source":{"type":"string"},"url":{"type":["string","null"]},"lean":{"anyOf":[{"type":"string","enum":["up","down","swing"]},{"type":"null"}]},"reaction":{"anyOf":[{"type":"object","properties":{"pct":{"type":"number"},"session":{"type":"string"}},"required":["pct","session"],"additionalProperties":false},{"type":"null"}]}},"required":["id","kind","at","upcoming","title","detail","source","url","lean","reaction"],"additionalProperties":false}}},"required":["nextEarningsDate","daysToEarnings","recentFilings","items"],"additionalProperties":false},"analystViews":{"type":"object","properties":{"consensusTarget":{"type":["number","null"]},"lowTarget":{"type":["number","null"]},"highTarget":{"type":["number","null"]},"dispersion":{"type":["number","null"]},"buy":{"type":["number","null"]},"hold":{"type":["number","null"]},"sell":{"type":["number","null"]},"asOf":{"type":["string","null"]},"stale":{"type":"boolean"},"source":{"type":"string"}},"required":["consensusTarget","lowTarget","highTarget","dispersion","buy","hold","sell","asOf","stale","source"],"additionalProperties":false},"strategyVerdict":{"type":"object","properties":{"verdict":{"type":"string","enum":["GREEN","YELLOW","RED","FLAGGED","DORMANT","INSUFFICIENT"]},"policy":{"type":"string"},"summary":{"type":"string"},"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"severity":{"type":"string","enum":["zone","hard","cap","soft","manual","info"]},"status":{"type":"string","enum":["PASS","FAIL","WARN","UNKNOWN","MANUAL","INFO"]},"detail":{"type":"string"},"observed":{"type":["number","string","null"]},"threshold":{"type":["number","string","null"]},"evidence":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"source":{"type":"string"},"title":{"type":"string"},"snippet":{"type":["string","null"]},"url":{"type":["string","null"]}},"required":["date","source","title","snippet","url"],"additionalProperties":false}}},"required":["id","label","severity","status","detail","observed","threshold"],"additionalProperties":false}},"inputFingerprint":{"type":"string"},"positionSignal":{"type":["string","null"]}},"required":["verdict","policy","summary","rules","inputFingerprint","positionSignal"],"additionalProperties":false},"userVerdict":{"anyOf":[{"type":"object","properties":{"verdict":{"type":"string","enum":["GREEN","YELLOW","RED","FLAGGED","DORMANT"]},"source":{"type":"string","enum":["imported","manual"]},"at":{"type":"string"},"rationale":{"type":["string","null"]},"engineVerdict":{"type":["string","null"]}},"required":["verdict","source","at","rationale","engineVerdict"],"additionalProperties":false},{"type":"null"}]},"buyZone":{"anyOf":[{"type":"object","properties":{"low":{"type":"number"},"high":{"type":"number"},"note":{"type":"string"}},"required":["low","high","note"],"additionalProperties":false},{"type":"null"}]},"framework":{"type":"object","properties":{"binding":{"type":["string","null"]},"size":{"type":"string","enum":["FULL","HALF","NONE"]},"sizeReasons":{"type":"array","items":{"type":"string"}},"triggerPrice":{"type":["number","null"]},"exitTarget":{"anyOf":[{"type":"object","properties":{"pct":{"type":"number"},"price":{"type":["number","null"]},"dollars":{"type":"number"},"basis":{"type":"string"},"rule":{"type":"string"}},"required":["pct","price","dollars","basis","rule"],"additionalProperties":false},{"type":"null"}]},"estimate":{"anyOf":[{"type":"object","properties":{"low":{"type":"number"},"high":{"type":"number"},"targetPct":{"type":"number"},"label":{"type":"string"},"inputs":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"effect":{"type":"string"},"detail":{"type":"string"}},"required":["key","label","effect","detail"],"additionalProperties":false}},"note":{"type":"string"}},"required":["low","high","targetPct","label","inputs","note"],"additionalProperties":false},{"type":"null"}]},"regime":{"anyOf":[{"type":"object","properties":{"state":{"anyOf":[{"type":"string","enum":["GREEN","YELLOW","RED"]},{"type":"null"}]},"asOf":{"type":["string","null"]},"indexPass":{"type":["boolean","null"]},"fillsPass":{"type":["boolean","null"]},"greenStreak":{"type":"number"},"detail":{"type":"string"}},"required":["state","asOf","indexPass","fillsPass","greenStreak","detail"],"additionalProperties":false},{"type":"null"}]},"earnings":{"type":"object","properties":{"date":{"type":["string","null"]},"confirmed":{"type":["boolean","null"]},"daysTo":{"type":["number","null"]},"lastDate":{"type":["string","null"]},"daysSince":{"type":["number","null"]}},"required":["date","confirmed","daysTo","lastDate","daysSince"],"additionalProperties":false},"manualChecks":{"type":"array","items":{"type":"string"}}},"required":["binding","size","sizeReasons","triggerPrice","exitTarget","estimate","regime","earnings","manualChecks"],"additionalProperties":false},"bearBull":{"type":"object","properties":{"bull":{"type":"array","items":{"type":"string"}},"bear":{"type":"array","items":{"type":"string"}},"failureConditions":{"type":"array","items":{"type":"string"}},"unknowns":{"type":"array","items":{"type":"string"}}},"required":["bull","bear","failureConditions","unknowns"],"additionalProperties":false},"changeLog":{"type":"object","properties":{"previousVerdict":{"type":["string","null"]},"previousEvaluatedAt":{"type":["string","null"]},"sentence":{"type":"string"},"ruleChanges":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"detail":{"type":"string"}},"required":["id","label","from","to","detail"],"additionalProperties":false}}},"required":["previousVerdict","previousEvaluatedAt","sentence","ruleChanges"],"additionalProperties":false},"provenance":{"type":"array","items":{"type":"object","properties":{"dataset":{"type":"string"},"source":{"type":"string"},"observedAt":{"type":"string"},"version":{"type":"string"},"notes":{"type":"string"}},"required":["dataset","source","observedAt","version"],"additionalProperties":false}},"freshness":{"type":"object","properties":{"quote":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"bars":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"fundamentals":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"filings":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"catalysts":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"analyst":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"barsRefresh":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"orders":{"type":"array","items":{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"},"open":{"type":"number"}},"required":["observedAt","source","open"],"additionalProperties":false}},"fills":{"type":"array","items":{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"},"count":{"type":"number"}},"required":["observedAt","source","count"],"additionalProperties":false}},"balances":{"type":"array","items":{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false}},"positions":{"type":"array","items":{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false}},"schwab":{"anyOf":[{"type":"object","properties":{"state":{"type":"string","enum":["LIVE","DELAYED","STALE","FAILED","REAUTH_REQUIRED"],"description":"Computed from finished sync runs only: LIVE under 2 min in market hours, DELAYED 2 to 15 min, STALE past 15 min (26 h outside market hours), FAILED when the last run errored, REAUTH_REQUIRED when Schwab needs a new sign-in"},"status":{"type":"string"},"lastSyncAt":{"description":"When the newest good run finished","type":["string","null"]},"reason":{"type":"string"},"lastError":{"type":["string","null"]},"scheduled":{"type":"boolean","description":"A scheduled run finished successfully in the last 26 hours"},"fillsSyncedAt":{"type":["string","null"]},"ordersSyncedAt":{"type":["string","null"]},"reauthRequiredAt":{"type":["string","null"]},"reauthWarningExpiresAt":{"description":"Set from day 6 of Schwab's 7-day authorization","type":["string","null"]}},"required":["state","status","lastSyncAt","reason","lastError","scheduled"],"additionalProperties":false},{"type":"null"}]}},"additionalProperties":false,"description":"observedAt / source for every dataset in the response (orders, fills, balances and positions per source)"},"disclaimer":{"type":"string"}},"required":["schemaVersion","reportId","generatedAt","identity","quote","tradingHistory","businessQuality","priceSetup","catalysts","analystViews","strategyVerdict","buyZone","framework","bearBull","changeLog","provenance","disclaimer"],"additionalProperties":false},"DatasetStamp":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},"DataFreshness":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"quote":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"bars":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"fundamentals":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"filings":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"catalysts":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"analyst":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"barsRefresh":{"anyOf":[{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false},{"type":"null"}]},"orders":{"type":"array","items":{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"},"open":{"type":"number"}},"required":["observedAt","source","open"],"additionalProperties":false}},"fills":{"type":"array","items":{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"},"count":{"type":"number"}},"required":["observedAt","source","count"],"additionalProperties":false}},"balances":{"type":"array","items":{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false}},"positions":{"type":"array","items":{"type":"object","properties":{"observedAt":{"description":"When Investi last fetched, imported or synced this dataset (ISO), or null when never","type":["string","null"]},"source":{"type":"string","description":"Provider name, or a record source such as schwab_api or schwab_csv"},"through":{"description":"Newest date the data covers: last daily bar, last fill, period end","type":["string","null"]},"stale":{"description":"Past this dataset's expected cadence","type":"boolean"},"note":{"type":"string"}},"required":["observedAt","source"],"additionalProperties":false}},"schwab":{"anyOf":[{"type":"object","properties":{"state":{"type":"string","enum":["LIVE","DELAYED","STALE","FAILED","REAUTH_REQUIRED"],"description":"Computed from finished sync runs only: LIVE under 2 min in market hours, DELAYED 2 to 15 min, STALE past 15 min (26 h outside market hours), FAILED when the last run errored, REAUTH_REQUIRED when Schwab needs a new sign-in"},"status":{"type":"string"},"lastSyncAt":{"description":"When the newest good run finished","type":["string","null"]},"reason":{"type":"string"},"lastError":{"type":["string","null"]},"scheduled":{"type":"boolean","description":"A scheduled run finished successfully in the last 26 hours"},"fillsSyncedAt":{"type":["string","null"]},"ordersSyncedAt":{"type":["string","null"]},"reauthRequiredAt":{"type":["string","null"]},"reauthWarningExpiresAt":{"description":"Set from day 6 of Schwab's 7-day authorization","type":["string","null"]}},"required":["state","status","lastSyncAt","reason","lastError","scheduled"],"additionalProperties":false},{"type":"null"}]}},"additionalProperties":false,"description":"observedAt / source for every dataset in the response (orders, fills, balances and positions per source)"},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}},"responses":{"Error":{"description":"Error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}