Docs navigation +
Data reference

Options Screener API — Filter Every U.S. Contract

/screen runs a constrained query across the entire options snapshot at once — every contract on every underlying — and returns matching rows. It’s the tool for cross-market questions: highest-IV names, contracts where today’s volume exceeds open interest, high-open-interest contracts, and so on.

Columns, filters, and sorts all use the same supported chain fields. Option bid/ask quotes, quote spreads, midpoint, NBBO, and last trades are not available; use fair_market_value when a current valuation estimate is needed.

Calling it

cvApi (in-app)
// Unusual activity: today's volume above open interest
const hot = await cvApi.screen({
  columns: ['underlying_ticker', 'ticker', 'strike_price', 'expiration_date',
            'day_volume', 'open_interest', 'implied_volatility', 'fair_market_value'],
  filters: [
    { field: 'day_volume', op: 'gt_field', field_ref: 'open_interest' },
    { field: 'open_interest', op: 'gt', value: 1000 },
  ],
  sort: [{ field: 'day_volume', direction: 'desc' }],
  limit: 100,
});
curl (REST)
curl -X POST -H "Authorization: Bearer cv_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "columns": ["underlying_ticker", "strike_price", "implied_volatility"],
    "filters": [{ "field": "implied_volatility", "op": "gt", "value": 1.5 }],
    "sort": [{ "field": "implied_volatility", "direction": "desc" }],
    "limit": 50
  }' \
  https://tap.convexvalue.com/api/data/screen

From a coding agent, the MCP tool is screen — see the MCP reference.

Request shape

Parameter Type Description
columns string[] Supported fields to return, in order. 1–32 entries; duplicates dropped. cvApi.screen() fills in its default set if omitted.
filters required object[] Predicates ANDed together. Up to 16. Each is { field, op, value } or { field, op, field_ref }. An empty array matches everything.
sort object[] Up to 4 entries of { field, direction: "asc" | "desc" }. Direction defaults to ascending.
limit integer Max rows. Default 100, capped at 500. The response sets truncated: true when more rows matched.

Operators

Value operators compare a field to a literal value (number or string):

op Type Description
eq value equals
ne value not equal
gt value greater than
gte value greater than or equal
lt value less than
lte value less than or equal

Field operators compare a field to another field on the same contract via field_ref — this is how you express relationships like “volume above open interest” without pulling everything client-side:

op Type Description
eq_field field_ref field equals another field
ne_field field_ref field differs from another field
gt_field field_ref field greater than another field
gte_field field_ref field ≥ another field
lt_field field_ref field less than another field
lte_field field_ref field ≤ another field

Validation is strict: value operators must include value and must not include field_ref; field operators the reverse. Anything else returns 400.

Response shape

Rows are arrays in the same order as columns — compact to transfer and cheap to feed straight into a table or chart:

JSON response
{
  "columns": ["underlying_ticker", "strike_price", "implied_volatility"],
  "rows": [
    ["GME", 20.0, 2.41],
    ["MARA", 15.0, 1.98]
  ],
  "row_count": 2,
  "truncated": false,
  "elapsed_ms": 87
}

Limits at a glance

ConstraintLimit
Columns32 max (min 1)
Filters16 max (0 allowed)
Sort keys4 max
Rows returneddefault 100, max 500 (truncated flags overflow)

Need more than 500 rows or GROUP BY-style aggregation? Use SQL queries instead.

Prefer a working interface first? Start with the custom options screener and its curated templates.

Get example prompts & new data guides

Occasional emails with prompts worth trying and what’s new in the data.