/api/sd/basis
GETAvailableFRESH

Futures basis (all venues)

Perpetual basis (mark vs index), perp-vs-spot basis on the same exchange and delivery-futures basis with annualised rate, per contract, plus OI-weighted, volume-weighted and median aggregates.

GET/api/sd/basis

Request

Query parameters

NameTypeRequiredDefaultAllowed valuesDescription
coinstringRequired——Coin symbol, case-insensitive (for example `BTC`). Missing or malformed values return 400. Example: BTC

Example request

curl -s "https://www.coinboss.com/api/sd/basis?coin=BTC"

Response fields

The field table is generated from real responses, so it lists exactly what the endpoint returns. Paths use a[] for array items and {*} for objects keyed by a dynamic name such as a coin or an exchange.

FieldTypeUnitDescription
successboolean—true when the request succeeded. On failure the body is `{ success: false, code, error, request_id }`.
schemastring—Schema id of this response. It changes only when an existing field changes meaning or type.
nownumbermsServer time when the response was built.
coinstring—Coin symbol (upper case).
perpobject—Perpetual basis: mark price against the index price of the same exchange.
perp.unitstring—Unit of the basis values (percent).
perp.aggregateobject—Cross-exchange aggregate of the section.
perp.aggregate.oi_weighted_pctnumber%Basis weighted by open interest; rows without an OI weight are left out.
perp.aggregate.oi_weight_usdnumberUSDSum of the open-interest weights used.
perp.aggregate.n_oi_weightednumber—Rows that carried an OI weight.
perp.aggregate.vol_weighted_pctnumber%Basis weighted by 24h notional volume.
perp.aggregate.vol_weight_usdnumberUSDSum of the volume weights used.
perp.aggregate.n_vol_weightednumber—Rows that carried a volume weight.
perp.aggregate.median_pctnumber%Median basis over one primary contract per exchange.
perp.aggregate.mean_pctnumber%Simple mean over the same set as the median.
perp.aggregate.n_exchangesnumber—Exchanges in the aggregate.
perp.aggregate.n_contractsnumber—Contracts in the aggregate.
perp.aggregate.minobject—Exchange and contract with the lowest basis.
perp.aggregate.min.exchangestring—Exchange id (lower case).
perp.aggregate.min.symbolstring—Contract symbol in CoinBoss storage form.
perp.aggregate.min.basis_pctnumber%(mark − index) ÷ index × 100 for perpetuals and delivery; in rankings, the cross-exchange median.
perp.aggregate.maxobject—Exchange and contract with the highest basis.
perp.aggregate.max.exchangestring—Exchange id (lower case).
perp.aggregate.max.symbolstring—Contract symbol in CoinBoss storage form.
perp.aggregate.max.basis_pctnumber%(mark − index) ÷ index × 100 for perpetuals and delivery; in rankings, the cross-exchange median.
perp.aggregate.median_last_pctnumber%Median of the last-price basis.
perp.aggregate.n_exchanges_lastnumber—Exchanges in the last-price median.
perp.aggregate.weightsobject—Where the weights come from, their fresh window and the age of the oldest weight.
perp.aggregate.weights.oiobject—Open interest.
perp.aggregate.weights.oi.sourcestring—Upstream public endpoints the data was collected from.
perp.aggregate.weights.oi.fresh_window_snumbersA weight older than this is not used.
perp.aggregate.weights.oi.oldest_age_snumbersAge of the oldest weight used.
perp.aggregate.weights.oi.sidestring—Whether the open-interest weight is single-sided.
perp.aggregate.weights.volobject—Volume.
perp.aggregate.weights.vol.sourcestring—Upstream public endpoints the data was collected from.
perp.aggregate.weights.vol.fresh_window_snumbersA weight older than this is not used.
perp.aggregate.weights.vol.oldest_age_snumbersAge of the oldest weight used.
perp.contractsarray—One row per contract.
perp.contracts[]object—One row per contract.
perp.contracts[].exchangestring—Exchange id (lower case).
perp.contracts[].symbolstring—Contract symbol in CoinBoss storage form.
perp.contracts[].native_symbolstring—Contract symbol as the exchange writes it.
perp.contracts[].quotestring—Quote currency of the contract.
perp.contracts[].margin_typestring—Margin type of the contract (for example USDT-margined, coin-margined).
perp.contracts[].multipliernumber—Coins per quoted unit (1000 for `1000PEPE`-style contracts). Basis is unaffected.
perp.contracts[].mark_pricenumber|null—Mark price published by the exchange.
perp.contracts[].index_pricenumber|null—Index price published by the exchange.
perp.contracts[].last_pricenumber|null—Last traded price.
perp.contracts[].index_kindstring|null—What the index is: `exchange_index`, `oracle`, or another kind that is shown but not aggregated.
perp.contracts[].basis_pctnumber|null%(mark − index) ÷ index × 100 for perpetuals and delivery; in rankings, the cross-exchange median.
perp.contracts[].basis_absnumber|null—mark − index, in the quote currency.
perp.contracts[].basis_last_pctnumber|null%(last − index) ÷ index × 100; `null` when there is no recent trade.
perp.contracts[].basis_last_reasonstring|null—Why `basis_last_pct` is null.
perp.contracts[].index_lag_snumber|nullsSeconds between the mark timestamp and the index timestamp of the row.
perp.contracts[].oi_usdnumber|nullUSDOpen interest of the contract, single-sided; used as weight.
perp.contracts[].vol_usd_24hnumber|nullUSD24h notional volume of the contract; used as weight.
perp.contracts[].primaryboolean—True for the contract that represents its exchange in median and mean.
perp.contracts[].in_aggregateboolean—True when the row passed the inclusion rules.
perp.contracts[].excluded_reasonstring|null—Why the row is not in the aggregate.
perp.contracts[].last_tsnumber|nullmsTime of the last trade.
perp.contracts[].observed_atnumber|nullmsTimestamp given by the source for the data.
perp.contracts[].received_atnumbermsTime the CoinBoss collector received the data.
perp.contracts[].age_snumbersSeconds since the row was received.
spot_perpobject—Perpetual price against the spot price of the same exchange.
spot_perp.unitstring—Unit of the basis values (percent).
spot_perp.aggregateobject—Cross-exchange aggregate of the section.
spot_perp.aggregate.oi_weighted_pctnumber%Basis weighted by open interest; rows without an OI weight are left out.
spot_perp.aggregate.oi_weight_usdnumberUSDSum of the open-interest weights used.
spot_perp.aggregate.n_oi_weightednumber—Rows that carried an OI weight.
spot_perp.aggregate.vol_weighted_pctnumber%Basis weighted by 24h notional volume.
spot_perp.aggregate.vol_weight_usdnumberUSDSum of the volume weights used.
spot_perp.aggregate.n_vol_weightednumber—Rows that carried a volume weight.
spot_perp.aggregate.median_pctnumber%Median basis over one primary contract per exchange.
spot_perp.aggregate.mean_pctnumber%Simple mean over the same set as the median.
spot_perp.aggregate.n_exchangesnumber—Exchanges in the aggregate.
spot_perp.aggregate.n_contractsnumber—Contracts in the aggregate.
spot_perp.aggregate.minobject—Exchange and contract with the lowest basis.
spot_perp.aggregate.min.exchangestring—Exchange id (lower case).
spot_perp.aggregate.min.symbolstring—Contract symbol in CoinBoss storage form.
spot_perp.aggregate.min.basis_pctnumber%(mark − index) ÷ index × 100 for perpetuals and delivery; in rankings, the cross-exchange median.
spot_perp.aggregate.maxobject—Exchange and contract with the highest basis.
spot_perp.aggregate.max.exchangestring—Exchange id (lower case).
spot_perp.aggregate.max.symbolstring—Contract symbol in CoinBoss storage form.
spot_perp.aggregate.max.basis_pctnumber%(mark − index) ÷ index × 100 for perpetuals and delivery; in rankings, the cross-exchange median.
spot_perp.pairsarray—One row per perpetual / spot pair of the same exchange.
spot_perp.pairs[]object—One row per perpetual / spot pair of the same exchange.
spot_perp.pairs[].exchangestring—Exchange id (lower case).
spot_perp.pairs[].symbolstring—Contract symbol in CoinBoss storage form.
spot_perp.pairs[].spot_symbolstring—Spot market used as the spot leg.
spot_perp.pairs[].quotestring—Quote currency of the contract.
spot_perp.pairs[].spot_multnumber—Factor applied to the spot price so that both legs quote the same quantity.
spot_perp.pairs[].futures_pricenumber|null—Perpetual price used; see `price_kind`.
spot_perp.pairs[].price_kindstring|null—Which perpetual price was used: `last` or `mark`.
spot_perp.pairs[].spot_pricenumber—Spot last price, after `spot_mult`.
spot_perp.pairs[].basis_pctnumber|null%(mark − index) ÷ index × 100 for perpetuals and delivery; in rankings, the cross-exchange median.
spot_perp.pairs[].basis_last_pctnumber|null%(last − index) ÷ index × 100; `null` when there is no recent trade.
spot_perp.pairs[].basis_mark_pctnumber|null%(mark − spot) ÷ spot × 100.
spot_perp.pairs[].leg_gap_snumbersSeconds between the timestamps of the two legs.
spot_perp.pairs[].spot_time_kindstring—What the spot timestamp is (trade time or receive time).
spot_perp.pairs[].spot_vol_24hnumber|null—24h turnover of the spot market, in its quote currency.
spot_perp.pairs[].oi_usdnumber|nullUSDOpen interest of the contract, single-sided; used as weight.
spot_perp.pairs[].vol_usd_24hnumber|nullUSD24h notional volume of the contract; used as weight.
spot_perp.pairs[].primaryboolean—True for the contract that represents its exchange in median and mean.
spot_perp.pairs[].in_aggregateboolean—True when the row passed the inclusion rules.
spot_perp.pairs[].excluded_reasonstring|null—Why the row is not in the aggregate.
spot_perp.pairs[].received_atnumbermsTime the CoinBoss collector received the data.
spot_perp.pairs[].spot_received_atnumbermsTime the spot leg was received.
deliveryobject—Delivery (dated) futures basis.
delivery.unitstring—Unit of the basis values (percent).
delivery.contractsarray—One row per contract.
delivery.contracts[]object—One row per contract.
delivery.contracts[].exchangestring—Exchange id (lower case).
delivery.contracts[].symbolstring—Contract symbol in CoinBoss storage form.
delivery.contracts[].native_symbolstring—Contract symbol as the exchange writes it.
delivery.contracts[].quotestring—Quote currency of the contract.
delivery.contracts[].margin_typestring—Margin type of the contract (for example USDT-margined, coin-margined).
delivery.contracts[].expiry_tsnumbermsExpiry time of the delivery contract.
delivery.contracts[].days_to_expirynumberdaysDays until expiry.
delivery.contracts[].mark_pricenumber—Mark price published by the exchange.
delivery.contracts[].last_pricenumber|null—Last traded price.
delivery.contracts[].index_pricenumber—Index price published by the exchange.
delivery.contracts[].index_kindstring—What the index is: `exchange_index`, `oracle`, or another kind that is shown but not aggregated.
delivery.contracts[].basis_pctnumber%(mark − index) ÷ index × 100 for perpetuals and delivery; in rankings, the cross-exchange median.
delivery.contracts[].annualized_pctnumber|null% per yearbasis_pct × 365 ÷ days to expiry, simple interest; `null` inside the last day.
delivery.contracts[].basis_reasonnull—Why `basis_pct` is null.
delivery.contracts[].index_lag_snumbersSeconds between the mark timestamp and the index timestamp of the row.
delivery.contracts[].basis_last_pctnumber|null%(last − index) ÷ index × 100; `null` when there is no recent trade.
delivery.contracts[].annualized_last_pctnumber|null% per yearAnnualised basis using the last traded price.
delivery.contracts[].spot_symbolstring|null—Spot market used as the spot leg.
delivery.contracts[].spot_pricenumber|null—Spot last price, after `spot_mult`.
delivery.contracts[].spot_price_kindstring|null—Which futures price was compared with spot.
delivery.contracts[].basis_spot_pctnumber|null%(futures − same-exchange spot) ÷ spot × 100.
delivery.contracts[].annualized_spot_pctnumber|null% per yearAnnualised basis against same-exchange spot.
delivery.contracts[].annualized_reasonstring|null—Why the annualised value is null (for example `expiry_lt_1d`).
delivery.contracts[].oi_usdnumber|nullUSDOpen interest of the contract, single-sided; used as weight.
delivery.contracts[].vol_usd_24hnumber|nullUSD24h notional volume of the contract; used as weight.
delivery.contracts[].last_tsnumber|nullmsTime of the last trade.
delivery.contracts[].observed_atnumber|nullmsTimestamp given by the source for the data.
delivery.contracts[].received_atnumbermsTime the CoinBoss collector received the data.
delivery.contracts[].age_snumbersSeconds since the row was received.
coverageobject—What is and is not included in the numbers. Compare this before comparing totals with another source.
coverage.included_exchangesarray—Sources whose fresh data is included.
coverage.included_exchanges[]string—Sources whose fresh data is included.
coverage.unavailablearray—Sources that could not be included, each with a reason. They are never counted as 0.
coverage.unavailable[]object—Sources that could not be included, each with a reason. They are never counted as 0.
coverage.unavailable[].exchangestring—Exchange id (lower case).
coverage.unavailable[].reasonstring—Machine-readable reason code.
coverage.unavailable[].detailstring—Human-readable explanation of the reason.
coverage.stale_excludedarray—Rows left out because their last update is outside the fresh window. empty in the samples used to generate this table
coverage.missing_fieldsarray—Exchanges that do not publish one of the prices.
coverage.excluded_from_aggregatearray—Rows shown but left out of the aggregate, each with the reason.
coverage.excluded_from_aggregate[]object—Rows shown but left out of the aggregate, each with the reason.
coverage.excluded_from_aggregate[].exchangestring—Exchange id (lower case).
coverage.excluded_from_aggregate[].symbolstring—Contract symbol in CoinBoss storage form.
coverage.excluded_from_aggregate[].sectionstring—Section the row belongs to.
coverage.excluded_from_aggregate[].reasonstring—Machine-readable reason code.
coverage.stock_excludedarray—Stock perpetuals that share the ticker and were removed. empty in the samples used to generate this table
coverage.dropped_delisted_rowsnumber—Rows dropped because the contract stopped updating.
coverage.delivery_unavailablearray—Exchanges whose delivery contracts are not collected.
coverage.delivery_unavailable[]object—Exchanges whose delivery contracts are not collected.
coverage.delivery_unavailable[].exchangestring—Exchange id (lower case).
coverage.delivery_unavailable[].reasonstring—Machine-readable reason code.
coverage.delivery_unavailable[].detailstring—Human-readable explanation of the reason.
methodobject—Plain-text statement of the formulas used for this response, one entry per field.
method.perp.basis_pctstring—Formula note for `perp.basis_pct`, plain text.
method.perp.basis_last_pctstring—Formula note for `perp.basis_last_pct`, plain text.
method.perp.aggregate.oi_weighted_pctstring—Formula note for `perp.aggregate.oi_weighted_pct`, plain text.
method.perp.aggregate.vol_weighted_pctstring—Formula note for `perp.aggregate.vol_weighted_pct`, plain text.
method.perp.aggregate.median_pctstring—Formula note for `perp.aggregate.median_pct`, plain text.
method.perp.aggregate.inclusionstring—Formula note for `perp.aggregate.inclusion`, plain text.
method.spot_perp.basis_pctstring—Formula note for `spot_perp.basis_pct`, plain text.
method.spot_perp.aggregate.inclusionstring—Formula note for `spot_perp.aggregate.inclusion`, plain text.
method.delivery.basis_pctstring—Formula note for `delivery.basis_pct`, plain text.
method.delivery.annualized_pctstring—Formula note for `delivery.annualized_pct`, plain text.
method.index_lag_sstring—Formula note for `index_lag_s`, plain text.
method.multiplierstring—Formula note for `multiplier`, plain text.
metaobject—Lineage and freshness of this response.
meta.schemastring—Schema id of this response. It changes only when an existing field changes meaning or type.
meta.sourcearray—Upstream public endpoints the data was collected from.
meta.source[]object—Upstream public endpoints the data was collected from.
meta.source[].exchangestring—Exchange id (lower case).
meta.source[].endpointstring—Public endpoint of the source the collector reads (shown for lineage; clients never call it).
meta.observed_atnumbermsTimestamp given by the source for the data.
meta.received_atnumbermsTime the CoinBoss collector received the data.
meta.fetched_atnumbermsTime this response was assembled.
meta.windowstring—Time window the numbers cover.
meta.qualitystring—FRESH, PARTIAL, STALE, BROKEN or UNAVAILABLE, judged from data timestamps and coverage.
meta.is_staleboolean—True when the data is older than its fresh window.
meta.cache_ttl_snumbersCache lifetime of this response.
meta.fallbackstring—What the endpoint returns when the collector or a source fails.
meta.collector_heartbeat_age_snumbersSeconds since the collector last reported that it is running.
coverage.missing_fields[]object—Exchanges that do not publish one of the prices.
coverage.missing_fields[].exchangestring—Exchange id (lower case).
coverage.missing_fields[].symbolstring—Contract symbol in CoinBoss storage form.
coverage.missing_fields[].missingstring—Price the exchange does not publish (`mark` or `index`).

