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.
Dashboard setup
Section titled “Dashboard setup”- Open Modules in the dashboard at
https://app.rudder.build/and installleaderboards. Its dependencies (reward,inventory,items) are installed with it. - 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 period —
weekly. Boards reset at 00:00 UTC on Mondays (dailyresets every day,monthlyon the first day of the month). - Order —
descwhen the highest score wins,ascfor time-attack boards where the lowest wins. - Max entries — optional cap on how many entries
topreturns. - Rewards — rank ranges with a reward each:
1–1,2–10,11–100. The dashboard rejects overlapping ranges and ranks below 1.
- Name — for example
- Create the board in
stagingfirst, test it there, then promote toprod.
Generate the client
Section titled “Generate the client”With leaderboards installed, generate a typed client (see Generated module clients):
rudder client generate --lang ts --out src/rudder.modules.tsrudder client generate --lang csharp --out Assets/Rudder/RudderModules.g.csSubmit scores
Section titled “Submit scores”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 });using RudderSdk.Modules;
var m = new RudderModules(client);var best = await m.Leaderboards.SubmitAsync(new LeaderboardsSubmitArgs { 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.
Show standings
Section titled “Show standings”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);}var top = await m.Leaderboards.TopAsync(new LeaderboardsTopArgs { Slug = "weekly_arena", Limit = 100 });
foreach (var entry in top.Entries){ Console.WriteLine($"{entry.Rank}. {entry.PlayerId} — {entry.Score}");}Entries do not carry player names; look them up in your own player data if you need them.
Payout and reset
Section titled “Payout and reset”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:
- Players whose rank falls in a reward range receive that reward through the
rewardmodule (currencies, items and counters). - 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.
Server-side alternative
Section titled “Server-side alternative”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:
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.
Edge cases and limits
Section titled “Edge cases and limits”- 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.
neverboards are never reset by the schedule. Use the Reset button to end a one-off tournament.- Environments. Boards, entries and resets are separate in
stagingandprod.