Loading…

Inventory

Valuation, performance and collections for any public Steam inventory.

Items in a profile inventory, with market value

GET/api/inventory/{profileId}

One row per item held, with its quantity and current market value, paginated. Accepts a profile id or guid, a Steam vanity name, or a 64-bit Steam id.

The default page size is large (2,000) because this is the whole-inventory view, and pageSize is clamped to 5,000 rather than rejected. metric chooses what the primary sort ranks on and priceSort gives it a direction.

It answers 401 when the profile has opted out of item analytics and the caller is neither its owner nor an administrator. That applies to every per-profile inventory read.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
searchquerynoFilter by item name or type.
collectionquerynoFilter to a single collection name (all = no filter).
priceSortquerynoPrimary sort by per-item market price. Defaults to desc.

One of: asc, desc

nameSortquerynoName order (A-Z / Z-A). Defaults to az.

One of: az, za

sortKeyquerynoWhich dropdown is the primary sort; the other only breaks ties. Defaults to price.

One of: price, name

metricquerynoWhat the primary sort ranks on (priceSort gives it a direction). price = per-unit market price, stack = unit price × owned quantity, ath/atl = the current Steam ask as a ratio of the all-time high/low sale (ath desc / atl asc = "closest to"), demand = Steam units sold in the last 24 h, supply = Steam sell-order count. Defaults to price; an unrecognised value falls back to it rather than rejecting. ath, atl, demand and supply are Steam-only measures, so unlike price and stack they ignore the market parameter and always rank on Steam’s figures.

One of: price, stack, ath, atl, demand, supply

pagequeryno1-based page index. Defaults to 1.
pageSizequerynoItems per page. Defaults to 2000, max 5000.
marketquerynoValuation source for each item price: steam (default) or a specific market key (e.g. Skinport) present in this inventory. Also scopes visibility: unless includeUnpriced=true, only items priced by the selected view are listed.
includeUnpricedquerynotrue includes every owned item. Default (false) hides items the selected view cannot price — Steam view requires a resale price (store-only items are hidden), a market view requires that market's price. The inventory value endpoint keeps counting the full owned set.

One of: true, false

currencyqueryno3-letter currency code. Defaults to the profile FK / USD.

Request

curl "https://api.scmm.app/api/inventory/<profileId>?search=<search>"

Response 200 · application/json · object

  • array<object>
  • page*number
  • pageSize*number
  • total*number
  • hasMore*boolean
  • collections*array<string>
  • markets*array<string>

Collections represented in a profile inventory

GET/api/inventory/{profileId}/collections

One row per collection the profile owns at least one item from, with how much of the set it holds and what that is worth. It is the set-completion view of an inventory rather than a list of items.

It answers 401 when the profile has opted out of item analytics and the caller is neither its owner nor an administrator.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
includeUnownedquerynoIf true, returns every tracked collection regardless of ownership (development env only).
currencyqueryno3-letter currency code. Defaults to the profile FK / USD.

Request

curl "https://api.scmm.app/api/inventory/<profileId>/collections?includeUnowned=<includeUnowned>"

Response 200 · application/json · array<object>

  • *array<object>

Total inventory value over a trailing window

GET/api/inventory/{profileId}/history

One point per day of the profile’s total inventory value, oldest first. A day the value was never computed on is absent rather than zero — never interpolate across a gap, because a missing day means no snapshot, not a worthless inventory.

It answers 401 when the profile has opted out of item analytics and the caller is neither its owner nor an administrator.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
periodquerynoWindow: 1d, 7d, 30d, 90d. Defaults to 30d.

One of: 1d, 7d, 30d, 90d

currencyqueryno3-letter currency code. Defaults to the profile FK / USD.

Request

curl "https://api.scmm.app/api/inventory/<profileId>/history?period=1d"

Response 200 · application/json · array<object>

  • timestamp*string
  • totalValue*number

Purchase price, market price and return per item

GET/api/inventory/{profileId}/investmentAuth required

