Loading…

Statistics

Market capitalisation, index funds, supply and per-store analytics.

Every index, valued at the latest snapshot day

GET/api/statistics/indexes

Every tracked index with its current level and its trailing changes, in one response. An index value is the market-cap-weighted average price of its basket, and supply is held at the latest snapshot day’s figure on both sides of every comparison, so a change in the level is a change in price rather than in the supply estimate behind it.

Levels are not comparable between indexes: a higher value means that category’s average skin costs more, not that it performed better. Use the change fields to compare performance. change90d, change180d and change52w are null — never 0 — until the comparable series is that deep, and seriesStart and comparableDays say how deep it is. An index with fewer than 5 priced constituents reports value: null with valueUnavailableReason set, because a 1–4 item index is one item’s price and would top the rankings on noise.

This is a different measure from GET /api/statistics/indexFund, which is a single global unweighted mean of sale prices. Cached 15 minutes per currency.

Parameters

NameInRequiredDescription
currencyqueryno3-letter currency code. Defaults to USD.

Request

curl "https://api.scmm.app/api/statistics/indexes?currency=USD"

Response 200 · application/json · object

  • array<object>
  • object

Daily level series for one or more indexes

GET/api/statistics/indexes/history

One series entry per requested code. Each carries its own range-independent badge fields: all-time high and the trailing changes are identical for every range, because an all-time high that moves when you change the zoom is not an all-time high. Only points is range-scoped. Days whose ask coverage is far from the latest day are excluded — a third, different boundary from /marketCap/history's supply basis and /indexFund's sales coverage: before ask coverage went catalogue-wide, an unpriced item contributed 0 to the past side of the ratio and its full value to the present side, manufacturing growth. Excluded days are gaps — never interpolated or carried forward. Unknown and duplicate codes are dropped silently and an empty selection falls back to the global index; nothing here 400s. events carries only computed Rust force wipes. Cached 15 minutes per range + selection + currency.

Parameters

NameInRequiredDescription
rangequerynoChart window. Anything unrecognised (or absent) falls back to year.

One of: month, year, lifetime

currencyqueryno3-letter currency code. Defaults to USD.
codesquerynoComma-separated index codes (repeatable). Unknown codes are ignored; capped at 8 series. Defaults to RS.GLBL.

Request

curl "https://api.scmm.app/api/statistics/indexes/history?range=month"

Response 200 · application/json · object

  • range*enum

    One of: month, year, lifetime

  • array<object>

    One entry per requested code, in request order.

  • array<object>

    Computed Rust force wipes only, clipped to the union of the plotted series.

Daily index-fund series

GET/api/statistics/indexFund

averageItemValue is the headline index-fund value — the mean median sale price across the catalogue, with non-trading items counted as 0 — and it is what summary describes. totalSalesVolume and totalSalesValue are supporting series. The envelope is the same as GET /api/statistics/marketCap/history, so one client code path reads both.

Days whose sales-data coverage is far from the latest day are excluded. That is a different test from the market-cap series’ supply basis, because sales are not derived from supply, and it also drops a run of days that recorded no sale prices at all and would otherwise plot as a collapse to zero. The current day is excluded, matching the v1 API, because a same-day row holds only a partial day's sales. Money is in hundredths here, where the v1 API returned major units. Cached 15 minutes per range and currency.

Parameters

NameInRequiredDescription
rangequerynoChart window. Anything unrecognised (or absent) falls back to year.

One of: month, year, lifetime

currencyqueryno3-letter currency code. Defaults to USD.

Request

curl "https://api.scmm.app/api/statistics/indexFund?range=month"

Response 200 · application/json · object

  • range*enum

    One of: month, year, lifetime

  • array<object>

    Ascending by day. A missing day is a gap — never interpolated.

  • object
  • array<object>

    Clipped to [first point, last point].

Aggregate statistics across every tracked market

GET/api/statistics/market

Six headline numbers for the whole tracked catalogue: how many items are tracked, the value of the open listings across every market, how many markets are currently reporting, the average item price, the number of open listings and the units sold in the last 24 hours.

