Mark
Pricing Sign Up
← All posts

Which API token should your game use?

Mike Dalton By Mike Dalton ·

A game window and a server, each with a key icon, with arrows pointing to a dashboard card showing a bar chart, beside the Game Stats AI logo.

Game Stats AI has two types of API token. A client token can send telemetry, such as matches and achievement events, but cannot read reports. A server token can send telemetry and read reports. Use a client token in anything that ships inside a game build, and a server token in code that runs on a machine you control.

What each token can do

Client token Server token
Send matches, events, characters, and achievements Yes Yes
Read reports and other account data No Yes
Connect to the MCP server No Yes
Safe to ship inside a game build Yes No

Choose the type when you create the token in Settings > API tokens. The full token is shown once, right after you create it. New tokens start with their type, client_ or server_, so you can tell which kind is in your code.

The new API token screen, with a name field and a Client or Server token type choice

What the API returns for each token

The requests below put your account id and both tokens in environment variables:

export ACCOUNT_ID=your_account_id
export CLIENT_TOKEN=client_your_token
export SERVER_TOKEN=server_your_token

Each request uses -w "\n%{http_code}\n", which prints the HTTP status code after the response body.

A client token can send telemetry

Send a match to the matches endpoint with the client token:

curl -s -w "\n%{http_code}\n" -X POST "https://gamestats.ai/api/v1/accounts/$ACCOUNT_ID/matches" \
  -H "Authorization: Bearer $CLIENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"external_id": "match_8f3a2c", "version_name": "2.1.0", "match_at": "2026-10-12T20:15:00Z", "match_players": [{"username": "player_3e8", "match_attributes": {"win": 1, "loss": 0}}, {"username": "player_40d", "match_attributes": {"win": 0, "loss": 1}}]}'
{}
201

201 Created means the match was accepted. The endpoints for achievement events, progression events, characters, and achievements accept a client token in the same way.

A client token cannot read reports

Request the account's reports from the character reports endpoint with the same token:

curl -s -w "\n%{http_code}\n" "https://gamestats.ai/api/v1/accounts/$ACCOUNT_ID/character_reports" \
  -H "Authorization: Bearer $CLIENT_TOKEN"

403

403 Forbidden means the token is valid, but its type is not allowed to make this request. The body is empty, so print the status code to see it. Every endpoint that reads data responds this way to a client token, and so does the MCP server.

A token that does not exist, or that has been revoked, gets 401 Unauthorized instead.

A server token can read reports

Send the same request with the server token:

curl -s -w "\n%{http_code}\n" "https://gamestats.ai/api/v1/accounts/$ACCOUNT_ID/character_reports" \
  -H "Authorization: Bearer $SERVER_TOKEN"
[{"id":1,"external_id":null,"label":"Character Win Rates","description":null}]
200

200 OK means the request succeeded, and the body lists the account's character reports. A server token can also send everything a client token can.

Which token to use where

  • Inside a game build, for desktop, mobile, console, or the browser: use a client token. Players download the build, and anyone who looks can find the token in it.
  • On your game server or backend: use a server token. If your game already sends results through a backend you run, send telemetry from there, and no token ships to players at all.
  • In your own scripts and in the MCP server: use a server token, and keep it on your machine.

Treat any token inside a game build as public. A client token limits what someone who finds it can do: they can send telemetry to your account, but they cannot read your reports or any other data in it.

What browser origins do and do not do

A browser game also needs its origin added in Settings > Browser origins. The Phaser guide shows the setup.

The Browser origins settings page with http://localhost:5173 added

Before a page sends a request with a token to another domain, the browser asks that domain whether the page's origin is allowed. This request is called a preflight. You can send the same preflight with curl:

curl -s -i -X OPTIONS "https://gamestats.ai/api/v1/accounts/$ACCOUNT_ID/matches" \
  -H "Origin: https://play.yourgame.com" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: authorization, content-type"

For an origin you added, the response includes this header:

access-control-allow-origin: https://play.yourgame.com

For an origin you did not add, the header is missing, and the browser does not send the request.

The browser runs this check, not the API. curl, scripts, and games that do not run in a browser skip the preflight and send the request directly. Here is the client token sending a match with an origin that is not on the list:

curl -s -w "\n%{http_code}\n" -X POST "https://gamestats.ai/api/v1/accounts/$ACCOUNT_ID/matches" \
  -H "Origin: https://not-your-game.example" \
  -H "Authorization: Bearer $CLIENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"external_id": "match_8f3a2d", "version_name": "2.1.0", "match_at": "2026-10-12T20:20:00Z", "match_players": [{"username": "player_3e8", "match_attributes": {"win": 0, "loss": 1}}, {"username": "player_40d", "match_attributes": {"win": 1, "loss": 0}}]}'
{}
201

The match was accepted. Browser origins stop other websites from using your token in their visitors' browsers. They do not limit what a token can do outside a browser, so they do not protect a token that leaks. The token type does that. Games that do not run in a browser do not need any origins.

If a token leaks

Revoke it in Settings > API tokens. Every request with a revoked token gets 401 from that moment, including requests from builds your players already have.

A leaked server token can read all of your account's data, so revoke it right away and create a new one.

A leaked client token can only send telemetry, so you can choose when to revoke it. Revoke it right away to stop the requests, or first ship an update with a new client token so current players keep sending events, and revoke the old token after that.

Keep reading

© 2026 Rowhome Labs, LLC