---
title: "Compare Spreads"
method: GET
path: "/api/market/spreads/compare"
tags: ["Market Data", "Beta"]
---

# Compare Spreads

`GET /api/market/spreads/compare`

## Request

- Base URL: `https://api.zerogex.io` (the document declares no server; this is the origin it was published from)
- URL: `https://api.zerogex.io/api/market/spreads/compare`
- Auth: HTTP bearer

The same reading side by side across symbols.

Read ``median_spread_bps_underlying`` for the cross-symbol comparison,
not ``median_spread``: index levels differ by 4x between SPX and NDX, so
their dollar widths are not on one scale.

A symbol whose chain cannot be read comes back as a row with
``unavailable`` set rather than being dropped — a missing row would read
as "not compared", and a zeroed one as "perfectly tight".

``puts_percentile`` follows the same rule as the snapshot endpoint's
``history``: null unless the requested scope is one the daily rollup
stored.  The widths themselves are returned at whatever scope was asked
for — this panel carries its own expiry pills, and only the ranking is
scope-bound.

**Beta** — contract may change.

## Query parameters

- `symbols` string: Comma-separated underlyings to compare
- `dte_max` integer
- `moneyness_band_pct` number
- `history_days` integer

## Response `200`

Successful Response

- SpreadCompareResponse
  - `symbols` string[], required
  - `dte_max` integer, required
  - `moneyness_band_pct` number, required
  - `basis` string
  - `disclosure` string
  - `rows` CompareRow[], required
    - `symbol` string, required
    - `spot_price` number, nullable
    - `timestamp` string, date-time, nullable
    - `calls` SpreadAggregateModel: One population's quote quality. Widths are null when nothing is quoted.
      - `contract_count` integer, required
      - `tradable_count` integer, required
      - `two_sided_pct` number, required
      - `zero_bid_pct` number, required
      - `crossed_or_locked_pct` number, required
      - `no_quote_pct` number, required
      - `median_spread` number, nullable
      - `median_relative_spread_pct` number, nullable
      - `p90_relative_spread_pct` number, nullable
      - `median_spread_bps_underlying` number, nullable
      - `p90_spread_bps_underlying` number, nullable
      - `total_open_interest` integer
      - `total_volume` integer
    - `puts` SpreadAggregateModel: One population's quote quality. Widths are null when nothing is quoted.
      - `contract_count` integer, required
      - `tradable_count` integer, required
      - `two_sided_pct` number, required
      - `zero_bid_pct` number, required
      - `crossed_or_locked_pct` number, required
      - `no_quote_pct` number, required
      - `median_spread` number, nullable
      - `median_relative_spread_pct` number, nullable
      - `p90_relative_spread_pct` number, nullable
      - `median_spread_bps_underlying` number, nullable
      - `p90_spread_bps_underlying` number, nullable
      - `total_open_interest` integer
      - `total_volume` integer
    - `put_call_width_ratio` number, nullable
    - `puts_percentile` number, nullable
    - `unavailable` string, nullable

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/zerogex/apis/zerogex-api.md) · [All operations](https://skmtc.dev/zerogex/apis/zerogex-api/llms.txt) · [OpenAPI document](https://skmtc.dev/zerogex/apis/zerogex-api/revisions/753b26bf0592?raw)