totalMarketValue is the value of what is for sale, not of what exists. For the value of the whole circulating population use GET /api/statistics/marketCap, which is a much larger number measuring a different thing.

Parameters

NameInRequiredDescription
currencyqueryno3-letter currency code. Defaults to USD.

Request

curl "https://api.scmm.app/api/statistics/market?currency=USD"

Response 200 · application/json · object

  • totalItems*number
  • totalMarketValue*number
  • activeMarkets*number
  • averagePrice*number
  • totalListings*number
  • volumeLast24hrs*number

Headline market-cap figures

GET/api/statistics/marketCap

totalMarketCap is Σ supply × price over the tracked marketable catalogue — the total value of all skins in circulation. It is a different figure from GET /api/statistics/market's totalMarketValue, which is the value of open listings only and is orders of magnitude smaller. Supply prefers the estimate over the known subtotal, which is what the daily series does too, so the headline figure and the series agree. Change fields are whole percents against the T-1, T-7 and T-30 daily snapshots, and are null — never 0 — when the baseline day has no rows. Cached 5 minutes per currency.

Parameters

NameInRequiredDescription
currencyqueryno3-letter currency code. Defaults to USD.

Request

curl "https://api.scmm.app/api/statistics/marketCap?currency=USD"

Response 200 · application/json · object

  • totalMarketCap*number

    Σ supply × price over the tracked marketable catalogue — "the total value of all skins in circulation", display-currency hundredths. It is a different figure from GET /api/statistics/market's totalMarketValue, which is the value of open listings only and is orders of magnitude smaller.

  • totalSupply*number

    A count — never currency-converted.

  • totalItemsTracked*number

    A count — never currency-converted.

  • hasEstimatedSupply*boolean

    True when at least one item's contribution to the total used an estimated supply figure rather than a known one.

  • totalListings*number

    Σ open sell orders — the "Items Listed" card. A count — never converted.

  • volume24h*number

    Value traded over the trailing 24h, display-currency hundredths.

  • marketCap24hChange*number | null

    Whole percent (0.61 = +0.61%), not a fraction — legacy returned fractions. null when the baseline day has no snapshot rows; never 0, because "no comparison" is not "no change".

  • marketCap7dChange*number | null
  • marketCap30dChange*number | null

    Most likely of the three to be measured constant-supply — 30 days reaches past the mid-July 2026 supply-estimator step. Read marketCap30dChangeBasis before quoting it as market growth.

  • marketCap24hChangeBasis*enum | null

    How the change was measured. recorded = both ends are recorded market cap, so it includes supply growth. constant-supply = the baseline day's supply basis is unusable, so the figure is the price movement of one fixed basket (same items, latest supply) — cross-checked against legacy at +4.13% vs its +4.07% over 30 days. Null alongside a null change.

    One of: recorded, constant-supply

  • marketCap7dChangeBasis*enum | null

    One of: recorded, constant-supply

  • marketCap30dChangeBasis*enum | null

    One of: recorded, constant-supply

  • volume24hChange*number | null

    Gated on how much sales data each day carries rather than on the supply basis, because traded value is not derived from supply. null means the baseline day recorded far fewer sale prices than the latest day, which would fake a collapse.

  • volume7dChange*number | null
  • volume30dChange*number | null

Daily market-cap series with a range-independent summary

GET/api/statistics/marketCap/history

points is range-scoped; summary is not — All Time High and the 7D/30D/90D changes are identical for every range, because an all-time high that moves when you change the zoom is not an all-time high. A null change means no comparable baseline for that window, never 0%. Days whose summed supply basis is incomparable to the latest day are excluded: our history has a supply-estimator level shift that would otherwise plot as an 8x cliff, so the usable series is shorter than the raw row count and month/year/lifetime may return the same points. Missing days are left as gaps — never interpolated. events carries only computed Rust force wipes; skin/Twitch drops have no data source. Cached 15 minutes per range + currency.

