Looking for the overview — what this API returns, what it costs, and a call you can run without a key? See the StockX API page →
E-commerce & Marketplaces

StockX API & Scraper

The StockX API returns live resale-market data for sneakers, streetwear and collectibles as clean JSON.

8 actionsLive JSON1,000 free credits$0.67–$1.50 / 1,000 creditsMCP-ready
Get a free keyOpen in playground

🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.

The primary product_detail endpoint returns a product's title, brand, model, SKU, colorway, retail price, release date and live market data — lowest ask, highest bid and last sale. You can also search, pull recent_sales, price_history and sales_history, browse and see what is trending. It is built for resale-price intelligence, sneaker apps and reselling tools that need StockX market data without scraping a defended marketplace. One ReefAPI key, one shared credit pool, the standard envelope.

Reference

StockX identifiers and market fields, and how to read them

StockX carries three identifiers for one product and two levels of market data, product-wide and per size. Mixing up the two levels is the usual reason a StockX number looks impossible. Every value below was measured on 2026-08-27 on air-jordan-4-retro-bred-reimagined with currency USD and market US.

FieldMeasured valueWhat it means
url_keyair-jordan-4-retro-bred-reimaginedThe slug after stockx.com/. This is what product_detail, recent_sales, price_history and sales_history take.
id and uuid3637430d-2155-4ee9-877e-9ab115ade280The same UUID in both fields. Also accepted in place of url_key.
sku and style_idFV5029-006The manufacturer style code, identical in both fields.
variants[].variant_id750b3017-9dd6-4f6d-8ae4-577ba4344f50One UUID per size. sales_history takes a size string and reports the variant_id it resolved to.
market.lowest_ask204The minimum lowest_ask across all 26 sizes, verified against the variants array.
market.highest_bid247The maximum highest_bid across all 26 sizes. It can and does exceed lowest_ask.
market.price_premium-0.0093(last_sale - retail_price) / retail_price, that is (213 - 215) / 215. A fraction, not a percent.
market.volatility0.1228Coefficient of variation of recent sales, again a fraction.
retail_price215Not currency-converted. Still 215 under currency=EUR while every market price had converted.
variants[].size"3.5" through "18"Strings on the US men's scale, 26 entries. The same list came back for market=DE.
sales_history cursorMjAyNi0wOC0yNiAwMzozMDozNQ==Base64 of a timestamp, here "2026-08-26 03:30:35". Pass it back as cursor to page.

Prices are whole units of the requested currency, not cents: lowest_ask 204 means 204 dollars. Fee fields can carry decimals (ask_service_levels.standard.processing_fee came back 215.8), so parse everything as a number rather than an integer.

Live example

Real request and response JSON

Captured from the indexed primary action, search, on .

Captured request
{
  "method": "POST",
  "url": "https://api.reefapi.com/stockx/v1/search",
  "headers": {
    "x-api-key": "$REEF_KEY",
    "content-type": "application/json"
  },
  "body": {
    "query": "jordan 1"
  }
}
Captured response
{
  "ok": true,
  "meta": {
    "api": "stockx",
    "endpoint": "search",
    "mode": "live",
    "latency_ms": 813.8,
    "record_count": 40,
    "bytes": 30731,
    "cache_hit": false,
    "currency": "USD",
    "market": "US",
    "page": 1,
    "total": 159479,
    "pagination": {
      "page": 1,
      "has_more": true
    }
  },
  "data": {
    "query": "jordan 1",
    "results": [
      {
        "id": "019cfdb4-3545-7b[redacted-phone]f7411145fb",
        "url_key": "air-jordan-1-retro-low-og-sp-travis-scott-sail-tropical-pink",
        "url": "https://stockx.com/air-jordan-1-retro-low-og-sp-travis-scott-sail-tropical-pink",
        "title": "Jordan 1 Retro Low OG SP Travis Scott Sail Tropical Pink",
        "brand": "Jordan",
        "sku": "IQ7604-101",
        "category": "sneakers",
        "gender": "men",
        "image": "https://images.stockx.com/images/Air-Jordan-1-Retro-Low-OG-SP-Travis-Scott-Sail-Tropical-Pink-Product.jpg?fit=fill&bg=FFFFFF&w=700&h=500&fm=webp&auto=compress&q=90&dpr=2&trim=color&updated_at=[redacted-phone]",
        "lowest_ask": 307,
        "highest_bid": 652,
        "last_sale": 343
      },
      {
        "id": "019b0a03-b142-73e7-b0f9-3cf04d719268",
        "url_key": "air-jordan-1-retro-low-og-sp-travis-scott-shy-pink",
        "url": "https://stockx.com/air-jordan-1-retro-low-og-sp-travis-scott-shy-pink",
        "title": "Jordan 1 Retro Low OG SP Travis Scott Shy Pink",
        "brand": "Jordan",
        "sku": "IQ7604-100",
        "category": "sneakers",
        "gender": "men",
        "image": "https://images.stockx.com/images/Air-Jordan-1-Retro-Low-OG-SP-Travis-Scott-Shy-Pink-Product.jpg?fit=fill&bg=FFFFFF&w=700&h=500&fm=webp&auto=compress&q=90&dpr=2&trim=color&updated_at=[redacted-phone]",
        "lowest_ask": 293,
        "highest_bid": 632,
        "last_sale": 356
      },
      {
        "id": "61e4b088-c550-40cb-bec7-9589f6cee907",
        "url_key": "air-jordan-11-retro-gamma-blue-2025",
        "url": "https://stockx.com/air-jordan-11-retro-gamma-blue-2025",
        "title": "Jordan 11 Retro Gamma Blue (2025)",
        "brand": "Jordan",
        "sku": "CT8012-047",
        "category": "sneakers",
        "gender": "men",
        "image": "https://images.stockx.com/images/Air-Jordan-11-Retro-Gamma-Blue-2025-Product.jpg?fit=fill&bg=FFFFFF&w=700&h=500&fm=webp&auto=compress&q=90&dpr=2&trim=color&updated_at=[redacted-phone]",
        "lowest_ask": 180,
        "highest_bid": 379,
        "last_sale": 225
      }
    ],
    "page_info": {
      "page": 1,
      "limit": 40,
      "total": 159479
    }
  }
}
Actions

