about / api

REST API

The API may change dramatically, so there are no guarantees about backwards compatibility. All responses are JSON and every endpoint is a public GET request.

ENDPOINTS

GET /api/leaderboard
Fetch the top scores/times for a game mode. One entry per player by default (each player's personal best), or every submitted score when duplicates=true.
NameTypeDefaultDescription
modeinteger2Mode id (see the mode table below). Non-integer values fall back to the default; unknown/out-of-range ids return an empty scores array.
subModeinteger(none)Filters to a sub-mode. Only meaningful for Four Wide (values 0–3 = 3/4/5/6 Residual; scores submitted before sub-modes existed count as 0). Omit the parameter to get all sub-modes combined.
duplicatesbooleanfalseOnly the literal string true enables it. When false, results are aggregated to one best row per player; when true, every score is returned (a player may appear multiple times).
amountinteger100Number of rows to return. Hard-capped at 100.
Response
{
  "scores": [
    {
      "username": "Alice",
      "time": 42317,
      "pieces": 100,
      "pps": 2.36,
      "date": 1718000000000,
      "replay": 8421
    }
  ]
}
A score field is added to each entry for score-based modes (PC Mode, The Almost Death, Four Wide, Hyper, T-Spin Rush, T-Spin Puzzle, All-Spin Puzzle). Time-only modes (40 Lines, Digger, Survival) omit it.
Modes
idNameSlug(s)Has score
1PC Modepc-mode, pcyes
240 Lines40-lines, 40lno
3Diggerdiggerno
4Survivalsurvivalno
5The Almost Deaththe-almost-death, tadyes
6Four Widefour-wide, 4wyes
7Hyperhyperyes
8T-Spin Rusht-spin-rushyes
9T-Spin Puzzlet-spin-puzzleyes
10All-Spin Puzzleall-spin-puzzleyes
The first slug listed is the canonical one. Each slug can also be used as a path parameter (see below).
GET /api/leaderboard/:modeSlug
Same as /api/leaderboard, but the mode is chosen by a slug in the path instead of the mode query param. An unknown slug falls back to the mode query param (default 2).
NameTypeDefaultDescription
:modeSlugpathstringA mode slug from the table above (e.g. 40-lines).
subModeinteger(none)Same as above.
duplicatesbooleanfalseSame as above.
amountinteger100Same as above. Hard-capped at 100.
Response
Identical shape to /api/leaderboard: { "scores": [ ... ] }.
GET /api/profile
Player profile: stats, achievements, personal best scores and recent games. Returns an empty body if player is missing or unknown.
NameTypeDefaultDescription
playerstringRequired. The player's username.
gamesinteger10Number of recent games to include. Hard-capped at 100.
Response
Top-level fields: achievements, best-scores (keyed by mode name), positions, recent-scores (array), stats, submitted-scores (score counts keyed by mode id, 0 = total).
GET /api/replay
Retrieve a recorded game replay by its numeric id. Returns an empty body if the id is missing, not a number, or no matching replay exists.
NameTypeDefaultDescription
idintegerRequired. The replay id.
Response
{
  "id": 8421,
  "username": "Alice",
  "mode": 2,
  "time": 42317,
  "pieces": 100,
  "pps": 2.36,
  "date": 1718000000000,
  "replay": "...",
  "serverReplay": "..."
}
GET /api/stats
Global server statistics: current world records, the number of submitted scores per mode, and player activity. Takes no parameters.
Response
Top-level fields: records (array of world records, each with username, mode, score or time, date, replay), submitted-scores (score counts keyed by mode id, 0 = total), and players (activity counters: online now, and unique players today, week, month, and allTime).
/replay/data and /profile/data are legacy aliases of /api/replay and /api/profile respectively.