Skip to content

Leaderboard

The leaderboard ranks members by what they did on the exchange: how much they traded and made, how many contracts and markets they settled, how often they won, their biggest win, their return and their longest winning streak. It is public inside the platform (every ranked row shows a handle and an avatar, never a name, an email or an account id), and you control whether you appear on it.

metric What is ranked value type
volume Notional traded: filled quantity × market max_price, whatever the trade price dollar string
profit Net profit and loss on markets settled in the period, after fees dollar string, e.g. "12.5000"
predictions Contracts settled in the period integer
markets Markets settled in the period, whether won, lost or pushed integer
win_rate Markets won ÷ markets won or lost. Needs 10 decided markets in the period number, 0–1
biggest_win Net profit on your best single market settled in the period dollar string
return Net profit ÷ volume. Needs $500 of volume and a profit in the period number, 0–1
streak Longest run of winning markets in a row in the period; a push does not break it integer

STX decides which boards are shown and how many members each lists (10, 25, 50 or 100). Asking for a hidden board is not an error: it comes back empty with "shown": false. The table above gives how value is written on each board.

STX can keep some account types (for example market makers or STX’s own accounts) off every board. An account that is self-excluded, in a cool-off period, suspended, banned, closed, rejected, archived or overdrawn never appears on a board or a profile page. Only a positive value earns a place on a board: a member with nothing settled or traded in the period is not listed, and neither is a net loss on profit. Ranks are dense: two members with the same value share a rank, and the next distinct value takes the next rank. A board holds at most the configured number of members per board, never more than 100 rows.

Every period is a range of calendar days in America/New_York, ending today. A settlement at 23:30 New York time on a Sunday counts for Sunday even though it is already Monday in UTC.

period Covers Resets
daily Today Midnight New York, every day
weekly Monday to today Midnight New York on Monday
monthly The 1st to today Midnight New York on the 1st
yearly 1 January to today Midnight New York on 1 January
all Everything Never

Every board response carries next_reset_at as a UTC timestamp: local midnight shifted to UTC, so it moves by an hour across a daylight-saving change while the board still resets at 00:00 New York. It is null for all.

Boards are rebuilt on a fixed schedule (every 15 minutes by default, on the clock), not after each trade or settlement; refreshed_at is when the snapshot you are reading was built. A member who leaves the leaderboard is removed at once.

category is all (every sport combined) or one sport key: the lowercase sport name, as in a row’s top_sport (for example basketball). A sport has a board once a market in it has settled or traded in the period.

An unknown category is not an error. The board is simply empty, because a sport that is between seasons genuinely has nobody on it.

Method Path Returns
GET /api/v1/leaderboard?period=weekly&category=all&metric=profit&limit=50 The top rows of one board
GET /api/v1/leaderboard/me?period=weekly&category=all Your own standing, including a rank outside the top 100
GET /api/v1/me Your identity and public profile
PATCH /api/v1/me/profile Change handle, avatar or opt-in

All of period, category, metric and limit are optional and default to weekly, all, the board STX opens on and the number of members per board. An unknown period or metric is a 400 naming the field. limit is clamped to the number of members per board: a board is a fixed top-N, so there is no cursor and never a next page.

A board row:

{
"rank": 1,
"handle": "swift.fox12",
"avatar_url": "/avatars/swift.fox12.svg",
"top_sport": "basketball",
"top_sport_icon_url": "/api/images/categories/standard/basketball-6b422c4a.svg",
"value": "300.0000"
}

top_sport is the sport the member traded most in the period; on a sport board it is that sport.

Your own standing:

{
"profit": {"rank": 2, "value": "12.5000"},
"volume": {"rank": 1, "value": "400.0000"},
"predictions": {"rank": 3, "value": 7},
"markets": {"rank": 4, "value": 12},
"win_rate_rank": {"rank": 2, "value": 0.7},
"biggest_win": null,
"return": null,
"streak": {"rank": 6, "value": 3},
"win_rate": 0.7,
"settled_markets": 10,
"opted_in": true,
"period": "weekly",
"category": "basketball"
}

A metric you have nothing positive on is null even while you rank on another, and so is every board STX hides. The Win rate board’s rank is win_rate_rank; win_rate is your plain share of decided markets. win_rate is the share of decided markets you won, and is null until at least 10 markets have been decided in the period. A market you settled at exactly zero is neither a win nor a loss. When you are unranked (opted out, or no activity in the period), every metric is null, settled_markets is 0 and opted_in tells you which of the two it is.

These endpoints, and GET /api/v1/me / PATCH /api/v1/me/profile, accept either credential:

  • The signed Ed25519 headers every other /api/v1 endpoint takes; see request signing. A read_only key can read every leaderboard endpoint; PATCH /api/v1/me/profile needs read_write.
  • Authorization: Bearer <token> with the session token STX’s own apps sign in with. A session may always update its own profile. An integration signs with its API key.

With no credential, or a bad one, the answer is 401 {"error": "Unauthorized"}. If any X-STX-ACCESS-* header is present the request is treated as a signed request and the signing rules apply.

Your handle is the name other members see. It is separate from your sign-in email and never derived from your name. Every account starts with a generated adjective.animal1234 handle; you can pick your own:

  • 3 to 24 characters: lowercase letters, digits, and . or _ between them. Case is folded, so Swift.Fox12 is saved as swift.fox12.
  • Not already taken, not a reserved word (admin, support, stx, …) and not on the blocklist.
  • Changeable once every 30 days. GET /api/v1/me reports handle_changeable_at: null when you may change it now, otherwise when the window ends. Sending your current handle again is not a change.

Your avatar is generated from three values you choose and rendered on demand. There is no upload:

{"style": "dots", "seed": "a1b2c3d4", "palette": "ocean"}

style is one of dots, rings, stripes, grid, ball, court, stitch, target, candles, dice; palette one of ember, forest, ocean, grape, slate, mint, rose, gold; seed any 1–32 characters, and the same three values always render the same image. Every row carries avatar_url, a path relative to the API host (/avatars/{handle}.svg) that serves the SVG publicly with a one-day cache and an ETag.

curl -X PATCH https://demo.stxapp.io/api/v1/me/profile \
-H "X-STX-ACCESS-KEY: $KEY_ID" -H "X-STX-ACCESS-TIMESTAMP: $TS" \
-H "X-STX-ACCESS-SIGNATURE: $SIG" -H "Content-Type: application/json" \
-d '{"handle": "swift.fox12", "avatar": {"style": "rings", "seed": "deadbeef", "palette": "gold"}}'

The response is the same object GET /api/v1/me returns. A key of the wrong JSON type is a 400; a handle that is taken, reserved, malformed or changed too soon is a 422 whose error names the rule.

{"leaderboard_opt_in": false}

sent to PATCH /api/v1/me/profile removes you from every public board on the next snapshot. Your own GET /api/v1/leaderboard/me then reports every rank as null with opted_in: false; your trading is unaffected. Send true to join. Each change is recorded with its time.

A new account starts with the jurisdiction’s default. An account opened before the leaderboard existed is not listed until you join; joining also gives you a generated handle and avatar if you do not have one yet.

v1.5.9Changelogllms.txtllms-full.txt