Requires authentication, and answers 401 for anyone but the inventory owner or an administrator. Rows are one per inventory item (never grouped by skin) because the purchase price is recorded per item. Every money field is in the resolved display currency.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
searchquerynoFilter by item name or type.
sortByquerynoColumn to sort on. Defaults to buyPrice.

One of: name, buyPrice, marketPrice, marketFee, profit, roi

sortDirectionquerynoSort direction. Defaults to desc.

One of: asc, desc

pagequeryno1-based page index. Defaults to 1.
pageSizequerynoItems per page. Defaults to 25, max 100.
currencyqueryno3-letter currency code. Defaults to the profile FK / USD.

Request

curl "https://api.scmm.app/api/inventory/<profileId>/investment?search=<search>" \
  -H "x-api-key: YOUR_KEY_HERE"

Response 200 · application/json · object

  • array<object>
  • page*number
  • pageSize*number
  • total*number

    Matching rows (inventory assets). Smaller than totalUnits when the profile holds a stack.

  • totalUnits*number

    Matching units — sum(quantity), the figure the page header calls "Inventory Items".

  • hasMore*boolean
  • currency*string
  • includeMarketFees*boolean

Invested, gains, losses and net return, totalled

GET/api/inventory/{profileId}/investment/totalsAuth required

Requires authentication, and answers 401 for anyone but the inventory owner or an administrator. Every figure is null until more than half the inventory carries purchase data — below that the numbers describe the missing data, not the portfolio.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
currencyqueryno3-letter currency code. Defaults to the profile FK / USD.

Request

curl "https://api.scmm.app/api/inventory/<profileId>/investment/totals?currency=USD" \
  -H "x-api-key: YOUR_KEY_HERE"

Response 200 · application/json · object

  • invested*number | null
  • gains*number | null
  • losses*number | null
  • netReturn*number | null
  • currency*string
  • itemsWithBuyPrices*number
  • itemCount*number
  • hasSetupInvestment*boolean

Performance overview for one profile inventory

GET/api/inventory/{profileId}/performance

