Magicweave: Leaderboards
The API supports three integration styles:
- Atomic endpoints — fetch one resource at a time (meta, leagues, rewards, entries, users, me).
- Preset bundles — common combinations (
/overview,/standings,/context). - Mix-and-match hub —
/bundle?include=...to request any combination of sections in one call.
Legacy GET /{leaderboard_slug} remains available for backward compatibility.
Base Path
- All routes are under:
/leaderboards
Authentication and Authorization
All endpoints require:
- Client credentials headers:
x-client-idx-client-secret
- A bearer access token in
Authorization: Bearer <token> - Permission:
client.leaderboard
If any requirement is missing or invalid, the API returns 401 or 403.
Shared Query Parameters
These parameters appear on multiple endpoints:
| Parameter | Type | Default | Description |
|---|---|---|---|
league | string | — | League slug filter (entries, users, rewards, bundle presets) |
limit | int | 100 | Page size (1..1000) |
offset | int | 0 | Pagination offset (>= 0) |
source | string | ranked | User list source: ranked or assigned (see User list sources) |
expand | string | — | Comma-separated expansions; currently profile |
include | string | — | Comma-separated sections for list/bundle endpoints (see Include tokens) |
Include tokens
Used by GET / (list) and GET /{slug}/bundle:
| Token | List (GET /) | Bundle (GET /{slug}/bundle) |
|---|---|---|
meta | yes | yes |
leagues | yes | yes |
rewards | yes | yes |
entries | — | yes |
users | — | yes |
me | — | yes |
Unknown include values return 400.
User list sources
ranked(default) — players with a stat value on the board, ordered by rank. Respectsleaguefilter (dynamic stat bands or AT_RESET assignment cohort).assigned— AT_RESET boards only. PaginatesPlayerLeagueAssignmentrows for the active cycle. Returns400on non-AT_RESET boards. Users without a stat may haverank: nullandstat_value: null.
Profile expansion
Pass expand=profile on /entries, /users, /standings, /context, or /bundle to attach ClientUserProfileSnippet (nickname, avatar_url) to each row when a client profile exists.
Endpoints
List
GET /— List all leaderboards for the current project
Atomic
GET /{leaderboard_slug}/meta— Leaderboard configuration and cycle timingGET /{leaderboard_slug}/leagues— All league tiers and zone rulesGET /{leaderboard_slug}/leagues/{league_slug}— One league tier detailGET /{leaderboard_slug}/rewards— Reward catalog with resolved item payloadsGET /{leaderboard_slug}/entries— Paginated leaderboard rankings with metadataGET /{leaderboard_slug}/users— Paginated user list with ranked or assigned sourceGET /{leaderboard_slug}/me— Current player's rank and league
Presets and bundle
GET /{leaderboard_slug}/bundle— Request any combination of sections in one responseGET /{leaderboard_slug}/overview— Preset:meta+leagues+rewards+meGET /{leaderboard_slug}/standings— Preset: paginatedentries+meGET /{leaderboard_slug}/context— Preset: all sections
Legacy
GET /{leaderboard_slug}— Legacy paginated rankings (no pagination metadata). Prefer/entriesfor new integrations.
Response Models
ClientPaginationMeta
limit: integeroffset: integertotal: integer — total rows matching the current filterhas_more: boolean —truewhenoffset + limit < total
ClientLeaderboardMetaResponse
slug,name,sort_order,leaderboard_type,stat_key: stringsleagues_enabled,expired: booleanspromotion_timing,reset_type: string ornullcycle_key,cycle_started_at,cycle_ends_at: present on relative boards withreset_rruleexpires_at: datetime ornull(absolute boards)
ClientLeagueResponse
slug,name: stringsmin_value,max_value: number ornull— half-open band[min, max)promotion_mode,demotion_mode: strings (none,top_ranks,bottom_ranks,stat_percent_from_max,stat_percent_from_min)promotion_rank_count,demotion_rank_count: integer ornullpromotion_percent,demotion_percent: number ornull
ClientRewardResponse
reward_trigger: string (promotion,demotion,rank)rank: integer ornull(forranktriggers)league_slug: string ornullitems: list of reward payload objects (currency,gem,stat, etc.)
ClientLeaderboardEntryResponse
Used in /entries and /users responses:
rank: integer ornulluser_id: integerstat_value: number ornullleague: string ornullprofile:ClientUserProfileSnippetornull(whenexpand=profile)
ClientUserProfileSnippet
nickname: stringavatar_url: string ornull
LeaderboardReadResponse (legacy)
leaderboard_id,leaderboard_slug,leaderboard_name,sort_orderleague: string ornullexpired: booleanentries: list of{ rank, user_id, stat_value }
CurrentUserLeaderboardResponse
leaderboard_id,leaderboard_slug,leaderboard_name,user_idrank,stat_value,league: nullableexpired: boolean
Behavior Notes
- Project scope is resolved from client credentials; leaderboard slugs are unique per project.
- Absolute leaderboards reject
leaguefilters on entries/users (400). - AT_RESET league filtering uses the active cycle's assignment cohort, not live stat bands.
- Dynamic league boards infer league from stat value bands at read time.
- Reward payloads mirror the admin-configured bundle items; grants are not exposed on this API.
Error Cases
400 Bad Request- Unknown
includetoken - Empty
includeon/bundle source=assignedon a non-AT_RESET boardleaguefilter on an absolute leaderboard
- Unknown
401 Unauthorized- Missing
x-client-idorx-client-secret - Invalid client credentials
- Missing or invalid bearer token
- Expired token
- Missing
403 Forbidden- Authenticated user does not have
client.leaderboardpermission
- Authenticated user does not have
404 Not Found- Leaderboard or league slug not found for the current project
cURL Example
curl -X GET "http://localhost:8000/client/leaderboards?include=meta,leagues" \
-H "x-client-id: <your-client-id>" \
-H "x-client-secret: <your-client-secret>" \
-H "Authorization: Bearer <access-token>"