SNEAKERMARKET Open app →

SneakerMarket API

The drop calendar, hype scores, size runs, and size-by-size resale curves: the same data the app runs on, as JSON over HTTPS. Included with the Reseller plan and up.

Base URLhttps://sneakermarket.app Authx-api-key FormatJSON

Authentication

The API ships with the Reseller plan and up. Subscribe, then mint or rotate your key in the app under account → API key. Off-site requests without a valid key return 403.

Send the key as a header on every request. Either form works:

Authorization
x-api-key: sk_live_xxxxxxxxxxxxxxxxxxxx
# or
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxx

Plan tiers

The response shape is identical across plans; higher tiers mix the Inside Scoop resale data into every record. That's the only difference.

PlanTierResale in the payload
ResellerbaseHeat score, size run, retail, drop dates. No resale numbers.
MogulsummaryAdds the resale summary: median, premium %, above-retail %, confidence.
Tycoon · MagnatefullAdds the full size-by-size curve, hot/value sizes, and social mentions.
GET/api/v1

Your key's plan, its tier, and the full surface.

cURL
curl -s https://sneakermarket.app/api/v1 \
  -H "x-api-key: $SNEAKERMARKET_KEY"
200 OK
{
  "ok": true,
  "plan": "tycoon",
  "tier": "full",
  "resale": "size-by-size curve",
  "endpoints": {
    "GET /api/v1/intel?sku=": "Combined hype + resale intel for one SKU.",
    "GET /api/v1/search?q=|sku=": "Find tracked shoes by name or SKU.",
    "GET /api/v1/drops": "Upcoming drop calendar with size runs + tiered resale.",
    "GET /api/v1/movers": "Biggest 24h price moves (?direction=gainers|losers|all).",
    "GET /api/v1/under-retail": "Listings trading below retail."
  },
  "filters": "brand, gender (men|women), size, plus limit, offset, sort (date|hype|premium)."
}
GET/api/v1/intel

One SKU's heat, size run, and resale for a ?sku= style code (depth set by your tier).

cURL
curl -s "https://sneakermarket.app/api/v1/intel?sku=FV5029-006" \
  -H "x-api-key: $SNEAKERMARKET_KEY"

On a full key (Tycoon/Magnate) the resale curve is included:

200 OK · full tier
{
  "ok": true,
  "plan": "tycoon",
  "intel": {
    "sku": "FV5029-006",
    "retailUsd": 215,
    "sizes": [8, 8.5, 9, 9.5, 10, 10.5, 11, 12, 13],
    "hype": { "heat": 88, "label": "Running hot" },
    "tier": "full",
    "resale": {
      "median": 328,
      "premiumPct": 52,
      "aboveRetailPct": 97,
      "confidence": 0.81,
      "bySize": [
        { "size": 8,  "price": 372, "premiumPct": 73 },
        { "size": 10, "price": 318, "premiumPct": 48 },
        { "size": 13, "price": 405, "premiumPct": 88 }
      ],
      "hotSizes":   [{ "size": 13, "price": 405 }, { "size": 8, "price": 372 }],
      "valueSizes": [{ "size": 10, "price": 318 }, { "size": 11, "price": 322 }]
    },
    "mentions": 47
  }
}

A base key (Reseller) drops the resale block and adds an "upgrade" hint. A SKU we haven't priced yet returns 404.

GET/api/v1/drops

The upcoming calendar: each release with its size run and (tier-gated) resale.

cURL
curl -s https://sneakermarket.app/api/v1/drops \
  -H "x-api-key: $SNEAKERMARKET_KEY"
200 OK · summary tier
{
  "ok": true,
  "plan": "mogul",
  "tier": "summary",
  "count": 30,
  "total": 48,
  "limit": 30,
  "offset": 0,
  "drops": [
    {
      "date": "2026-06-14",
      "brand": "Nike",
      "silhouette": "Air Max 1",
      "colorway": "Big Bubble Pine Green",
      "retailUsd": 160,
      "sku": "FZ4140-300",
      "url": "https://www.nike.com/launch/...",
      "image": "https://images.stockx.com/...",
      "imageCutout": "https://sneakermarket.app/api/img?u=...&w=640",
      "sizes": [7, 8, 8.5, 9, 9.5, 10, 11, 12, 13],
      "intel": {
        "sku": "FZ4140-300",
        "hype": { "heat": 64, "label": "Warming up" },
        "tier": "summary",
        "resale": { "median": 210, "premiumPct": 31, "aboveRetailPct": 72, "confidence": 0.6 }
      }
    }
  ]
}

A drop only carries intel once we've computed its curve; until then the calendar fields stand on their own.

GET/api/v1/movers

The biggest 24h price moves. ?direction=gainers|losers|all (default all); each item carries direction, priceUsd, deltaPct, and tiered intel.