The summary numbers for one inventory over the chosen window: its current value, the change across the window, the best and worst movers and the per-collection deltas. It is the overview the more specific performance/* endpoints break down.

Every figure is computed over period, which defaults to 24h — the shortest window and the noisiest, so widen it before drawing conclusions. It answers 401 when the profile has opted out of item analytics and the caller is neither its owner nor an administrator.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
periodquerynoWindow: 24h, 7d, 30d, 90d. Defaults to 24h.

One of: 24h, 7d, 30d, 90d

Request

curl "https://api.scmm.app/api/inventory/<profileId>/performance?period=24h"

Response 200 · application/json · object

  • object
  • array<object>
  • array<object>
  • historyBackfillPending*boolean

Per-collection performance over a window

GET/api/inventory/{profileId}/performance/collections

One row per collection the profile owns from, with its value and its value-weighted change over the window. Value-weighted rather than a simple mean, so a collection’s change reflects what the holder actually owns rather than treating one cheap item as equal to a set.

It answers 401 when the profile has opted out of item analytics and the caller is neither its owner nor an administrator.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
periodquerynoWindow: 24h, 7d, 30d, 90d. Defaults to 24h.

One of: 24h, 7d, 30d, 90d

Request

curl "https://api.scmm.app/api/inventory/<profileId>/performance/collections?period=24h"

Response 200 · application/json · array<object>

  • name*string
  • iconUrl*string | null
  • value*number
  • changePercent*number | null
  • currency*string
  • ownedCount*number
  • totalCount*number

Wipe and store-release events in a window

GET/api/inventory/{profileId}/performance/events

Dated game events inside the same window a performance series covers: monthly force wipes and item-store releases. They are returned separately from the series so a client can annotate it without a second time axis, and they explain most of the sharp moves in one.

It answers 401 when the profile has opted out of item analytics and the caller is neither its owner nor an administrator.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
daysquerynoTrailing window in days. 0 returns all time. Defaults to 30.

Request

curl "https://api.scmm.app/api/inventory/<profileId>/performance/events?days=30"

Response 200 · application/json · array<object>

  • kind*object
  • label*string
  • timestamp*string

Inventory performance report as CSV

GET/api/inventory/{profileId}/performance/export

The same figures as the performance endpoints, as a CSV file: the portfolio summary followed by one row per owned item. Responds text/csv as an attachment rather than JSON, and the figures are computed over period in the resolved currency.

It answers 401 when the profile has opted out of item analytics and the caller is neither its owner nor an administrator.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
periodquerynoWindow the figures are computed over: 24h, 7d, 30d, 90d. Defaults to 24h.

One of: 24h, 7d, 30d, 90d

currencyqueryno3-letter currency code. Defaults to the profile FK / USD.

Request

curl "https://api.scmm.app/api/inventory/<profileId>/performance/export?period=24h"

Portfolio value series over a trailing window

GET/api/inventory/{profileId}/performance/history

One point per day of the profile’s portfolio value, oldest first, over a trailing window in days. days=0 returns the whole recorded history. A day with no snapshot is absent rather than zero.

It answers 401 when the profile has opted out of item analytics and the caller is neither its owner nor an administrator.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
daysquerynoTrailing window in days. 0 returns all time. Defaults to 30.

Request

curl "https://api.scmm.app/api/inventory/<profileId>/performance/history?days=30"

Response 200 · application/json · array<object>

  • timestamp*string
  • value*number

Per-item performance for one profile inventory

GET/api/inventory/{profileId}/performance/items

One row per item held, with its price, its change over the window, its recent volume and a sparkline of its recent levels — paginated, searchable and sortable. It is the detail behind the performance overview.

It answers 401 when the profile has opted out of item analytics and the caller is neither its owner nor an administrator.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
periodquerynoWindow: 24h, 7d, 30d, 90d. Defaults to 24h.

One of: 24h, 7d, 30d, 90d

searchquerynoFilter by item name or type.
sortquerynoSort order. Defaults to price_desc.

One of: price_asc, price_desc, change_asc, change_desc, liquidity_asc, liquidity_desc, volume_asc, volume_desc

pagequeryno1-based page index. Defaults to 1.
pageSizequerynoItems per page. Defaults to 24, max 100.

Request

curl "https://api.scmm.app/api/inventory/<profileId>/performance/items?period=24h"

Response 200 · application/json · object

  • array<object>
  • total*number
  • page*number
  • pageSize*number

Profile summary for an inventory

GET/api/inventory/{profileId}/summary

Who an inventory belongs to, in one small response: Steam id, name, avatar and when the inventory was last imported. It is the header a client needs before any of the heavier inventory reads, and it accepts the same identifier forms they do.

It answers 401 when the profile has opted out of item analytics and the caller is neither its owner nor an administrator.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.

Request

curl "https://api.scmm.app/api/inventory/<profileId>/summary"

Response 200 · application/json · object

  • profileId*string
  • steamId*string
  • name*string | null
  • avatarUrl*string | null
  • lastUpdatedInventoryOn*string | null
  • privacy*number

Current total value of a profile inventory

GET/api/inventory/{profileId}/value

The current total market value of one inventory, plus the item counts behind it. This is the cheapest inventory read and the one to poll; the item list and the performance endpoints answer the same question in far more detail and cost accordingly.

It answers 401 when the profile has opted out of item analytics and the caller is neither its owner nor an administrator.

Parameters

NameInRequiredDescription
profileIdpathyesProfile id, profile guid, vanity url, or 64-bit Steam id.
marketquerynoValuation market. steam (default) prices via the Steam Community Market and refreshes the stored snapshot; a MarketType key returns a view-only total under that market’s listing prices.
currencyqueryno3-letter currency code. Defaults to the profile FK / USD.

Request

curl "https://api.scmm.app/api/inventory/<profileId>/value?market=<market>"

Response 200 · application/json · object

  • totalValue*number
  • itemCount*number
  • currency*string
  • profitLoss*number

Resolve a Steam id and queue an inventory import

POST/api/inventory/calculate

Resolves the identifier to a 64-bit Steam id (resolving vanity names via Steam when needed), creates a lightweight profile on first sight, and enqueues an inventory import. The import runs asynchronously — poll the profile’s lastUpdatedInventoryOn for completion.

Request body application/json · required

  • identifier*string

Request

curl -X POST "https://api.scmm.app/api/inventory/calculate" \
  -H "Content-Type: application/json" \
  -d '{"identifier":"<identifier>"}'

Status of an on-demand inventory import

GET/api/inventory/import-status/{steamId}

The poll target for an import queued by POST /api/inventory/calculate. It reports whether the import has produced a value, is still running, or finished without one — the third case is a real answer rather than a failure, and it is what a private or empty Steam inventory returns. Takes a 64-bit Steam id.

Parameters

NameInRequiredDescription
steamIdpathyes64-bit Steam id.

Request

curl "https://api.scmm.app/api/inventory/import-status/<steamId>"

Trigger an inventory import from Steam

POST/api/inventory/import/{steamId}Auth required

Synchronously pages the Steam inventory and reconciles items into the database. Requires authentication. Throttled to once per hour per profile; force=true bypasses the throttle but is honored only for the owner of the Steam id (or an admin) — other callers stay throttled.

Parameters

NameInRequiredDescription
steamIdpathyes64-bit Steam id.
forcequerynoOwner/admin only: bypass the 1-hour sync throttle and fetch from Steam now.

Request

curl -X POST "https://api.scmm.app/api/inventory/import/<steamId>?force=<force>" \
  -H "x-api-key: YOUR_KEY_HERE"

Response 200 · application/json · object

  • imported*number
  • updated*number
  • errorstringoptional
  • privatebooleanoptional
  • completebooleanoptional
  • skippedbooleanoptional

Update purchase price or source for one item

PUT/api/inventory/item/{itemId}Auth required

Requires authentication, and answers 401 unless the item belongs to you (or you are an administrator). Absent fields are left unchanged; an explicit null clears one. Choosing a free acquisition source (gambling, gift, game drop) always clears the price.

Parameters

NameInRequiredDescription
itemIdpathyesSteam asset id of the inventory item, as returned in itemId.

Request body application/json · required

  • buyPricenumber | nulloptional
  • currencystring | nulloptional
  • acquiredBynumberoptional

Request

curl -X PUT "https://api.scmm.app/api/inventory/item/<itemId>" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_KEY_HERE" \
  -d '{"buyPrice":0}'

Highest-valued inventories, paginated and sortable

GET/api/inventory/leaderboard

Serves the top 500 inventories for the requested sort, not every inventory tracked. total is therefore capped at 500 and totalPages with it; pages beyond the cap return no entries. For the true, uncapped count of valued inventories use inventoriesTracked on GET /api/inventory/leaderboard/stats.

Parameters

NameInRequiredDescription
pagequeryno1-based page index. Defaults to 1. Pages past the 500-row cap return no entries.
pageSizequerynoRows per page. Defaults to 50, max 100.
sortquerynoSort key. Defaults to value.

One of: value, time, amount

dirquerynoSort direction. Defaults to desc.

One of: asc, desc

Request

curl "https://api.scmm.app/api/inventory/leaderboard?page=1"

Inventory totals across every valued profile

GET/api/inventory/leaderboard/stats

Uncapped on purpose — this is the counterpart to the leaderboard's 500-row cap, and the only place the true number of valued inventories is published.

Request

curl "https://api.scmm.app/api/inventory/leaderboard/stats"

Item ids in the authenticated user’s own inventory

GET/api/inventory/owned/item-idsAuth required

Lightweight companion to the inventory list — hydrates the "Owned" badge across the app. Distinct ids only, no quantities and no ordering. Scoped to the resolved app, so a Rust session never reports a CS2 item.

Request

curl "https://api.scmm.app/api/inventory/owned/item-ids" \
  -H "x-api-key: YOUR_KEY_HERE"

Response 200 · application/json · array<string>

  • *array<string>