Parameters

NameInRequiredDescription
rangequerynoChart window. Anything unrecognised (or absent) falls back to year.

One of: month, year, lifetime

currencyqueryno3-letter currency code. Defaults to USD.

Request

curl "https://api.scmm.app/api/statistics/marketCap/history?range=month"

Response 200 · application/json · object

  • range*enum

    One of: month, year, lifetime

  • array<object>

    Ascending by day. A missing day is a gap — never interpolated or carried forward.

  • object
  • array<object>

    Clipped to [first point, last point]. Computed Rust force wipes only — skin/Twitch drops have no data source, so no pill is fabricated for them.

Paginated, sortable market-cap item table

GET/api/statistics/marketCap/items

total is the filtered count before pagination. Sortable on price, change24h, change7d, change30d, supply and marketCap, defaulting to marketCap descending, the same default the v1 API used. Every sort is tie-broken on name, id so pagination cannot repeat or drop a row, and nulls always sort last. page and pageSize are clamped rather than rejected, so a browse request past the end returns an empty page instead of an error. The three change columns are whole percents against the daily snapshot at exactly T-1, T-7 and T-30, and are null when that day has no row: an all-null priceChange24h means yesterday was never snapshotted, not that prices held still. pricesLast30d omits missing days rather than interpolating them. minPrice and maxPrice are in the display currency.

Parameters

NameInRequiredDescription
pagequeryno1-based. Clamped to [1, 10000].
pageSizequerynoClamped to [1, 100]. Defaults to 30.
sortqueryno

One of: price, change24h, change7d, change30d, supply, marketCap

directionqueryno

One of: asc, desc

filterquerynoCase-insensitive match on the item name.
itemTypequeryno
itemCollectionqueryno
indexquerynoRestrict the rows to one index's basket. Composes with the other filters. RS.GLBL covers the whole catalogue, and an unrecognised code is ignored rather than rejected.

One of: RS.GLBL, RS.WPN, RS.CLT, RS.BPK, RS.DOOR, RS.CRT, RS.ARM, RS.TOOL, RS.DEP, RS.BLD, RS.WALL, RS.OTHR

minPricequerynoDisplay-currency major units (e.g. 100).
maxPricequerynoDisplay-currency major units (e.g. 1000).
minLiquidityqueryno0–100. Items with no market data at all score null, not 0, and a floor above 0 excludes them.
maxLiquidityqueryno0–100. A null-scoring item survives this bound.
ownedquerynotrue restricts to the signed-in profile’s inventory. Ignored when signed out — this endpoint is public and never 401s on an optional filter.
currencyqueryno3-letter currency code. Defaults to USD.
excludequerynoBlacklist term. Repeatable (?exclude=a&exclude=b); an item is dropped when its name contains any term, case-insensitively. Capped at 20 terms of 64 characters — surplus is dropped, over-long terms truncated. % and _ are matched literally.

Request

curl "https://api.scmm.app/api/statistics/marketCap/items?page=1"

Response 200 · application/json · object

  • array<object>
  • total*number

    Filtered count before pagination, which is what the page count is derived from.

  • page*number
  • pageSize*number

Per-item estimated revenue split for a store

GET/api/statistics/store/{id}/itemRevenue

Estimated gross revenue split into sales tax (10%) → item author (25% of the remainder) → Steam (20% of what is left) → publisher (the remainder). Computed in USD and converted once; all amounts are display-currency hundredths. Cached 5 minutes per currency.

Parameters

NameInRequiredDescription
idpathyesStore guid, yyyy-MM-dd-HHmm id, themed name, or current for the active rotation.
currencyqueryno3-letter currency code. Defaults to USD.

Request

curl "https://api.scmm.app/api/statistics/store/<id>/itemRevenue?currency=USD"

Response 200 · application/json · array<object>

  • salesTax*number

    Display-currency hundredths (divide by 100 — never by 10 ** scale).

  • publisherRevenue*number

    Remainder of the split — the four components sum to total exactly.

  • itemGuid*string
  • name*string
  • iconUrl*string | null
  • iconAccentColour*string | null
  • authorRevenue*number
  • platformRevenue*number
  • total*number

