The cvApi client
Every app built in cvforge is a single index.html with
window.cvApi already available — a small client wired to the data
backend through a local proxy. The proxy injects your API key server-side, so
the key never exists in the page: no Authorization
headers to manage, no CORS, nothing to leak if you share the app.
All methods return promises and throw a TypeError on malformed
arguments, or an Error containing the HTTP status and server message
when a request fails.
cvApi.chain(symbol, fields?)
Option chain for one underlying — see the options snapshot
for supported fields and response shape. Current option valuation is
fair_market_value, a proprietary estimate; cvforge does not provide option
bid/ask quotes, quote sizes, midpoint, NBBO, or last-trade data.
const data = await cvApi.chain('SPY');
const custom = await cvApi.chain('I:SPX', ['expiration_date', 'strike_price', 'contract_type', 'open_interest']); | Parameter | Type | Description |
|---|---|---|
symbol required | string | Underlying ticker; uppercased for you. Index tickers use the I: prefix (I:SPX, I:VIX, I:NDX, I:RUT, I:XSP). |
fields | string[] | Supported chain fields to return. Omit to use the server default. |
cvApi.screen(request)
Cross-market screener — see the screener reference for operators and limits.
const result = await cvApi.screen({
columns: ['underlying_ticker', 'ticker', 'implied_volatility', 'open_interest'],
filters: [{ field: 'open_interest', op: 'gt', value: 5000 }], // required (can be [])
sort: [{ field: 'implied_volatility', direction: 'desc' }],
limit: 50,
}); cvApi.query(sql, maxRows?)
Read-only SQL — see the SQL reference for tables and rules.
const stats = await cvApi.query(
"SELECT contract_type, COUNT(*) n FROM options_snapshots WHERE underlying_ticker = 'TSLA' GROUP BY 1"
); cvApi.call(endpoint, body?)
The forward-compatible escape hatch: POST to any data-api endpoint by path.
chain/screen/query are sugar over this. New
backend endpoints are reachable here the day they ship, with no cvforge update.
// FMP: company profile
const profile = await cvApi.call('/fmp/stable/profile', { symbol: 'AAPL' });
// Historical bars for a contract (Research plan)
const bars = await cvApi.call('/mas/aggs', {
ticker: 'O:SPY260116C00400000', multiplier: 1, timespan: 'day',
from: '2026-01-02', to: '2026-07-02',
}); | Parameter | Type | Description |
|---|---|---|
endpoint required | string | Data-api path, e.g. "/chains", "/fmp/stable/profile", "/mas/aggs". Leading slash optional. |
body | object | JSON body matching the endpoint (same shape as the corresponding MCP tool’s arguments). |
Environment notes
- Everything is a POST.
cvApi.callposts JSON to/api/data/*on the local preview origin; the proxy forwards it upstream with auth. - Don’t fetch
tap.convexvalue.comdirectly from an app page — the preview’s Content-Security-Policy restricts the page to its own origin (plus a few chart/font CDNs), so direct calls fail. This is what keeps downloaded apps from exfiltrating your data. - Errors surface in the app chrome. Uncaught errors and promise rejections are captured and shown in the preview banner with a “Tell agent” shortcut; a
402/429from the backend shows an upgrade/limit notice. See workspace & preview. - Plotly is preloaded in every app template; other libraries can be added via CDN
<script>tags.
Get example prompts & new data guides
Occasional emails with prompts worth trying and what’s new in the data.