Identifying your player
One server-to-server call, before you show a game, returns a short-lived token scoped to the player and game you name.
The call
POST /partner/sessions
Authorization: Bearer <your API key>
Content-Type: application/json
{
"playerId": "u_8813", // yours, stable per player
"gameId": "streakpeaks",
"displayName": "Ada Lovelace" // optional — what their opponent sees
}The response
200 {
"uid": "ptr:acme:u_8813",
"token": "eyJhbGciOiJIUzI1NiJ9…",
"expiresAt": 1754211600,
"displayName": "Ada Lovelace"
}| Field | Meaning |
|---|---|
| uid | Our identifier, derived from yours; every later record refers to it. Store what you were given rather than rebuilding it — see below. |
| token | An opaque bearer credential, valid one hour, scoped to this player and game. |
| expiresAt | That expiry, as Unix epoch seconds. |
| displayName | The name we actually stored, not always the one you sent — see below. |
Mint one per session rather than storing tokens, and pass it to the frame per Embedding a game.
The player id is yours; the uid is ours
playerId is 1–64 characters of A-Za-z0-9_- — no colons, dots, slashes, spaces or non-ASCII; whitespace trimmed, nothing else transformed. Map ids like emails or braced UUIDs to a compliant one first, or get 400 malformed_player_id.
The environment is part of the uid: a live key gives ptr:acme:u_8813, a test key ptr:test:acme:u_8813 — the same playerId is two different players whose histories never mix. The uid is derived, not chosen, and never collides with another partner's, ours or any first-party account. Changing how you generate playerId for the same real person produces a different player with none of that history carried over. displayName plays no part in identity: changing it never creates a new player or breaks the link to their history.
The name is yours too
Send displayName and that is what the opponent sees — the only way a name reaches us, since there is no in-frame route to set one. Names are 1–20 characters of letters, digits, spaces and - _ .; we clean rather than reject one, so a disallowed character never stops play, substituting our own handle if nothing usable is left — compare the response against what you sent to see if anything changed. Omitting displayName leaves whatever is already stored rather than clearing it.
What we store about a player of yours
The complete list, none asked directly — it comes from the mint call and the games played.
- The uid — ptr:<partnerId>:<playerId> — and the display name we actually stored (yours, or a generated handle).
- Their match records — both uids, each display name at the time, each score, and when created, started and finished. Kept after an account closes — it is the other player's history too.
- Per-game stats folded from those matches — play/win/loss/tie counts and scores — plus a skill rating, never shown to anyone.
Not stored: email, password or credential, payout address, or balance — settlement runs through you, so it skips the payout check a first-party account is held to.
Closing a player's account
No partner-facing route for this — ask us; we close it by uid.