Per-item supply breakdown for a store

GET/api/statistics/store/{id}/itemSales

Five supply components per item (market listings, tracked/untracked subscribers, tracked/untracked duplicate stock) plus the total and its label. The two *Estimated values are the untracked remainder (max(estimated − known, 0)) because they stack on top of their tracked counterpart. Counts, not money — currency-independent. Cached 5 minutes.

Parameters

NameInRequiredDescription
idpathyesStore guid, yyyy-MM-dd-HHmm id, themed name, or current for the active rotation.

Request

curl "https://api.scmm.app/api/statistics/store/<id>/itemSales"

Response 200 · application/json · array<object>

  • supplyTotalOwnersEstimated*number

    Untracked remainder — max(ownersEstimated − ownersKnown, 0); it stacks on top of known.

  • supplyTotalInvestorsEstimated*number

    Untracked remainder — max(investorsEstimated − investorsKnown, 0); it stacks on top of known.

  • totalText*string
  • itemGuid*string
  • name*string
  • itemType*string | null
  • iconUrl*string | null
  • iconAccentColour*string | null
  • supplyTotalKnown*number
  • supplyTotalEstimated*number
  • supplyTotalMarketsKnown*number
  • supplyTotalOwnersKnown*number
  • supplyTotalInvestorsKnown*number

Per-item workshop-subscriber timeline for a store

GET/api/statistics/store/{id}/subscribers

Points are decoded from both encodings the column carries (legacy .NET ticks strings and ISO), sorted ascending, and capped at 500 points (first/last kept, evenly sampled between). An item with no points returns an empty timeline. Cached 5 minutes.

Parameters

NameInRequiredDescription
idpathyesStore guid, yyyy-MM-dd-HHmm id, themed name, or current for the active rotation.

Request

curl "https://api.scmm.app/api/statistics/store/<id>/subscribers"

Response 200 · application/json · array<object>

  • array<object>

    Ascending by timestamp. Capped at 500 points (first/last kept, evenly sampled between).

  • name*string
  • iconUrl*string | null
  • iconAccentColour*string | null

Per-item top-seller rank timeline for a store

GET/api/statistics/store/{id}/topSellers

Change-only rows: a rank holds until it moves, so render as a step chart. Series are capped at 500 points (first/last kept, evenly sampled between). For a live rotation each still-ranked series is closed with a synthetic "now" point so a rank that has held for days does not read as stale. Returns [] when nothing has been captured yet. Cached 1 minute.

Parameters

NameInRequiredDescription
idpathyesStore guid, yyyy-MM-dd-HHmm id, themed name, or current for the active rotation.

Request

curl "https://api.scmm.app/api/statistics/store/<id>/topSellers"

Response 200 · application/json · array<object>

  • position*number

    Current rank, or 0 when the item is no longer ranked.

  • array<object>

    Change-only rank timeline, ascending. Capped at 500 points (first/last kept, evenly sampled between). For a live rotation a synthetic "now" point closes each still-ranked series so it does not read as stale.

  • name*string
  • iconUrl*string | null
  • iconAccentColour*string | null

Supply and demand grouped by item category

GET/api/statistics/supply

One row per item category with the number of items in it, its known and estimated supply, its open listings, its 24-hour sales and its total market value. Known supply counts the units this site can see; estimated supply models the rest, and the two are published separately rather than merged so a caller can tell measurement from model.

Parameters

NameInRequiredDescription
currencyqueryno3-letter currency code. Defaults to USD.

Request

curl "https://api.scmm.app/api/statistics/supply?currency=USD"

Response 200 · application/json · array<object>

  • category*string
  • itemCount*number
  • totalSupplyKnown*number
  • totalSupplyEstimated*number
  • totalListings*number
  • totalDemand24hrs*number
  • averagePrice*number
  • totalMarketValue*number