Skip to Content
Token LaunchpadPublic API

Public API

A read-only, versioned API for programs: every live token with its pair and status, one token by address, the counts, and the Early Creators race standings. No key, no account, no rate you can buy.

https://www.winr.games/api/v1/tokens https://www.winr.games/api/v1/tokens/{address} https://www.winr.games/api/v1/stats https://www.winr.games/api/v1/campaigns/early-creators

The same four operations are described in an OpenAPI document at the gateway’s /api/docs path, if you would rather generate a client (operation ids launchpadV1Tokens, launchpadV1Token, launchpadV1Stats, launchpadV1EarlyCreators).

The API makes no chain reads. Every field is served from the platform’s database behind a cache. That is why it carries identity and status, and not price, market cap, liquidity, volume or holders: each of those needs a chain call or a per-token fan-out, and a public endpoint’s cost would be set by whoever polls it hardest.


Quick Start

curl -s https://www.winr.games/api/v1/tokens | jq '.data.tokens[0]'
{ "address": "0xa1bbdf595c7f9df47f2ff9e560569c8055dbce27", "name": "Paper Moonboy", "ticker": "PMB", "pairAddress": "0x…", "pairFeeBps": 10000, "quoteTokenAddress": "0x0bd7d308f8e1639fab988df18a8011f41eacad73", "status": "LIVE", "launchedAt": "2026-09-09T18:44:02.000Z", "graduatedAt": null, "gameSlug": "paper-moonboy", "gameUrl": "https://just.bet/game/paper-moonboy", "pageUrl": "https://www.winr.games/token/0xa1bbdf595c7f9df47f2ff9e560569c8055dbce27" }

Envelope

Every response is one of two shapes, told apart by which key is present:

{ "data": { } } // 200 { "error": { "statusCode": 503, "type": "FeedUnavailable", "message": "…" } } // 400 / 404 / 429 / 503

An empty list is a success ("tokens": [], "count": 0). A 503 means the read failed, and there is never a partial list: you will not receive a short array that looks complete. Retry, and do not treat a 503 as “every token was delisted”.


GET /api/v1/tokens

Every launched token whose game is published and which the operator has not blocked, newest first, tie-broken by address so an unchanged list never reshuffles between polls.

{ "data": { "tokens": [ ], "count": 43, "chainId": 4663, "generatedAt": "2026-09-15T12:04:15.407Z" } }
FieldTypeMeaning
addressstringToken contract. Full 0x form, lowercase.
namestringDisplay name.
tickerstringSymbol, without a leading $.
pairAddressstringThe Uniswap V3 pool. Full 0x form, lowercase.
pairFeeBpsintegerPool fee tier in basis points. 10000 is the 1% tier every launch uses today.
quoteTokenAddressstringThe other side of the pair: WETH on this chain.
statusenumLIVE, GRADUATED or INACTIVE. See below.
launchedAtstringLaunch block timestamp, ISO-8601 UTC.
graduatedAtstring or nullGraduation timestamp, ISO-8601 UTC, or null.
gameSlugstringThe just.bet game this token is.
gameUrlstringWhere the game is played.
pageUrlstringThe token’s page on winr.games.

Status

ValueMeaning
LIVELaunched and trading. Has not reached the graduation threshold.
GRADUATEDReached 4.2 ETH of real TWAP pool depth. One-way.
INACTIVEGraduated, then no trade for 30 days. Returns to GRADUATED on the next trade.

Graduating is not a status. The Explore page’s Graduating tab is a view over LIVE tokens whose depth has passed half the threshold. Computing it needs live pool depth, which this API does not carry. Treat an unknown value as “not tradeable” rather than failing.

Which tokens appear

A token is listed when its game is published and an operator has not blocked it. Two consequences:

  • Test tokens are excluded. Two tokens exist to test the launchpad itself. They have real pools and appear on the Explore page. They are not in this API, and they should not be traded.
  • Unclaimed drafts are excluded. A token whose game has not yet been claimed and published is on chain and tradeable, but is not listed until it is.

The list is therefore a subset of the Explore page. That is the whole difference.

GET /api/v1/tokens/{address}

The same token object for one address, in any case. It is answered out of the cached list, so it is exactly as fresh as the list and costs nothing beyond it.

  • 200 with the token.
  • 400 if address is not 0x followed by 40 hex characters.
  • 404 if no listed token has this address: unknown, a test token, or an unclaimed draft.

GET /api/v1/stats

{ "data": { "tokens": { "total": 43, "live": 43, "graduated": 0, "inactive": 0 }, "chainId": 4663, "generatedAt": "2026-09-15T12:04:15.407Z" } }

Counts from the same cached list.

GET /api/v1/campaigns/early-creators

The Early Creators race: window, prize ladder and standings, ranked by indexed swap volume on each token’s pool inside the window.

{ "data": { "campaign": "early-creators", "phase": "RUNNING", // BEFORE | RUNNING | ENDED "windowStartUtc": "2026-09-12T17:00:00.000Z", "windowEndUtc": "2026-09-19T17:00:00.000Z", "final": false, // the window has closed "frozen": false, // the standings are the recorded result "prizePoolUsd": 1000, "prizesUsd": [300, 200, 150, 100, 75, 50, 40, 35, 30, 20], "volumeDefinition": "…", "entrantCount": 40, "rankedCount": 12, "indexedThroughUtc": "2026-09-15T12:03:58.000Z", "standings": [ { "rank": 1, // null for an entrant with no trade in the window "tokenAddress": "0x…", "ticker": "PMB", "tokenName": "Paper Moonboy", "gameSlug": "paper-moonboy", "volumeEth": "1.234567", // fixed 6 decimal places, as a string "tradeCount": 12, "prizeUsd": 300, "excluded": false } ], "generatedAt": "2026-09-15T12:04:00.000Z" } }

final and frozen are different claims. final means the window has shut. frozen means the result has been recorded. Between the two, the standings are still a live query and may move. An entrant with no trade is unranked, not last.


Caching and Freshness

Use generatedAt in the body to tell how fresh a response is, not the headers.

The application caches each body for 60 seconds (30 for the race), and a CDN edge in front of it caches the same body for the time left on that clock. Both hostnames reach the same edge. On an edge hit you receive a body built earlier together with the headers frozen at that moment, so Age, X-Origin-Cache and X-RateLimit-Remaining may describe an earlier request. generatedAt travels inside the body and cannot be replayed to mean something else.

Plan for a worst case of about two minutes of staleness. A newly launched token is normally visible within a minute and always within two. Polling faster does not change this; most of those requests are answered by an edge and never reach the application.

Rate Limit

30 requests per minute per caller, and 600 per minute for the API as a whole, across all four endpoints. The intended use is one request an hour.

Over either limit returns 429 with X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Scope (which signal identified you) and Retry-After in seconds. Honour Retry-After.

Stability

The path is versioned and the shape is a promise. Fields may be added; none will be renamed, retyped or removed. status may gain a value. A breaking change would be published under /api/v2, and /v1 would keep working.

Example: Watch for New Listings

import time, requests URL = "https://www.winr.games/api/v1/tokens" seen = set() while True: r = requests.get(URL, timeout=20) if r.status_code == 429: time.sleep(int(r.headers.get("Retry-After", 60))); continue if r.status_code != 200: time.sleep(300); continue # a failed read; the last list still stands for t in r.json()["data"]["tokens"]: if t["address"] not in seen: seen.add(t["address"]) print(t["ticker"], t["address"], t["pairAddress"], t["status"], t["gameUrl"]) time.sleep(3600)
Last updated on
The AI casino system© 2026 WINR Protocol18+ · Gamble responsibly