Skip to main content
XBOX services leaderboards are derived from user statistics and built by queries. This is different from the leaderboards on Steam, which are driven by “scores” that are uploaded to the API. Similar to achievements, the XBOX Game Development Kit (GDK) has two APIs for statistics: event-based and title-managed. Unlike achievements, we recommend that you use event-based statistics and leaderboards over title-managed. We focus on that API in this topic. For more information about how these two APIs differ, see Event-based vs. title-managed Stats. Both platforms define leaderboards on their portals. The difference is that XBOX services has you first define a stat rule on Partner Center, and then build a leaderboard based on that statistic that the rule drives. Steam, on the other hand, doesn’t make a distinction between the two: you create a leaderboard in their portal or programmatically do so, and then upload user scores directly to that leaderboard. To illustrate how each of these APIs can be used compared to the Steam Leaderboard API, code examples are provided about how to create a leaderboard for furthest distance traveled (the example is from the Steamworks API documentation) on the Steam SDK and the event-based XBOX Game Development Kit (GDK) stats platform. The following sections walk through the logic.

Creating a stat/leaderboard in the portal

Steamworks

On the Steamworks admin portal, go to Stats & Achievements > Leaderboards. Complete the form as shown in the following screenshot (from the Steamworks documentation).

XBOX Game Development Kit (GDK) (event-based)

On Partner Center, go to your game and select XBOX services > Gameplay settings. On the navigation bar on the right pane, select Player Stats > Stat Rules and add a stat rule as Show, configuring it to meet your stat’s needs. Because our stat updates will include a calculated value of how far the player (user) has traveled since the last update, we’ll specify a measurement field for the service to get this value from.
There’s no functional difference if you store the data to update an event in the event’s Measurements or Dimensions field. The two fields exist for use with Application Insights. For more information about this, see [Application Insights API for custom events and
metrics](https://learn.microsoft.com/en-us/azure/azure-monitor/app/api-custom-events-metrics). The following screenshot shows the form that’s used to create a stat rule in Partner Center. After saving, select Leaderboard on the top bar of the right pane and create a new leaderboard that’s driven by the stat you just created as shown in the following screenshot.

Uploading a score

Steamworks

On Steamworks, you need to calculate the new total value of feet traveled and send it to the API by using the ISteamUserStats::UploaderLeaderboardScore method.

XBOX Game Development Kit (GDK) (event-based)

With event-based stats in the XBOX Game Development Kit (GDK), you simply need to pass the difference in feet traveled to XblEventsWriteInGameEvent because we specified that we want to increment this stat when receiving an event and have specified where to find this diff value in the measurements JSON string, shown as follows.
For more information, see Writing an event to power an event-based Stat.

Getting a global leaderboard

Global leaderboards can be fetched with the Steamworks SDK by calling ISteamUserStats::GetLeaderboardEntries, and then calling ISteamUserStats::GetDownloadedLeaderboardEntry in the callback function to get each entry or “row” of the leaderboard.

Steamworks

XBOX Game Development Kit (GDK) (event-based)

The XBOX Game Development Kit (GDK) APIs follow a similar pattern. Build a query specifying which leaderboard you want, what scope it should cover, how to sort it, which additional fields it should contain (if any), and more. After calling XblLeaderboardGetLeaderboardAsync with your query, you can use XblLeaderboardGetLeaderboardResultSize and XblLeaderboardGetLeaderboardResult to put the results into your specified buffer and iterate over them as shown in the following code example.
For more information, see the following:

Getting a social leaderboard

On Steamworks, you can use the ELeaderboardDataRequest::k_ELeaderboardDataRequestFriends enum to scope the leaderboard to the current user’s friends. In the XBOX Game Development Kit (GDK), this is known as a social leaderboard. To get a social leaderboard from XBOXBOX services, set xboxIUserId equal to the XBOX User ID (XUID) of the current user who is signed in to XBOX services, leaderboardName to nullptr, and the socialGroup as XblSocialGroupType::People or XblSocialGroupType::Favorites in your XblLeaderboardQuery struct. Call XblLeaderboardGetLeaderboardAsync as previously shown. For more information, see XblSocialGroupType. In addition to the usual user stats that are used to generate Steam-like leaderboards, XBOX services has an additional concept called Featured Stats. Featured Stats appear on several different surfaces across the XBOX ecosystem for your game and can show the values of user’s stats or leaderboards that are already generated. You can create up to 20 Featured Stats for your game. For more information about Featured Stats and how to add them, see Featured Stats overview and Portal configuration of event-based Featured Stats.

Rate limiting

When writing events, be careful to avoid hitting the XBOX Services API (XSAPI) too often, because it may cause your game to hit its rate limit. This may cause unexpected behavior and a bad experience for your users. Note that this is an XBOX services concern that isn’t an issue on Steam. Writing stat values on Steam doesn’t cause an API call to the server until your game explicitly syncs them. For events that frequently occur, try batching API calls to be fired after a certain number of events happen or to update on the server at a certain time interval. You can debug your API calls by using the XBOX Live Trace Analyzer (XblTraceAnalyzer.exe). For more information about rate limiting on XBOX services, see Fine-Grained Rate Limiting.
Last modified on August 20, 2026