Generated 2026-11-11 23:00 UTC from 4 real responses.

Example response

/api/sd/basis?coin=BTC · Real response captured 2026-11-13 01:42:45 UTC. Long arrays and maps are shortened for display: meta.source had 20 items; perp.contracts had 37 items; spot_perp.pairs had 22 items; delivery.contracts had 53 items; coverage.unavailable had 4 items; coverage.included_exchanges had 20 items.

  • {
    • "success": true,
    • "schema": "coinboss.sd.basis/1",
    • "now": 1794534165725,
    • "coin": "BTC",
    • "perp": {
      • "unit": "percent",
      • "aggregate": { … 15 },
      • "contracts": [ … 1 ]
      },
    • "spot_perp": {
      • "unit": "percent",
      • "aggregate": { … 12 },
      • "pairs": [ … 1 ]
      },
    • "delivery": {
      • "unit": "percent",
      • "contracts": [ … 1 ]
      },
    • "coverage": {
      • "included_exchanges": [ … 8 ],
      • "unavailable": [ … 1 ],
      • "stale_excluded": [],
      • "missing_fields": [],
      • "excluded_from_aggregate": [ … 1 ],
      • "stock_excluded": [],
      • "dropped_delisted_rows": 2,
      • "delivery_unavailable": [ … 1 ]
      },
    • "method": {
      • "perp.basis_pct": "(mark_price - index_price) / index_price * 100, percent; mark and index are both published by the same exchange for that…",
      • "perp.basis_last_pct": "(last_price - index_price) / index_price * 100; null when the exchange gives no last-trade price or the last trade is mo…",
      • "perp.aggregate.oi_weighted_pct": "sum(basis_pct * oi_usd) / sum(oi_usd) over all included perpetual contracts that have an open-interest weight; oi_usd fr…",
      • "perp.aggregate.vol_weighted_pct": "same with 24h notional volume (market_tickers.volume_usd / sd_contract_latest.vol_usd_24h, <= 1 h old) as weight",
      • "perp.aggregate.median_pct": "median of basis_pct over one primary contract per exchange (largest OI, then volume, then USDT-margined); mean_pct is th…",
      • "perp.aggregate.inclusion": "row is fresh (<= 180 s), basis_pct is not null, index_kind is exchange_index or oracle, the contract traded within 24 h …",
      • "spot_perp.basis_pct": "(perp last_price, or mark_price when last is unusable - spot last price * spot_mult) / (spot last price * spot_mult) * 1…",
      • "spot_perp.aggregate.inclusion": "as perp, plus spot 24h turnover >= 10000 (quote currency) when the exchange reports it",
      • "delivery.basis_pct": "(F - S) / S * 100 with F = mark_price and S = the exchange index price of the underlying; basis_last_pct uses F = last_p…",
      • "delivery.annualized_pct": "basis_pct * 365 / days_to_expiry, simple (not compounded); null when days_to_expiry < 1; days_to_expiry = (expiry_ts - p…",
      • "index_lag_s": "seconds between the mark timestamp and the index timestamp of the row; 0 when the exchange returns both in one response;…",
      • "multiplier": "contract units per coin (1000PEPE, kPEPE = 1000); mark and index carry the same multiplier so basis_pct is unaffected; s…"
      },
    • "meta": {
      • "schema": "coinboss.sd.basis/1",
      • "source": [ … 1 ],
      • "observed_at": 1794534153288,
      • "received_at": 1794534153368,
      • "fetched_at": 1794534165725,
      • "window": "latest",
      • "quality": "FRESH",
      • "is_stale": false,
      • "cache_ttl_s": 20,
      • "fallback": "rows older than 180 s are excluded; if no exchange is fresh the last stored rows (<= 1 h old) are served with is_stale=t…",
      • "collector_heartbeat_age_s": 4
      }
    }