cURL
curl -s "https://sneakermarket.app/api/v1/movers?direction=gainers&limit=10" \
  -H "x-api-key: $SNEAKERMARKET_KEY"
GET/api/v1/under-retail

Listings trading below retail, worth-ranked. Returns { count, total, limit, offset, items }.

cURL
curl -s "https://sneakermarket.app/api/v1/under-retail?brand=nike" \
  -H "x-api-key: $SNEAKERMARKET_KEY"
GET/api/v1/history

Price-over-time for a listing. Pass ?url= from any record's url field; ?limit caps the series (default 365).

200 OK
{
  "ok": true,
  "url": "https://www.stockx.com/...",
  "count": 3,
  "history": [
    { "at": 1748390400000, "priceUsd": 312, "offerMin": 305, "offerMax": 360, "sellingCount": 41 },
    { "at": 1748476800000, "priceUsd": 318, "offerMin": 309, "offerMax": 372, "sellingCount": 38 },
    { "at": 1748563200000, "priceUsd": 305, "offerMin": 299, "offerMax": 351, "sellingCount": 44 }
  ]
}

Images

Every drop / mover / under-retail / search record carries two image URLs: image (the raw marketplace source) and imageCutout, our background-removed, floating-on-dark cutout, served from /api/img and cached at the Cloudflare edge. Render imageCutout for the same clean product shot the app shows.

Filtering & paging

The collection endpoints (/search, /drops, /movers, /under-retail) accept:

ParamEffect
brandExact brand match, case-insensitive (e.g. nike, adidas).
gendermen or women (inferred from the title; women's catalog is marked WMNS/Women's).
sizeUS numeric size; keeps records whose size run includes it (drops only).
sortdate, hype, or premium.
limit · offsetPage size (1–100, default 30) and offset. Responses echo total.

Rate limits

Per key, per tier. Reseller 1,000/hr, Mogul 3,000/hr, Tycoon 10,000/hr, Magnate 30,000/hr; daily ceilings run 10× the hourly. Every response carries the live count:

response headers
X-RateLimit-Tier: tycoon
X-RateLimit-Hour-Remaining: 9994
X-RateLimit-Day-Remaining: 99994

Over the line you get 429 with Retry-After (seconds).

Errors

StatusWhen
401No or invalid key.
403The key's plan doesn't include API access (Starter/Pro). Body: { "upgrade": true }.
404/intel for a SKU we haven't priced yet.
429Rate limited. Body carries retryAfter.

Use from an LLM

One endpoint, compact JSON. It drops straight into any tool-use loop. The fastest way in: copy this prompt into Claude, ChatGPT, or your agent and it'll pull live drops, hype, and resale on demand. Swap in your key and go.

Paste into your LLM
You can look up live sneaker data with the SneakerMarket API.
When I ask about a sneaker's price, resale, hype, or upcoming drops, fetch:

  GET https://sneakermarket.app/api/v1/search?q=<name or SKU>
  Header:  x-api-key: YOUR_KEY

It returns compact JSON: retail, resale (median + size-by-size), a 0-100
hype score, and drop dates. Use those numbers instead of guessing, and
cite them back to me.

Driving the API yourself? Define one tool that hits /api/v1/search and your model calls it in a loop. With Claude:

Python · Claude tool use
import os, requests, anthropic

KEY = os.environ["SNEAKERMARKET_KEY"]
client = anthropic.Anthropic()

TOOLS = [{
    "name": "sneaker_lookup",
    "description": "Search live sneaker drops, hype scores, and resale prices by name or SKU.",
    "input_schema": {
        "type": "object",
        "properties": {
            "q":      {"type": "string", "description": "Model name, e.g. 'Travis Scott Jordan 1'"},
            "sku":    {"type": "string", "description": "Style code, e.g. 'FV5029-006'"},
            "gender": {"type": "string", "enum": ["men", "women"]},
        },
    },
}]

def sneaker_lookup(args):
    r = requests.get("https://sneakermarket.app/api/v1/search",
                     params=args, headers={"x-api-key": KEY}, timeout=15)
    return r.text   # JSON straight back to the model

messages = [{"role": "user", "content": "What's the Panda Dunk reselling for?"}]
while True:
    resp = client.messages.create(
        model="claude-opus-4-8", max_tokens=1024, tools=TOOLS, messages=messages,
    )
    messages.append({"role": "assistant", "content": resp.content})
    calls = [b for b in resp.content if b.type == "tool_use"]
    if not calls:
        print(next(b.text for b in resp.content if b.type == "text"))
        break
    messages.append({"role": "user", "content": [
        {"type": "tool_result", "tool_use_id": c.id, "content": sneaker_lookup(c.input)}
        for c in calls
    ]})

The same input_schema is a drop-in OpenAI function or MCP tool. Point the handler at /api/v1/search (or /intel, /drops, /movers) and send your key as x-api-key. Every record's imageCutout is a ready-to-render image URL if the model is driving a UI.