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. Sign up free for a key and 100 calls a day to sample it; paid plans add volume and resale depth.

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

Get your free key → · See plans & pricing

Authentication

Create a free account, then mint or rotate your key in the app under account → API key. A free key samples the full surface at 100 calls/day (base tier); paid plans (Pro and up) lift the volume and layer in resale data. 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 Market Intel resale data into every record. That's the only difference.

PlanTierResale in the payload
FreebaseSign up free and mint a key. Same base shape as Pro — heat, size run, retail — capped at a small sampling quota (100 calls/day).
ProbaseThe entry API tier at $29/mo. Heat score, size run, retail, drop dates at 2,500 calls/day. No resale numbers.
ResellerbaseHeat score, size run, retail, drop dates at 10,000 calls/day. 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.",
    "GET|POST|DELETE /api/v1/watch": "Track listings; we watch the price across marketplaces."
  },
  "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 (Pro or 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 }
  ]
}

Price watch

Track a listing and let us watch its price for you. We re-check watched listings continuously, comparing across every marketplace, so a watch fires the moment any source hits your target. Methods follow REST: GET reads, POST creates, DELETE removes.

POST/api/v1/watch

Add a watch. Body: { url, targetPrice? }url is any listing URL from a record; targetPrice (optional) is the USD price you want to be alerted under. Pass { urls: [...] } instead to set up many at once (they share the optional targetPrice); the response then carries { added, failed, results } with a per-URL outcome.

cURL
curl -s -X POST https://sneakermarket.app/api/v1/watch \
  -H "x-api-key: $SNEAKERMARKET_KEY" -H "content-type: application/json" \
  -d '{"url":"https://www.goat.com/...","targetPrice":215}'
cURL · bulk
curl -s -X POST https://sneakermarket.app/api/v1/watch \
  -H "x-api-key: $SNEAKERMARKET_KEY" -H "content-type: application/json" \
  -d '{"urls":["https://www.goat.com/...","https://stockx.com/..."],"targetPrice":215}'
GET/api/v1/watch

List your watches. Each carries the best cross-source price, a reliability score (how much to trust that price), and a status of hit (at/under target), above, watching, or stale.

200 OK
{
  "ok": true,
  "plan": "tycoon",
  "cap": 2000,
  "count": 1,
  "watches": [
    {
      "id": 42,
      "url": "https://www.goat.com/...",
      "sku": "DZ5485612",
      "targetPrice": 215,
      "currentPrice": 210,
      "bestPrice": { "amount": 210, "currency": "USD", "source": "GOAT", "url": "https://www.goat.com/..." },
      "priceRange": { "low": 210, "high": 240, "currency": "USD" },
      "reliability": { "score": 93, "label": "high", "fresh": true, "sources": 2, "authenticated": true, "spreadPct": 0.143 },
      "sources": 2,
      "status": "hit"
    }
  ]
}
DELETE/api/v1/watch/:id

Remove a watch by its id.

cURL
curl -s -X DELETE https://sneakermarket.app/api/v1/watch/42 \
  -H "x-api-key: $SNEAKERMARKET_KEY"
GET/api/v1/watch/events

The update feed: price moves and target hits we've detected on your watches, newest first, plus an unseen count. We monitor each watched listing on an adaptive cadence — checked as often as every 15 minutes while its price is moving, backing off when it sits flat — so updates land fast without wasted polling. POST /api/v1/watch/events/seen clears the unseen count.

200 OK
{
  "ok": true,
  "unseen": 1,
  "events": [
    { "kind": "target_hit", "url": "https://www.goat.com/...", "oldPrice": 240, "newPrice": 210, "pct": -12.5, "createdAt": 1748563200000, "seen": false }
  ]
}
GET/api/catalog

No key required. The full catalog of tracked sneakers with their best cross-source price, as a keyset-paginated feed — built for crawlers, LLMs, and price aggregators. Walk it deterministically with the nextCursor from each page (?cursor=, ?limit= up to 500). Each item links to the canonical /sneaker/:slug page.

cURL
curl -s "https://sneakermarket.app/api/catalog?limit=100"
200 OK
{
  "count": 100,
  "items": [
    {
      "sku": "DZ5485612",
      "title": "Air Jordan 1 Retro High OG Chicago Lost and Found",
      "brand": "Jordan",
      "slug": "air-jordan-1-retro-high-og-chicago-lost-and-found",
      "url": "https://sneakermarket.app/sneaker/air-jordan-1-retro-high-og-chicago-lost-and-found",
      "image": "https://images.stockx.com/...",
      "bestPrice": { "amount": 312, "currency": "USD", "source": "GOAT", "url": "https://www.goat.com/..." },
      "priceRange": { "low": 312, "high": 410, "currency": "USD" },
      "sources": 5,
      "pricedSources": 4,
      "offers": 6,
      "updatedAt": 1748563200000
    }
  ],
  "nextCursor": 812,
  "next": "/api/catalog?cursor=812&limit=100"
}
GET/api/catalog/:slug

No key required. One product with its full offer list across every marketplace we track, cheapest first. The :slug is the slug (or the tail of the url) from a feed item.

cURL
curl -s "https://sneakermarket.app/api/catalog/air-jordan-1-retro-high-og-chicago-lost-and-found"
200 OK
{
  "sku": "DZ5485612",
  "title": "Air Jordan 1 Retro High OG Chicago Lost and Found",
  "brand": "Jordan",
  "slug": "air-jordan-1-retro-high-og-chicago-lost-and-found",
  "url": "https://sneakermarket.app/sneaker/air-jordan-1-retro-high-og-chicago-lost-and-found",
  "bestPrice": { "amount": 312, "currency": "USD", "source": "GOAT", "url": "https://www.goat.com/..." },
  "priceRange": { "low": 312, "high": 410, "currency": "USD" },
  "sources": 5,
  "offers": [
    { "source": "GOAT", "url": "https://www.goat.com/...", "price": 312, "currency": "USD", "shipping": null, "landedPrice": null, "image": "https://...", "lastSeen": 1748563200000 },
    { "source": "StockX", "url": "https://stockx.com/...", "price": 330, "currency": "USD", "shipping": null, "landedPrice": null, "image": "https://...", "lastSeen": 1748560000000 }
  ],
  "updatedAt": 1748563200000
}

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

Every endpoint is rate-limited. Keyed /api/v1 calls count per key, per tier; the keyless public endpoints count per IP. Cross either the hourly or the daily ceiling and you get 429 with Retry-After (seconds). Daily ceilings run ~10× the hourly.

Keyed API /api/v1/* — per key

PlanPer hourPer day
Free20100
Pro1002,500
Reseller1,00010,000
Mogul3,00030,000
Tycoon10,000100,000
Magnate30,000300,000

Public endpoints — per IP, no key

The keyless reads (/api/catalog, /api/catalog/search, /api/catalog/:slug) allow 600/hr (6,000/day) per IP — generous for crawling the feed, since pages are edge-cached and a full walk is only a handful of requests. Signing in or adding a key raises the ceiling; for sustained high volume, use the keyed /api/v1 surface.

Every response — keyed or public — carries the live count:

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

Errors

StatusWhen
401No or invalid key.
404/intel for a SKU we haven't priced yet.
429You've hit your plan's daily call allowance. Body carries retryAfter plus an upgrade hint: { "upgradeTo": { "plan": "pro", "price": "$29/mo", "checkout": "…" } }. Every plan includes the API, so higher tiers just lift the ceiling.

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.