Wiki Developer Public Leaderboard API

Public Leaderboard API

Last updated Apr 17, 2026

Public Leaderboard API

Read-only JSON access to TetroWars leaderboards. Free to use for community tools, Discord bots, stream overlays, or stat trackers.

  • Base URL: https://tetrowars.com/api/v1
  • Format: JSON (UTF-8)
  • Auth: None required
  • CORS: Access-Control-Allow-Origin: * (cross-origin friendly)
  • Rate Limit: 60 requests/minute per IP
  • Cache: Responses are cacheable for 60s (Cache-Control: public, max-age=60)

All responses follow the shape:

{ "ok": true, "data": { ... } }

or on error:

{ "ok": false, "error": "message" }

Each row includes a user_id so you can drill into the player's full profile via Public Users API without a search step.


GET /leaderboard

Returns a paginated slice of a leaderboard.

Query Parameters

Param Type Default Values / Notes
tab string ranked ranked, singleplayer, multiplayer, clans
mode string overall See "Modes" below
period string all Only used by ranked: all, season, month, week, day
page int 1 1-indexed
limit int 50 Max 100

Modes per tab

  • ranked: overall, 1v1, br, duel, team
  • singleplayer: marathon, sprint, blitz, cheese, survival
  • multiplayer: wins, games, tetrises, t_spins, best_combo
  • clans: elo, members, wars

Example

curl "https://tetrowars.com/api/v1/leaderboard?tab=ranked&mode=overall&period=all&limit=10"

Response

{
  "ok": true,
  "data": {
    "rows": [
      {
        "user_id": 206,
        "username": "rivernaught",
        "avatar_url": "/uploads/avatars/avatar_206_1775528757.webp",
        "glicko_rating": 4036,
        "games_won": 183,
        "games_played": 537,
        "is_ranked": 1,
        "placement_games": 10,
        "clan_tag": "RIVER"
      }
    ],
    "total": 343,
    "page": 1,
    "limit": 10,
    "pages": 35,
    "my_rank": null,
    "tab": "ranked",
    "mode": "overall",
    "period": "all"
  }
}

Row fields vary by tab. Every row has user_id and username, plus a ranking value (rating / score / wins / time).

Clan leaderboard rows return tag instead of user_id.


Errors

HTTP Meaning
400 Bad request (missing/invalid params)
429 Rate limit exceeded - slow down
500 Server error - report via Discord

Usage Tips

  • Cache aggressively. With 60s cache headers, a simple HTTP cache gets you plenty of freshness without hammering the server.
  • Paginate deep queries. limit caps at 100. Walk pages instead of asking for huge windows.
  • Drill into players with user_id. Pair with GET /users/{id} - no intermediate search needed.
  • Respect the rate limit. Sustained abuse will get your IP blocked. If you need higher quotas for a legitimate tool, reach out on the TetroWars Discord.

Example: Clickable leaderboard in vanilla JS

<div id="lb"></div>
<script>
fetch('https://tetrowars.com/api/v1/leaderboard?tab=ranked&limit=10')
  .then(r => r.json())
  .then(({ data }) => {
    document.getElementById('lb').innerHTML = data.rows
      .map((r, i) => `<div>
        #${i + 1}
        <a href="/profile/${r.username}">${r.username}</a>
        - ${r.glicko_rating}
        <button onclick="loadStats(${r.user_id})">Details</button>
      </div>`)
      .join('');
  });

async function loadStats(id) {
  const res = await fetch(`https://tetrowars.com/api/v1/users/${id}`);
  const { data } = await res.json();
  console.log(data);
}
</script>

Questions or found a bug? Ping us on Discord in #dev.

developer