Verified samples

Besides the example above, the probe calls this endpoint with these parameters and checks the schema each time.

ParametersHTTPLatencyResult
coin=ETH20025 msPass FRESH
coin=SOL20021 msPass FRESH
coin=PEPE20027 msPass PARTIAL
—4002 msPass returns the expected error

Checked 2026-11-13 01:28:05 UTC

Details

Authentication
None. Public endpoint.
Rate limit
1200 requests per minute per IP
Server cache
20s
Edge micro-cache
10s
Update frequency
Collector round every 60 seconds; a row is fresh for 180 seconds. Hourly snapshots feed the history.
Window
Latest value per contract.
Data sources
Mark price, index price and last price published by 21 derivatives exchanges, plus the spot price of the same exchange, collected and stored by CoinBoss (sd_px_latest, sd_px_hourly).
Exchange coverage
21 exchanges. Exchanges that do not publish an index or mark price are listed under `coverage.unavailable`; rows whose two price legs are more than 60 seconds apart return `null`. Rows left out of the aggregate are listed under `coverage.excluded_from_aggregate` with the reason.
Pagination
No paging.
Sorting
Contracts with the largest open interest first.
Units
All basis values in percent. Prices in the quote currency of the contract (USDT / USDC / USD). `oi_usd` single-sided.
Method
Perpetual: basis_pct = (mark − index) ÷ index × 100. Spot-perp: (perpetual price − spot price) ÷ spot price × 100, same exchange and quote currency. Delivery: basis_pct = (futures − index) ÷ index × 100; annualized_pct = basis_pct × 365 ÷ days to expiry (simple interest; `null` inside the last day). Aggregates use one primary contract per exchange; a row enters only if it is fresh, traded within 24 hours and |basis| ≤ 10 %.
Timestamps
Unix epoch milliseconds (UTC) unless the field description says otherwise
Response format
json
Stability
Stable
Available since
2026-11-11

