StockX API

Read the StockX resale market, size by size

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

S
/stockx/v1

8 active endpoints, on 1, 2 and 3 credit tiers.

  • POST/stockx/v1/product_detail
  • POST/stockx/v1/search
  • POST/stockx/v1/recent_sales
  • POST/stockx/v1/suggest
  • POST/stockx/v1/price_history
  • POST/stockx/v1/sales_history
  • POST/stockx/v1/browse
  • +1 more

What StockX endpoints does ReefAPI ship?

8 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

8 endpoints

product_detail

2 cr

full product by url OR url_key/id/uuid.

required
optional
url, url_key, id, uuid, currency, market

search

1 cr

product search → results[]{id,url_key,url,title,brand,sku,category,image,lowest_ask,highest_b…

required
query
optional
max_results, page, currency, market, brand, gender, category, sort

recent_sales

1 cr

recent transaction feed by url/url_key/id → sales[]{amount,created_at} (most recent first) +…

required
optional
url, url_key, id, uuid, currency, market

suggest

1 cr

autocomplete query suggestions for query (QuerySuggestion text.

required
query
optional

price_history

3 cr

historical price time-series for a product, aggregated from the deep sales feed → series[]{da…

required
optional
url, url_key, id, uuid, window, bucket, size, currency

sales_history

1 cr

deep paginated transaction log → sales[]{amount,created_at,cursor} (newest first) + page_info…

required
optional
url, url_key, id, uuid, cursor, limit, size, currency

browse

1 cr

category/vertical grids + sort + facet filters → results[]{id,url_key,url,title,brand,sku,cat…

required
optional
category, query, brand, gender, sort, max_results, page, currency, market

trending

1 cr

movers / most-active products (global or within a category) → results[] (same card shape as b…

required
optional
category, brand, gender, sort, max_results, page, currency, market

Every parameter, every allowed value →

StockX API

3 of 8 endpoints, ready to run

View docs ↗

One product and its whole market: retail price, release date, the style code, the ask and bid per size, and ninety-day and annual sale averages with their counts.

2 credits1 required · 2 optional
POST/stockx/v1/product_detail
idle
// Press "Try it" and this pane shows exactly what the
// live site returned this second — including an empty
// result, if that is the truth. No key, no account.

How the StockX API works

StockX is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 185 engines.

02
Call
POST /stockx/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
1 or 2 or 3 credits per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

Work out whether a size is actually liquid

A single resale price is close to meaningless — the ask on a size nobody wants and the ask on the size everyone wants are the same field. Two calls tell you which is which.

01search
POST/stockx/v1/search
{"query": "jordan 1", "max_results": 20}

One credit per 40 rows. Take results[].url_key.

02product_detail
POST/stockx/v1/product_detail
{"url_key": "...", "currency": "USD"}

Two credits flat. variants[] is one row per size with its own ask, bid and last sale; market.number_of_asks and number_of_bids give you the depth on both sides.

03sales_history
POST/stockx/v1/sales_history
{"url_key": "...", "limit": 50}

One credit, cursor-paged, and the response reports the total number of sales on record.

Three credits for a product with a per-size order book and a real trade history — and this is the fastest engine in this batch, most calls landing under a second and a half.

request
curl -X POST https://api.reefapi.com/stockx/v1/product_detail \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"url_key":"air-jordan-4-retro-bred-reimagined"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "stockx",
    "endpoint": "product_detail",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

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.

Three ids, and why a bid can be higher than an ask

Measured on 2026-08-27 across sneakers, watches and trading cards, in USD/US and EUR/DE. Three of these lines go against us.

Three ids, and only one opens the door

Every row carries id (a UUID), url_key (the slug) and sku, which is the manufacturer style code — DZ5485-612 for the shoe in the panel above, echoed as style_id on detail. product_detail takes the url_key. Passing the style code instead returned NOT_FOUND. So the style code is the id you MATCH against your own catalogue; the url_key is the id you CALL with.

The style code is empty outside sneakers

Against us, though it is really the source's doing: sku was filled on 20 of 20 sneaker rows, 2 of 14 watch rows and 0 of 20 trading-card rows. Streetwear and collectibles have no manufacturer style code to carry. If your join key is the style code, this engine joins sneakers and little else.

The product-level ask and bid are not a spread

This is the field everyone reads wrongly, so it is worth being exact. market.lowest_ask is the cheapest ask ACROSS ALL SIZES and market.highest_bid is the dearest bid across all sizes — so a product can, correctly, report a highest_bid of 286 against a lowest_ask of 154. They are two different sizes. Only variants[] gives a real per-size spread, and there the ask is above the bid as it should be: size 3.5 asked 188 and bid 115 on the same run.

retail_price and market price are different things, and only one converts

Against us. retail_price is what the item cost new at release — 180 for the shoe above. Reading the same product in EUR on the German market changed every market number (lowest ask 154 became 103, per-size asks changed entirely) but left retail_price at 180. So retail_price is a USD figure whatever currency you asked for. Compute premiums on the market fields, not against retail.

The market really is regional

US and DE returned different asks, bids and last sales for the same product on the same minute — not a converted number but a different order book. The variant count stayed the same 26 sizes on both, so the size grid is global and the prices are not.

price_history samples the last 400 sales, not the window you asked for

Against us, and worth reading the response for. Asking a 365-day window bucketed by month returned ONE point, with summary.sales_sampled 400 and window_complete false — because on a shoe selling that fast, 400 sales is a few weeks. A 90-day window bucketed by week returned five points from the same product. The endpoint tells you it is incomplete; it costs 3 credits, the dearest here, so check window_complete before you pay for a long one.

The parameter enums are strict, and say what is allowed

In our favour for once. window accepts 30d, 90d, 180d, 365d and all; bucket accepts day, week and month. A wrong value came back as INVALID_PARAM with the permitted list in the error, not as a silent fallback to a default. That is the behaviour you want from a paid endpoint.

Search stops at a thousand

meta.total reported exactly 1000 for every broad query and last_page 26 at 40 rows a page. Page 7 and page 26 shared zero rows, so those thousand are real and distinct — the cap is on how deep the feed goes, not on what it returns. A narrow query reports its true total instead: a watch search returned 14 with incomplete true.

Cost and speed

search, browse and trending are 1 credit per 40 rows, so 200 rows is 5. product_detail is flat 2, price_history flat 3, and recent_sales, sales_history and suggest flat 1. Most calls returned in 400 to 1,500 milliseconds; a 200-row search took about 1.2 seconds. Nothing else in this batch is close.

What people build with StockX

The jobs this data is most often used for.

8

endpoints

1/2/3

credits per call

01

Resale-price tools call product_detail to track lowest ask, highest bid and last sale for a SKU.

02

Sneaker apps use price_history and recent_sales to chart a product's market value over time.

03

Resellers use trending and browse to spot rising products before they spike.

What StockX data costs

The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 185 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/stockx/v1/product_detail \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"url_key":"air-jordan-4-retro-bred-reimagined"}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/stockx/v1/product_detail",
    headers={"x-api-key": REEF_KEY},
    json={
  "url_key": "air-jordan-4-retro-bred-reimagined"
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up StockX.

Get a free key →
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.

37 E-commerce & Marketplaces APIs on the same key

One key, one credit pool, one response envelope. If you are pulling StockX, you are one call away from the rest of the category — no second contract, no second integration.

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 184 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-27.