What the StockX API does

ActionDescriptionConcrete use caseKey params
product_detailfull product by `url` OR `url_key`/`id`/`uuid`: title/brand/model/sku/category/colorway/retail_price/release_date/image + market{lowest_ask,highest_bid,number_of_asks/bids,last_sale,sales_last_72h,last_sale_change_pct/value,avg_price_72h/90d/annual,sales_count_*,price_premium=(last_sale-retail)/retail, volatility=CV-of-recent-sales, ask_service_levels{standard/express_*: count,lowest_ask,processing_fee,delivery}} + per-size variants[]{size,lowest_ask,highest_bid,last_sale}. The market-data moat. `currency` (USD/EUR/GBP/…) + `market` (US/GB/DE/…) optional.Pricing teams call product_detail to get full product by `url` OR `url_key`/`id`/`uuid`.url, url_key, id, uuid, currency, ...
searchproduct search → results[]{id,url_key,url,title,brand,sku,category,image,lowest_ask,highest_bid,last_sale} + page_info{page,limit,total}. Resolves url_keys for product_detail. Optional facet filters: `brand` (e.g. Jordan), `gender` (men/women/…), `category` (sneakers/apparel/…) + `sort` (most-active/featured/release_date/lowest_ask). Return up to 1000 products in one call with `max_results` (40/page, paged for you) — that is StockX's own ceiling, its grid stops at page 26. `page` picks where the window starts. `currency`/`market` optional.Marketplace operators call search to get product search → results[]{id,url_key,url,title,brand,sku,category,image,lowest_ask,highest_b….query, max_results, page, currency, market, ...
recent_salesrecent transaction feed by `url`/`url_key`/`id` → sales[]{amount,created_at} (most recent first) + product ref. Best-effort market-history. `currency`/`market` optional.Catalog enrichment teams call recent_sales to get recent transaction feed by `url`/`url_key`/`id` → sales[]{amount,created_at} (most recent fir….url, url_key, id, uuid, currency, ...
suggestautocomplete query suggestions for `query` (QuerySuggestion text; falls back to search-derived titles if the suggest op drifts).Retail analysts call suggest to get autocomplete query suggestions for `query` (QuerySuggestion text; falls back to search-derive….query
price_historyhistorical price time-series for a product, aggregated from the deep sales feed → series[]{date,count,avg,min,max,last} (oldest→newest) + summary{points,sales_sampled,min,max,avg,first_date,last_date,window_complete}. `window` (30d/90d/180d/365d/all) bounds lookback; `bucket` (day/week/month) sets granularity; optional `size` for per-size history. The #1 resale-trader ask. `currency` optional.Pricing teams call price_history to get historical price time-series for a product, aggregated from the deep sales feed → series[]{da….url, url_key, id, uuid, window, ...
sales_historydeep paginated transaction log → sales[]{amount,created_at,cursor} (newest first) + page_info{cursor,has_more,total,limit,returned} + product. Far deeper than recent_sales (StockX exposes the full ledger, e.g. 60k+ sales). Cursor-paginate with `cursor`; optional `size` filters to one variant. `limit` ≤ 50 (StockX page cap). `currency` optional.Marketplace operators call sales_history to get deep paginated transaction log → sales[]{amount,created_at,cursor} (newest first) + page_info….url, url_key, id, uuid, cursor, ...
browsecategory/vertical grids + sort + facet filters → results[]{id,url_key,url,title,brand,sku,category,image,lowest_ask,highest_bid,last_sale} + page_info{page,limit,total}. Needs at least one of `category` (sneakers/apparel/electronics/collectibles/accessories), `query`, or a facet filter (`brand`/`gender`). `sort` (most-active/featured/release_date/lowest_ask) optional. Return up to 1000 products in one call with `max_results` (40/page, paged for you — StockX's own ceiling, its grid stops at page 26); `page` picks where the window starts. The catalog-discovery surface.Catalog enrichment teams call browse to get category/vertical grids + sort + facet filters → results[]{id,url_key,url,title,brand,sku,cat….category, query, brand, gender, sort, ...
trendingmovers / most-active products (global or within a `category`) → results[] (same card shape as browse) + page_info. Defaults `sort`=most-active. Optional `category`, `brand`, `gender`. Return up to 1000 products in one call with `max_results` (40/page, paged for you — StockX's grid stops at page 26); `page` picks where the window starts. Surfaces what's trading right now.Retail analysts call trending to get movers / most-active products (global or within a `category`) → results[] (same card shape as….category, brand, gender, sort, max_results, ...
Code samples

Call search from your stack

curl -X POST https://api.reefapi.com/stockx/v1/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"query":"jordan 1"}'
MCP one-liner
Ask your MCP-connected assistant: call reefapi.stockx.search with {"query":"jordan 1"}.
Use cases

Who uses this API and why

  • Resale-price tools call product_detail to track lowest ask, highest bid and last sale for a SKU.
  • Sneaker apps use price_history and recent_sales to chart a product's market value over time.
  • Resellers use trending and browse to spot rising products before they spike.
FAQ

Questions developers ask before integrating

Why is highest_bid higher than lowest_ask? That looks impossible.

Because the two product-level numbers do not describe the same size. lowest_ask is the minimum across every size and highest_bid is the maximum across every size. Measured on 2026-08-27: the product block reported lowest_ask 204 and highest_bid 247, and reading the 26-entry variants array gave exactly min(lowest_ask) = 204 and max(highest_bid) = 247. For a real spread on one size, compare variants[].lowest_ask with variants[].highest_bid on the same row.

Are StockX prices in cents or in whole currency units?

Whole units of the currency you asked for. lowest_ask 204 with currency=USD means 204 dollars, not 2.04. StockX itself quotes whole dollars for asks, bids and sales, so those fields look like integers, but fee fields are not: ask_service_levels.standard.processing_fee came back 215.8. Parse them as floats.

What do currency and market actually change?

currency converts the money fields and market switches the regional order book. The same product returned lowest_ask 204, highest_bid 247 and last_sale 213 under USD/US, and 167, 181 and 183 under EUR/DE, so the two are not simply an exchange-rate transform of each other. The size list did not change: both markets returned the same 26 US men's sizes from 3.5 to 18, with size_descriptor null.

Can I trust price_premium when I request a non-USD currency?

No, compute it yourself. price_premium is (last_sale - retail_price) / retail_price, and retail_price is not currency-converted. Measured under EUR/DE the response held last_sale 183 EUR against retail_price 215, which is still the USD figure, and reported price_premium -0.1488. Under USD/US the same formula on 213 and 215 gives -0.0093, which is the honest number. Read the premium in USD, or convert retail yourself first.

Which identifier should I pass, url_key or id?

url_key is the one to store. It is the slug from the product URL, it is what search returns on every row, and it is human-readable, for example air-jordan-4-retro-bred-reimagined. The url_key parameter also accepts the internal UUID (id and uuid carry the same value, 3637430d-2155-4ee9-877e-9ab115ade280) and there is a separate url parameter for the full link. sku, here FV5029-006, is the manufacturer style code and is not a lookup key for this API.

Which market fields can come back null?

avg_price_72h was null while sales_count_72h on the same product was 62, so a null average does not mean no sales. The 90-day and annual averages were populated (222 over 1,976 sales and 237 over 8,058). Per size, lowest_ask, highest_bid and last_sale can each be null at the thin end of the size run, so guard before doing arithmetic across variants.

How do I page through a product's sales history?

sales_history returns page_info with cursor, has_more, total and returned, and you pass the cursor straight back. On size 10 of the measured product, total was 8,653 and the cursor for a five-row page was MjAyNi0wOC0yNiAwMzozMDozNQ==, which decodes to the timestamp 2026-08-26 03:30:35. Each sale row also carries its own cursor. recent_sales is the shortcut when you only want the last 20 across all sizes, and those rows have amount and created_at but no size.

What is the difference between lowest_ask, highest_bid and last_sale?

lowest_ask is the cheapest price a seller will accept right now, highest_bid is the most a buyer has offered, and last_sale is what the most recent trade actually cleared at. On 2026-08-27 the measured product had 1,497 open asks against 262 open bids, and 62 sales in the previous 72 hours. last_sale_change_pct (-0.065789) and last_sale_change_value (-15) describe the move from the sale before it.

What is the StockX API?

StockX API is a ReefAPI endpoint group for live resale prices, market stats and sales history. It returns live JSON through POST requests under /stockx/v1.

Is the StockX API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. StockX calls use the same shared credit balance as every other ReefAPI engine.

Do I need a StockX login or account?

No login to StockX is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the StockX data?

The page example is captured from a live product_detail call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the StockX API use?

StockX actions currently cost 1-3 credits per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call StockX from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call stockx actions with the same key, credit pool and JSON envelope used by normal REST requests.

docs / stockx

StockX

Live resale prices, market stats and sales history.

base /stockx/v18 endpoints
post/stockx/v1/product_detail2 credits

full product by `url` OR `url_key`/`id`/`uuid`: title/brand/model/sku/category/colorway/retail_price/release_date/image + market{lowest_ask,highest_bid,number_of_asks/bids,last_sale,sales_last_72h,last_sale_change_pct/value,avg_price_72h/90d/annual,sales_count_*,price_premium=(last_sale-retail)/retail, volatility=CV-of-recent-sales, ask_service_levels{standard/express_*: count,lowest_ask,processing_fee,delivery}} + per-size variants[]{size,lowest_ask,highest_bid,last_sale}. The market-data moat. `currency` (USD/EUR/GBP/…) + `market` (US/GB/DE/…) optional.

ParameterAllowed / rangeDescription
url_keyoptionalProduct slug from the StockX product URL (stockx.com/<url_key>) — copy it from search results. Internal id/uuid also accepted. Provide url_key OR url.
urloptionalFull StockX product URL — alternative to url_key.
currency = USDoptionalUSD · EUR · GBP · JPY · AUD · CAD · CHF · HKD · KRW · MXN · NZD · SGD · SEK · DKK · NOK · PLN · CNY · TWD · THBCurrency for all prices.
market = USoptionalUS · GB · DE · FR · IT · ES · NL · JP · AU · CA · KR · HK · SG · CH · MX · NZ · SE · DK · NO · PL · CN · TW · THMarketplace region (affects asks/bids and service levels).
Try in playground →
post/stockx/v1/recent_sales1 credit

recent transaction feed by `url`/`url_key`/`id` → sales[]{amount,created_at} (most recent first) + product ref. Best-effort market-history. `currency`/`market` optional.

ParameterAllowed / rangeDescription
url_keyoptionalProduct slug from the StockX product URL (stockx.com/<url_key>) — copy it from search results. Internal id/uuid also accepted. Provide url_key OR url.
urloptionalFull StockX product URL — alternative to url_key.
currency = USDoptionalUSD · EUR · GBP · JPY · AUD · CAD · CHF · HKD · KRW · MXN · NZD · SGD · SEK · DKK · NOK · PLN · CNY · TWD · THBCurrency for all prices.
market = USoptionalUS · GB · DE · FR · IT · ES · NL · JP · AU · CA · KR · HK · SG · CH · MX · NZ · SE · DK · NO · PL · CN · TW · THMarketplace region (affects asks/bids and service levels).
Try in playground →
post/stockx/v1/suggest1 credit

autocomplete query suggestions for `query` (QuerySuggestion text; falls back to search-derived titles if the suggest op drifts).

ParameterAllowed / rangeDescription
queryrequiredPartial search text to complete.
Try in playground →
post/stockx/v1/price_history3 credits

historical price time-series for a product, aggregated from the deep sales feed → series[]{date,count,avg,min,max,last} (oldest→newest) + summary{points,sales_sampled,min,max,avg,first_date,last_date,window_complete}. `window` (30d/90d/180d/365d/all) bounds lookback; `bucket` (day/week/month) sets granularity; optional `size` for per-size history. The #1 resale-trader ask. `currency` optional.

ParameterAllowed / rangeDescription
url_keyoptionalProduct slug from the StockX product URL (stockx.com/<url_key>) — copy it from search results. Internal id/uuid also accepted. Provide url_key OR url.
urloptionalFull StockX product URL — alternative to url_key.
window = 90doptional30d · 90d · 180d · 365d · allHow far back the price series reaches.
bucket = dayoptionalday · week · monthTime-bucket granularity for each series point.
sizeoptionalOptional shoe/apparel size for per-size price history (must match a product variant size, e.g. 10, 10.5, M).
currency = USDoptionalUSD · EUR · GBP · JPY · AUD · CAD · CHF · HKD · KRW · MXN · NZD · SGD · SEK · DKK · NOK · PLN · CNY · TWD · THBCurrency for all prices.
Try in playground →
post/stockx/v1/sales_history1 credit

deep paginated transaction log → sales[]{amount,created_at,cursor} (newest first) + page_info{cursor,has_more,total,limit,returned} + product. Far deeper than recent_sales (StockX exposes the full ledger, e.g. 60k+ sales). Cursor-paginate with `cursor`; optional `size` filters to one variant. `limit` ≤ 50 (StockX page cap). `currency` optional.

ParameterAllowed / rangeDescription
url_keyoptionalProduct slug from the StockX product URL (stockx.com/<url_key>) — copy it from search results. Internal id/uuid also accepted. Provide url_key OR url.
urloptionalFull StockX product URL — alternative to url_key.
cursoroptionalPagination cursor from a previous page_info.cursor (omit for the first/newest page).
limit = 50optional1–50Rows per page (StockX caps at 50).
sizeoptionalOptional size for one variant's transaction log.
currency = USDoptionalUSD · EUR · GBP · JPY · AUD · CAD · CHF · HKD · KRW · MXN · NZD · SGD · SEK · DKK · NOK · PLN · CNY · TWD · THBCurrency for all prices.
Try in playground →
post/stockx/v1/browse1 credit

category/vertical grids + sort + facet filters → results[]{id,url_key,url,title,brand,sku,category,image,lowest_ask,highest_bid,last_sale} + page_info{page,limit,total}. Needs at least one of `category` (sneakers/apparel/electronics/collectibles/accessories), `query`, or a facet filter (`brand`/`gender`). `sort` (most-active/featured/release_date/lowest_ask) optional. Return up to 1000 products in one call with `max_results` (40/page, paged for you — StockX's own ceiling, its grid stops at page 26); `page` picks where the window starts. The catalog-discovery surface.

ParameterAllowed / rangeDescription
categoryoptionalsneakers · apparel · electronics · collectibles · accessoriesStockX vertical to browse (grid of that whole category).
queryoptionalOptional keyword to combine with category/filters.
brandoptionalFilter results to a brand (StockX facet value, e.g. Jordan, Nike, adidas, New Balance, Supreme).
genderoptionalmen · women · youth · infantFilter results by gender facet.
sortoptionalmost-active · featured · release_date · lowest_askResult ordering for browse/trending grids.
max_results = 40optional1–1000How many products to return. MAXIMUM 1000 — the published ceiling, so there is nothing to probe for. StockX serves 40 per page, so asking for more fetches further pages automatically (up to 25 of them). Omit it and you get exactly one page, which is what this action has always done. The ceiling is StockX's own: its grid stops at page 26 (1040 products) and it caps the reported `total` at 1000 however many matches a query really has. Above 1000 the value is clamped, not rejected. Treat it as an upper bound: a narrow query returns everything it has, and a broad one can still come up short because StockX repeats some products across grid pages and duplicates are dropped (measured 2026-08-07: browse sneakers returned a full 1000, the keyword 'nike' returned 709). Whenever fewer rows come back than you asked for, `meta.incomplete` is true.
page = 1optional1–26Page to start from (1-based, 40 results per page). MAXIMUM 26 — StockX's grid ends there. Measured 2026-08-07 on three separate queries: pages 1-26 are all distinct, page 27 and beyond return page 1's products while reporting `page: 1`. A higher value is clamped to 26 rather than looping silently.
currency = USDoptionalUSD · EUR · GBP · JPY · AUD · CAD · CHF · HKD · KRW · MXN · NZD · SGD · SEK · DKK · NOK · PLN · CNY · TWD · THBCurrency for all prices.
market = USoptionalUS · GB · DE · FR · IT · ES · NL · JP · AU · CA · KR · HK · SG · CH · MX · NZ · SE · DK · NO · PL · CN · TW · THMarketplace region (affects asks/bids and service levels).
Try in playground →