Live status

AvailableChecked 2026-11-13 01:42:45 UTCHTTP 20032 msSchema matchesNewest data point 12s old

Availability, last 30 days

100% of 380 checks passed

Errors

Failed calls share one shape on every endpoint. The full list is on the errors page. Errors and rate limits →

CodeHTTPMeaningWhat to do
INVALID_PARAM400A required parameter is missing or a value is not accepted. `param` names the parameter when it is known.Do not retry unchanged; fix the request.
UNAUTHORIZED401The `CB-API-KEY` header was sent but the key is unknown or revoked. Public data needs no key — drop the header or use a valid key.Do not retry unchanged.
FORBIDDEN403The route is not part of the public API (internal or account-only).Do not retry.
NOT_FOUND404Unknown route, or the requested coin / exchange / fund does not exist.Do not retry; check the path and identifiers against the catalog.
RATE_LIMITED429More requests than the per-minute limit. `Retry-After` gives the seconds to wait.Wait for `Retry-After`, then retry with backoff.
INTERNAL500Unexpected server error. The message is generic by design; quote `request_id` when reporting it.Retry once after a few seconds; report it with the request id if it persists.
UPSTREAM_FAILED503The data source behind this endpoint did not answer in time. No stale or substitute numbers are returned in its place.Retry with backoff; check the status page.
UNAVAILABLE501 / 503The dataset is temporarily not ready (cache warming) or the endpoint has no lawful public source yet.Retry later; the catalog marks endpoints that are unavailable by design.
REQUEST_FAILED200Some older endpoints answer HTTP 200 with `success: false`. Always check `success`, not only the HTTP status.Depends on the message; treat as a failed request.

Try it

GET/api/sd/basisDegraded
Parameters

string — Coin symbol, case-insensitive (for example `BTC`). Missing or malformed values return 400.

Request URLhttps://www.coinboss.com/api/sd/basis?coin=BTC
Choose an endpoint and press “Send request”. The response, headers and timing will appear here.