Skip to content

Leaderboard Tournament

This recipe builds a weekly tournament with the first-party leaderboards module. Players submit scores during the week. When the week ends, the module grants rewards by rank and clears the board.

  • A board that collects scores for a week.
  • A live standings screen in the game client.
  • Rewards by final rank: for example rank 1 gets 500 gems, ranks 2–10 get 100 gems, ranks 11–100 get 25 gems.
  1. Open Modules in the dashboard at https://app.rudder.build/ and install leaderboards. Its dependencies (reward, inventory, items) are installed with it.
  2. Open Leaderboards → Boards and create a board:
    • Name — for example Weekly Arena. The slug (weekly_arena) is filled from the name; the game client submits scores to it.
    • Reset periodweekly. Boards reset at 00:00 UTC on Mondays (daily resets every day, monthly on the first day of the month).
    • Orderdesc when the highest score wins, asc for time-attack boards where the lowest wins.
    • Max entries — optional cap on how many entries top returns.
    • Rewards — rank ranges with a reward each: 1–1, 2–10, 11–100. The dashboard rejects overlapping ranges and ranks below 1.
  3. Create the board in staging first, test it there, then promote to prod.

With leaderboards installed, generate a typed client (see Generated module clients):

Terminal window
rudder client generate --lang ts --out src/rudder.modules.ts
rudder client generate --lang csharp --out Assets/Rudder/RudderModules.g.cs

Call submit when a match ends. The module keeps each player’s best score: the highest on desc boards, the lowest on asc boards, so players can submit as often as they like. The result is the stored best score.

import { modules } from './rudder.modules';
const m = modules(client);
const { score: best } = await m.leaderboards.submit({ slug: 'weekly_arena', score: finalScore });

submit fails with board_not_found (HTTP 422, RudderModuleError / RudderModuleException) for an unknown slug. An empty slug or a score that is not a JSON number is rejected by argument validation with invalid_parameters. Scores can be fractional, for example times on asc boards.

top returns { entries } in rank order, each with rank (from 1), playerId and score. limit (0 to 1000) defaults to 10 and is capped by the board’s max entries.

const { entries } = await m.leaderboards.top({ slug: 'weekly_arena', limit: 100 });
for (const entry of entries) {
console.log(entry.rank, entry.playerId, entry.score);
}

Entries do not carry player names; look them up in your own player data if you need them.

The module’s reset function runs hourly on a schedule, in both staging and prod. For each board with a reset period, it resets the board once the next boundary after its last reset has passed:

  1. Players whose rank falls in a reward range receive that reward through the reward module (currencies, items and counters).
  2. All entries of the board are deleted.

A board that was never reset counts from its creation time. Admins can also reset a board immediately with the Reset button on its detail page, which grants the rewards the same way.

Players do not need to claim anything: rewards land in the wallet and inventory during the reset.

To check scores before paying out, for example for anti-cheat, leave the board’s rewards empty and pay out from your backend. Read the final standings from the admin resource API with the environment’s admin key:

Terminal window
curl -H "X-API-Key: $RUDDER_ADMIN_KEY" \
"https://api.rudder.build/game/v1/resources/entries/rows?board_eq=weekly_arena&_sort=score&_order=desc&_start=0&_end=100"

The response is { items, total }; without _start/_end the endpoint returns 50 rows. Then grant rewards with POST /game/v1/players/wallet/adjust (one batch of up to 100 players, with an idempotencyKey) and reset the board from the dashboard.

  • Ties. Entries are sorted by score only, so the order of equal scores is not guaranteed. If tied players must get the same reward, use wider ranges or pay out from your backend.
  • Late submissions. The board accepts scores at any time. A submission just before the boundary counts until the reset runs, which can be up to an hour after the boundary.
  • never boards are never reset by the schedule. Use the Reset button to end a one-off tournament.
  • Environments. Boards, entries and resets are separate in staging and prod.