Skip to content

Scoreboards ​

Reading boards. Every read is a GET, board data is public (no player auth needed beyond your game credentials), and responses are edge-cached for ~30 seconds.

The global leaderboard ​

GET /leaderboard?sort={score|streak}&limit={n}
bash
curl "https://api.cheddaboards.com/leaderboard?sort=score&limit=100" \
  -H "X-API-Key: cb_my-game_xxxxxxxxx" \
  -H "X-Game-ID: my-game"
json
{
  "ok": true,
  "data": {
    "leaderboard": [
      { "rank": 1, "nickname": "Chedz", "score": 5148898, "streak": 4, "authType": "external" },
      { "rank": 2, "nickname": "Player_1504", "score": 151732, "streak": 7, "authType": "external" }
    ],
    "total": 2
  }
}

sort is score (default) or streak. Each entry carries rank, nickname, score, streak, and authType (how the player signed in — external for anonymous / API-key play). This reads the game's global fan-out board; for a specific board use the endpoint below.

A specific board ​

GET /games/{gameId}/scoreboards/{scoreboardId}?limit={n}

Works for any board — all-time, a timed board, or a targeted category board — they read identically:

bash
curl "https://api.cheddaboards.com/games/my-game/scoreboards/weekly?limit=100" \
  -H "X-API-Key: cb_my-game_xxxxxxxxx" \
  -H "X-Game-ID: my-game"
json
{
  "ok": true,
  "data": {
    "scoreboardId": "weekly",
    "config": { "name": "weekly", "description": "", "period": "weekly",
                "sortBy": "score", "lastReset": 1789948800000000000 },
    "entries": [
      { "rank": 1, "nickname": "Player_2519", "score": 500, "streak": 0,
        "authType": "external", "submittedAt": 1790157891387042954 }
    ],
    "totalEntries": 1
  }
}

config describes the board (period is its reset cadence, lastReset when the current period began), entries are ranked, and totalEntries is the board's full size, handy when you've asked for fewer with limit. Each entry adds submittedAt to the fields above: when that best was set, in nanoseconds. Field-by-field, including the archive variant: Timed leaderboards → the config dictionary.

Reading straight from the chain ​

The same board read is served directly by the canister, no proxy involved and no API key needed:

bash
curl "https://fdvph-sqaaa-aaaap-qqc4a-cai.raw.icp0.io/games/my-game/scoreboards/weekly?limit=100"

Byte-identical JSON, browser-safe (Access-Control-Allow-Origin: *). Use it for read-only surfaces — kiosks, overlays, companion pages — that should keep working regardless of the API layer. See the quick start.

List a game's boards ​

GET /games/{gameId}/scoreboards

Returns every board configured for the game — fan-out and targeted, timed and all-time — with each board's config. Use it to discover board IDs rather than hard-coding them.

Archives ​

When a timed board resets, its final standings are archived. Read them back:

EndpointReturns
GET /games/{gameId}/scoreboards/{id}/archivesList of archived periods for a board (add ?after=&before= nanosecond timestamps to filter a date range)
GET /games/{gameId}/scoreboards/{id}/archives/latestThe most recent archive
GET /archives/{archiveId}One specific archive (gameId:scoreboardId:timestamp)
GET /games/{gameId}/archives/statsArchive statistics for the game

Full treatment of resets, retention, and archive display: Timed leaderboards.

Caching & polling ​

Board reads are edge-cached for about 30 seconds, so polling faster than that returns the same data. If you refresh a board on screen, a 30-second interval plus a refresh after the player's own submit is the pattern the official SDKs use — it keeps you well clear of any rate concern and off the proxy for reads that haven't changed.

Notes ​

  • A 404 on a board lookup is normal — it means the board isn't configured for the game.
  • limit caps how many entries come back; omit it for the default. Through the API the maximum is 1,000; the direct canister read isn't capped.
  • Board and game IDs in the path must be 1–64 chars of [A-Za-z0-9_-] or the request is rejected with a 400.

See also: Scores · Category boards · Timed leaderboards · REST quick start

Can't be taken away. Open source backend and SDKs.