Kraty

SDK API reference

Every /sdk/v1 endpoint your game client talks to, rendered from the OpenAPI spec.

These endpoints back the game-client SDKs. They all take a client_sdk API key; routes that read or mutate a specific player's state additionally require the per-player secret. See Authentication for the security model.

For the human-readable overview with auth notes and idempotency guidance, start at the REST API page. The list below is the machine-derived companion, generated from the OpenAPI spec on every build, so it cannot drift from the implementation.

Health

Connectivity probes.

get/ping

Cheap auth probe.

Returns 200 if the supplied API key validates, with the key's environment (`live` / `test`) and the game it belongs to. Use as a connectivity smoke test before issuing real SDK calls.

Responses

  • 200Authenticated.SdkPingResponse
  • 401Missing or invalid API key.ErrorResponse
get/time

Authoritative server clock (anti-cheat game timers).

Returns the server time as `epochMs` (UTC) + `iso`. Fetch once at startup and anchor a monotonic timer to it so players cannot spoof event countdowns by changing their device clock; compare `epochMs` against event `endsAt`. Pass `?timezone=<IANA>` (e.g. `Europe/Lisbon`) to also receive that zone's wall-clock (`local`) + `offsetMinutes` for display.

Query parameters

FieldTypeDescription
timezonestring

Responses

  • 200Server time.TimeResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse

Events

Start and progress event attempts.

get/players/:externalId/events

List events with active windows for a player.

Returns events whose current window is active. The `leaderboardId` is non-null only for `global` mode; grouped/segmented events allocate per-player on `/start`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
status"active"

Responses

  • 200List of active events.EventsListResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
post/players/:externalId/events/:eventKey/start

Start an attempt.

Upserts the player on first contact and creates a fresh attempt against the event's active window. Returns 202 with the lobby id when the event uses matchmaking and the lobby is still forming.

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring

Request body (required)

FieldTypeDescription
playerContextobject
idempotencyKeystring

Responses

  • 201Attempt created.StartAttemptResponse
  • 202Lobby still forming. Poll `/sdk/v1/lobbies/{lobbyId}` until status=`active`, then retry start.ErrorResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/events/:eventKey/attempts/:attemptId/progress

Report progress on an active attempt.

Updates the attempt's metrics and recomputes the score via the event's score formula. Completing the attempt (hitting the target metric or supplying `mode=set` with the final value) automatically triggers the reward pipeline and emits webhooks.

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring
attemptIdrequiredstring

Request body (required)

FieldTypeDescription
moderequired"increment" | "set"
metricValuenumber
metricsobject
occurredAtstring
idempotencyKeystring
eventTeamIdstring

Responses

  • 200Updated attempt.ProgressResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/event-teams/:eventTeamId/members

A co-op team's members.

The team's members in in-team rank order (by counted contribution): name, avatar, contribution, rank, seat status and `isSelf`. Only a player with a seat on the team may read it; anyone else gets 404. Page with `cursor` (the returned `nextCursor`). The player's own team score, goal and milestones ride on the events listing and the start / progress responses (`teams`).

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventTeamIdrequiredstring

Query parameters

FieldTypeDescription
cursorstring
limitinteger

Responses

  • 200One page of members.EventTeamMembersResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/events/:eventKey/teams/match

Find a team (auto-matched team events).

For events whose teams use the `auto_match` formation: the player's team in the active window, found (the oldest open team with room in their matchmaking slice) or opened. A team plays from its first member; one still under-filled when its join window closes gets a smaller goal. Idempotent: a player who already has a team gets it back. `start` matches a team-less player too, so this call is optional (e.g. to show the team before playing). 409 `team_formation_mismatch` for other formations, 409 `late_join_next_window` (with `nextWindowId`) when the event only matches early in a window, 422 `player_banned`. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring

Request body

FieldTypeDescription
idempotencyKeystring

Responses

  • 200The player's team and seats.TeamMatchResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 422The player is banned.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/events/:eventKey/partners/invites

List pending partner invites.

Pending invites in the event's active window: sent to the player (`direction=in`, default) or by them (`direction=out`). Expired invites are left out. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring

Query parameters

FieldTypeDescription
direction"in" | "out"

Responses

  • 200Pending invites.PartnerInviteListResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/events/:eventKey/partners/invites

Invite a partner (partner events).

For events whose teams use the `partner_slots` formation: invites a player (by `externalPlayerId` or `friendCode`) to a new pair, which is its own team with its own bar. A pending invite holds a slot on both sides (`maxPartners`). If they had already invited you, this accepts their invite (200, `status: 'accepted'`). A declined, cancelled or expired pair can be invited again. 403 `player_blocked` (a block either way), 409 `partner_limit_reached` (`details.externalPlayerId` names who is full), 409 `already_partners`, 400 `cannot_partner_self`. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring

Request body (required)

FieldTypeDescription
externalPlayerIdstring
friendCodestring
idempotencyKeystring

Responses

  • 200Their pending invite to you was accepted instead.PartnerInviteResponse
  • 201Invite sent (or already pending).PartnerInviteResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/events/:eventKey/partners/invites/:eventTeamId/accept

Accept a partner invite.

The invited player accepts: the pair's bar goes live (its goal resolves for its members) and both partners can play for it (`eventTeamId` on progress). 404 for an unknown or foreign invite (or one whose inviter can no longer play), 409 `invite_expired` once it expired; 403 `player_blocked` if a block appeared since. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring
eventTeamIdrequiredstring

Request body

FieldTypeDescription
idempotencyKeystring

Responses

  • 200The accepted invite and the player's team seats.AcceptPartnerInviteResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/events/:eventKey/partners/invites/:eventTeamId/decline

Decline a partner invite.

The invited player declines: the pair closes and both players get their slot back. A later invite between them starts it over. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring
eventTeamIdrequiredstring

Request body

FieldTypeDescription
idempotencyKeystring

Responses

  • 200The closed invite.PartnerInviteResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/events/:eventKey/partners/invites/:eventTeamId/cancel

Cancel a partner invite.

The inviter withdraws: the pair closes and both players get their slot back. A later invite between them starts it over. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring
eventTeamIdrequiredstring

Request body

FieldTypeDescription
idempotencyKeystring

Responses

  • 200The closed invite.PartnerInviteResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/events/:eventKey/partners/random

Get a random partner.

Pairs the player with the oldest bar waiting for a random partner (never a blocked player or a debug account), or opens a bar that waits for one (`status: 'waiting'`). The waiting bar is playable at once; after the event's `randomFallbackSeconds` alone it stays a solo bar with a one-member goal. Idempotent while waiting. 409 `random_partner_disabled` when the event has no random partners, 409 `partner_limit_reached`. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring

Request body

FieldTypeDescription
idempotencyKeystring

Responses

  • 200Paired or waiting, with the player's team seats.RandomPartnerResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/events/:eventKey/partners/suggestions

Partner suggestions.

Players the caller could invite: friends first, then recently active players, each with a free partner slot and not already partnered or invited; blocked players (either way) and debug accounts are never suggested. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring

Query parameters

FieldTypeDescription
limitinteger

Responses

  • 200Suggested partners.PartnerSuggestionsResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse

Leaderboards

Read live and finalized leaderboards.

get/leaderboards

List the game's leaderboards.

Dashboard-configured leaderboards for the key's game (archived ones omitted), so a client can discover board keys instead of hard-coding them. Includes the next reset, whether client score submission is allowed, and the playerContext fields that segment the board.

Responses

  • 200Leaderboards.SdkLeaderboardListResponse
  • 401Missing or invalid API key.ErrorResponse
get/event-leaderboards/:leaderboardId

Read a per-event-window leaderboard.

Returns the top `limit` entries (1–200, default 50). When the window is closed the entries come from the materialized table; while active they come from the Redis sorted set with a short-TTL view cache. Pass `includeSelf=true&externalId=<id>` to also receive the player's own rank/score.

Path parameters

FieldTypeDescription
leaderboardIdrequiredstring

Query parameters

FieldTypeDescription
limitinteger
progressionstring
includeSelfboolean | null
externalIdstring

Responses

  • 200Leaderboard view.LeaderboardResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/event-leaderboards/:leaderboardId/stream

Subscribe to live score updates over Server-Sent Events.

Opens a persistent `text/event-stream` connection that emits a JSON event each time a player submits progress to this leaderboard. Event types: - `ready`: sent once when the stream is wired (payload: `{ leaderboardId, finalized }`). - `score_update`: sent on each player progress write (payload: `LeaderboardStreamEvent`). - `closed`: sent once when the leaderboard is already finalized; the server then closes the connection. The server also writes SSE comment heartbeats (`:`-prefixed lines) every 15 seconds to keep intermediaries from reaping the socket; clients should ignore them. Bot-evaluator score writes and initial window-open registrations are not broadcast; only player-driven progress.

Path parameters

FieldTypeDescription
leaderboardIdrequiredstring

Responses

  • 200SSE stream open. Body is `text/event-stream`.
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse

Grants

Pull, claim, and open reward grants.

get/players/:externalId/pending-grants

List a player's unclaimed grants.

Returns up to `limit` (1–200, default 50) grants in `pending` status newest-first. A player who has never started an attempt returns an empty list (not 404).

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
limitinteger

Responses

  • 200List of pending grants.PendingGrantsResponse
  • 401Missing or invalid API key.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/grants

Create a grant for the calling player (permissive mode).

Client-initiated grant: the player-authenticated game client grants items / currency / a crate to ITS OWN player (the player secret enforces self-only — a client can never grant to another player). Requires `games.settings.inventoryManagement = 'permissive'`; any other mode returns `403 inventory_not_permissive`. Permissive is platform-managed, so a `reward` grant auto-deposits into the player's holdings and can be read straight back from `/inventory` and `/wallet`. Pass an optional `idempotencyKey` to make retries return the same grant.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Request body (required)

FieldTypeDescription
kindGrantKind→ GrantKind
entriesrequiredSdkGrantEntry[]
expiresAtstring
metadataobject
idempotencyKeystring

Responses

  • 200Idempotency-key replay: the same grant is returned.SdkGrantResponse
  • 201Grant created.SdkGrantResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403Inventory management isn't set to `permissive` for this game.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/grants/:grantId/claim

Claim a grant.

Atomic transition from `pending` → `claimed` with `ackedBy=sdk`. Replays against an already-claimed grant return the same row + 200 (idempotent). Grants belonging to a different player return 404 (no cross-tenant enumeration).

Path parameters

FieldTypeDescription
externalIdrequiredstring
grantIdrequiredstring

Request body

FieldTypeDescription
idempotencyKeystring

Responses

  • 200Grant after claim.ClaimGrantResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/crates/:grantId/open

Open a crate grant.

Atomic: rolls the crate's reward table, creates a `kind=reward` child grant with the rolled entries, flips the crate to `claimed`. Replays return the previously-rolled contents (idempotent via the crate id).

Path parameters

FieldTypeDescription
externalIdrequiredstring
grantIdrequiredstring

Responses

  • 200Crate + rolled contents grant.OpenCrateResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse

Lobbies

Poll matchmaking lobbies between start retries.

get/lobbies/:lobbyId

Poll a lobby waiting to fill.

Used after `/start` returns 202. Once `status=active`, retry `/start` to get an attempt.

Path parameters

FieldTypeDescription
lobbyIdrequiredstring

Responses

  • 200Lobby state.LobbyResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse

Daily-login

Read the game's daily login calendar and the player's place on it.

get/players/:externalId/daily-login

The game's daily login calendar for this player.

Days with their reward entries, what happens after the last day (`restart` | `hold_last` | `stop`), the player's `loginStreak` and `currentDay` (0 without a streak), whether today is already paid, and `nextDayAt` (start of the next UTC day). Read-only: authenticating the request records the session, which is what pays today's reward as a `daily_login` grant, so call this on launch and today is already marked paid. `data` is null when the game has no calendar or it is off for this environment. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200The calendar, or null.DailyLoginResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse

Friends

Player social graph: friend codes, requests, the friends list with live presence, username search, and blocking.

get/players/:externalId/friend-code

Get (and lazily generate) the player's shareable friend code.

Returns the caller's short friend code (6 chars, unambiguous alphabet), generating one on first use. A player shares this code out-of-band so a friend can add them without a username search. Pass `?progression=level` to also get the caller's own balance of those progression items. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
progressionstring

Responses

  • 200The player's friend code.FriendCodeResponse
  • 401Missing or invalid API key.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/presence

Heartbeat the player's online presence.

Refreshes the caller's online status (a TTL'd record; call every ~30s while active). Optionally sets a free-form status label ("in_match", "lobby", …) that friends see. Presence expires automatically when heartbeats stop. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Request body

FieldTypeDescription
statusstring | null

Responses

  • 200Presence recorded.PresenceResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/friends

List the player's friends with live presence.

Returns accepted friends within the same game + environment, each enriched with display identity and current online status / last-active / status label. Pass `?progression=level` to also get each friend's balance of those progression items (e.g. their level) in the same round-trip. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
progressionstring

Responses

  • 200The player's friends.FriendListResponse
  • 401Missing or invalid API key.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/friends/suggestions

Suggest players to add as friends.

Returns "people you may want to add": recently-active players in the same game + environment the caller has no relationship with (not already a friend, no pending request either way, not blocked, not self). Results are a weighted-random sample biased toward the most recently active, so repeating the call surfaces a different set — no cursor needed. `?limit=` defaults to 5 (clamped 1–25); `?progression=level` attaches progression balances. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
limitinteger
progressionstring

Responses

  • 200Suggested players.FriendSuggestionsResponse
  • 401Missing or invalid API key.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/friends/requests

List pending friend requests.

Returns the caller's pending incoming and outgoing friend requests. Pass `?progression=level` to attach each player's progression balances. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
progressionstring

Responses

  • 200Pending requests.FriendRequestsResponse
  • 401Missing or invalid API key.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/friends/requests

Send a friend request (or auto-accept a reciprocal one).

Adds another player by their `friendCode` or `externalPlayerId` (exactly one). Creates a pending request they must accept — unless they had already requested the caller, in which case the friendship is accepted immediately (200). Refused with 403 `player_blocked` when a block exists in either direction, 409 `already_friends` when already friends, 400 `cannot_friend_self` for self-adds. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Request body (required)

FieldTypeDescription
friendCodestring
externalPlayerIdstring

Responses

  • 200Reciprocal request auto-accepted into a friendship.SendFriendRequestResponse
  • 201Friend request created (pending).SendFriendRequestResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/friends/requests/:requestId/accept

Accept an incoming friend request.

Accepts a pending request addressed to the caller, establishing the friendship. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
requestIdrequiredstring

Responses

  • 200Request accepted; the new friend is returned.AcceptFriendRequestResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/friends/requests/:requestId/decline

Decline an incoming friend request.

Declines (deletes) a pending request addressed to the caller. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
requestIdrequiredstring

Responses

  • 200Request declined.PingResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
delete/players/:externalId/friends/requests/:requestId

Cancel an outgoing friend request.

Cancels (deletes) a pending request the caller sent. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
requestIdrequiredstring

Responses

  • 200Request cancelled.PingResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
delete/players/:externalId/friends/:friendExternalId

Remove a friend.

Ends an existing friendship (both directions). Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
friendExternalIdrequiredstring

Responses

  • 200Friend removed.PingResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/blocks

List blocked players.

Returns the players the caller has blocked. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200Blocked players.BlockListResponse
  • 401Missing or invalid API key.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/blocks

Block a player.

Blocks another player by `friendCode` or `externalPlayerId`. Tears down any existing friendship / pending requests between the two, and hides each from the other's search + presence. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Request body (required)

FieldTypeDescription
friendCodestring
externalPlayerIdstring

Responses

  • 201Player blocked.BlockPlayerResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
delete/players/:externalId/blocks/:blockedExternalId

Unblock a player.

Removes a block the caller had placed. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
blockedExternalIdrequiredstring

Responses

  • 200Player unblocked.PingResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse

Guilds

Guilds: found, join, roles, leave, discovery and help requests.

get/players/:externalId/guilds/config

The game's guild rules, as this player sees them.

Max members (fixed 50), default join type, what each role may do, the unlock gate (with the caller's balance and eligibility; `active: false` when the studio picked no item), the create cost, cooldowns, help-request settings and the guild week (the weekly donation cap counts over it). Build every guild screen from this instead of hardcoding rules. 403 `guilds_disabled` when guilds are off for this key's environment. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200The guild config.GuildClientConfigResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/guilds

Search guilds by name.

Case-insensitive name search over live guilds in the same game + environment, prefix matches first. `?country=` filters by the guild's country (ISO-3166 alpha-2). In the live environment, guilds made only of debug players are hidden. Paged: `limit` (default 20, max 50) and `offset`; `nextOffset` is null on the last page, and paging stops at offset 500. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
qrequiredstring
countrystring
limitinteger
offsetinteger | null

Responses

  • 200A page of matching guilds.GuildSearchResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/guilds

Found a guild.

The caller becomes its leader. Checks the unlock gate and the leave cooldown, then charges the create cost in the same transaction (409 `guild_insufficient_balance`). In a game that manages inventory itself (`config.costsChargedBy: 'studio'`) Kraty charges nothing: the game charges the player. Names are unique per game, ignoring case, accents and look-alike letters (409 `guild_name_taken`); invisible and bidi characters are refused (400 `validation_failed`) and pass the studio's name filter (400 `guild_name_rejected`). 409 `already_in_guild`. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Request body (required)

FieldTypeDescription
namerequiredstring
descriptionstring | null
badgestring | null
countrystring | null
joinTypeGuildJoinType→ GuildJoinType
metadataobject
idempotencyKeystring

Responses

  • 201Founded.CreatedGuildResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/guilds/:guildId

A guild with its roster.

Profile, leader and members (role, tenure, last seen, online, helps this week). Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring
guildIdrequiredstring

Responses

  • 200The guild.GuildDetailResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/guilds/:guildId/join

Join an open guild, or ask to join a request guild.

Open guild: joins now (200, `status: joined`). Request guild: creates or returns the pending request (201, `status: requested`). Both check the unlock gate, the leave cooldown (429 `guild_join_cooldown`) and the kick block for this guild (403 `guild_rejoin_blocked`). A declined player can ask the same guild again after 24 h (429 `guild_request_retry`); at most 10 pending requests (429 `guild_request_limit`). 409 `guild_full` / `already_in_guild`. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring
guildIdrequiredstring

Request body

FieldTypeDescription
messagestring | null
idempotencyKeystring

Responses

  • 200Joined.GuildJoinResultResponse
  • 201Request created (or already pending).GuildJoinResultResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/guild-requests

The player's pending join requests.

Outgoing requests still waiting for an answer. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200Pending requests.GuildJoinRequestListResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
delete/players/:externalId/guild-requests/:requestId

Cancel one of the player's join requests.

204 on success; 409 `conflict` when it was already answered. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring
requestIdrequiredstring

Responses

  • 204Cancelled.
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/guild

The player's guild.

The guild with its roster, and the caller's role and permissions. `data: null` when the player has no guild. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200The guild, or null.MyGuildResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
patch/players/:externalId/guild

Edit the guild's profile.

Name, description, badge, country, join type, metadata. Needs `edit_profile` (403 `guild_permission_denied`); names pass the name filter. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Request body (required)

FieldTypeDescription
namestring
descriptionstring | null
badgestring | null
countrystring | null
joinTypeGuildJoinType→ GuildJoinType
metadataobject
idempotencyKeystring

Responses

  • 200Updated.GuildDetailResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/guild/leave

Leave the guild.

A leaving leader hands the guild to the longest-serving co-leader, else the longest-serving member (`newLeader`); the last member leaving disbands it (`disbanded`). Cancels the player's open help request. 409 `not_in_guild`. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200Left.GuildLeaveResultResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/guild/requests

The guild's pending join requests.

Oldest first. Needs `accept_requests`. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200The inbox.GuildJoinRequestListResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/guild/requests/:requestId/accept

Accept a join request.

The requester becomes a member; the gate, cooldowns and room are re-checked now. Returns the guild. Needs `accept_requests`. 409 `conflict` when it was already answered. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring
requestIdrequiredstring

Responses

  • 200Accepted.GuildDetailResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/guild/requests/:requestId/decline

Decline a join request.

The request is closed (204). The player may ask again after 24 h. Needs `accept_requests`. 409 `conflict` when it was already answered. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring
requestIdrequiredstring

Responses

  • 204Declined.
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/guild/members/:memberExternalId/kick

Kick a member.

Needs `kick` and a strictly higher rank than the target (403 `guild_permission_denied`). A kicked player can't rejoin this guild for the configured block (default 7 days). Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring
memberExternalIdrequiredstring

Responses

  • 200The guild after the change.GuildDetailResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/guild/members/:memberExternalId/promote

Promote a member to co-leader.

Needs `promote` and a strictly higher rank than the target (403 `guild_permission_denied`). Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring
memberExternalIdrequiredstring

Responses

  • 200The guild after the change.GuildDetailResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/guild/members/:memberExternalId/demote

Demote a co-leader to member.

Needs `demote` and a strictly higher rank than the target (403 `guild_permission_denied`). Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring
memberExternalIdrequiredstring

Responses

  • 200The guild after the change.GuildDetailResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/guild/leader

Hand leadership to another member.

Leader only. The caller becomes a co-leader. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Request body (required)

FieldTypeDescription
externalPlayerIdrequiredstring
idempotencyKeystring

Responses

  • 200Handed over.GuildDetailResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/guild/help

The guild's help requests and the player's weekly helps counter.

Open requests (newest first), the caller's latest request, when they may ask again, and donations made this guild week. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200Help overview.GuildHelpOverviewResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/guild/help

Ask guildmates for a resource.

Only resources on the game's help list, up to their per-request cap. One open request at a time (409 `guild_help_active`), with a cooldown between requests (429 `guild_help_cooldown`). Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Request body (required)

FieldTypeDescription
typerequired"item" | "currency"
resourceKeyrequiredstring
amountrequiredinteger
idempotencyKeystring

Responses

  • 201Requested.GuildHelpRequestResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/guild/help/:requestId/donate

Donate to a guildmate's help request.

Delivered to the requester as a grant (`sourceKind: guild_help`); the donor may get a reward grant (`guild_help_reward`). A resource that costs the donor is debited (409 `guild_help_insufficient_balance`). Weekly cap: 429 `guild_help_limit_reached`. 409 `guild_help_closed` once filled, cancelled or expired. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring
requestIdrequiredstring

Request body

FieldTypeDescription
amountinteger
idempotencyKeystring

Responses

  • 201Donated.GuildHelpDonationResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
delete/players/:externalId/guild/help/:requestId

Cancel your own help request.

Donations already made stay delivered. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring
requestIdrequiredstring

Responses

  • 200Cancelled.GuildHelpRequestResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse

Players

post/players/:externalId/register

Mint a per-player secret for zero-trust auth.

Game client calls this ONCE on first launch (or after a data wipe). Returns the player row + plaintext `secret`. Because it is surfaced only here, the SDK must persist it locally and present it as `X-Player-Secret` on every subsequent player-scoped call. 409 if the player already has a secret; pass `?force=true` (dev/test API keys only) to rotate.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
forceboolean | null

Responses

  • 201Player registered (or rotated); plaintext secret in response body.RegisterPlayerResponse
  • 401Missing or invalid API key.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse

Inventory

get/players/:externalId/inventory

List the player's platform-managed inventory.

Returns every item the player currently holds. Requires `X-Player-Secret`. For studio-managed inventory games the list is always empty, because the studio backend holds the canonical state in that mode.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200Player inventory rows.InventoryListResponse
  • 401Missing or invalid API key.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/inventory/:itemKey/consume

Atomically decrement an item quantity.

Requires `X-Player-Secret`. 409 `conflict` if the player doesn't have enough of the item, because the ledger never goes negative. Idempotent on `idempotencyKey`.

Path parameters

FieldTypeDescription
externalIdrequiredstring
itemKeyrequiredstring

Request body (required)

FieldTypeDescription
quantityrequiredinteger
reasonstring
idempotencyKeystring

Responses

  • 200New holding after the decrement.ConsumeItemResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/wallet

List the player's wallet entries.

Returns every economy entry the player has touched, including zero-balance rows (so a wallet that's been emptied still surfaces). Requires `X-Player-Secret`. Filter client-side for live balances.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200Player wallet rows.WalletListResponse
  • 401Missing or invalid API key.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/wallet/:economyKey/debit

Atomically decrement a wallet balance.

Requires `X-Player-Secret`. 409 `conflict` on insufficient balance. Credit is intentionally NOT exposed on the SDK surface; only the server API can mint balance (so a leaked SDK key can't print money).

Path parameters

FieldTypeDescription
externalIdrequiredstring
economyKeyrequiredstring

Request body (required)

FieldTypeDescription
amountrequiredinteger
reasonstring
idempotencyKeystring

Responses

  • 200New balance after the decrement.DebitWalletResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/wallet/:economyKey/progress

Push progress into a client-writable progression resource.

The client-authoritative counterpart to the server API's `wallet/credit`: lets the GAME add progress to a progression resource it owns (XP from a finished run, distance travelled, stars collected) without a studio backend in the loop. Gated three ways, because letting a client raise its own balance is a deliberate trade: 1. the resource must be `kind: progression` — spendable currencies stay server-only; 2. it must be flagged **client-writable** in the dashboard (off by default); 3. normal SDK auth: API key + `X-Player-Secret` + `idempotencyKey`. Anything DERIVED from this resource moves with it in the same transaction, and each level crossed pays its configured reward — so one call can return `derived: [{ economyKey: "level", previous: 3, current: 5, grantIds: [...] }]`. Errors: 403 `forbidden` when the resource is a currency or not client-writable; 409 `conflict` when the resource is itself derived (write its SOURCE instead) or the balance would go negative.

Path parameters

FieldTypeDescription
externalIdrequiredstring
economyKeyrequiredstring

Request body (required)

FieldTypeDescription
amountrequiredinteger
reasonstring
idempotencyKeystring

Responses

  • 200New balance, plus any derived items that moved with it.ProgressWalletResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/inventory/stream

Subscribe to live inventory / wallet / grant changes (SSE).

Opens a persistent `text/event-stream` carrying everything that touches this player's items, wallet, and grants — regardless of who caused it: the client itself, the studio backend, an operator granting from the dashboard, or the engine paying out an event reward or a level-up. Without it, a game only learned about server-side changes by polling, so a dashboard grant appeared to do nothing until the next app launch. Event types: - `ready`: sent once when the subscription is wired (`{ externalPlayerId }`). - `inventory_changed`: `{ itemKey, delta, quantity, reason, origin, ledgerId, occurredAt }`. - `wallet_changed`: `{ economyKey, delta, balance, reason, origin, ledgerId, occurredAt }`. - `grant_created`: `{ grantId, grantKind, sourceKind, contents, occurredAt }`. `origin` is one of `client` / `server` / `admin` / `engine`, so a client can ignore the echo of its own writes. Treat each event as "refresh this"; the REST reads stay authoritative. SSE comment heartbeats (`:`-prefixed) arrive every 15s; ignore them. Requires `X-Player-Secret`.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200SSE stream open. Body is `text/event-stream`.
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse

Purchases

post/players/:externalId/purchases

Record a real-money purchase.

Requires `X-Player-Secret`. Idempotent on `transactionId` — the store issues it, so a replay (retry, restore, relaunch) records nothing new and returns the original row with `deduplicated: true`. Note there is no `idempotencyKey`: `transactionId` IS the key. `amountMinor` is the currency's minor units as charged; the response also carries `normalizedAmountMinor` in USD cents, which is what spend thresholds compare against. 400 `unknown_currency` if no FX rate is on file for `currency`. Write-only: there is no client-facing spend read.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Request body (required)

FieldTypeDescription
transactionIdrequiredstring
storerequired"app_store" | "google_play" | "steam" | "epic" | "amazon" | "microsoft" | "playstation" | "nintendo" | "web" | "other"
productIdrequiredstring
productType"consumable" | "non_consumable" | "subscription"
amountMinorrequiredinteger
currencyrequiredstring
receiptstring
purchasedAtstring
metadataobject

Responses

  • 200The stored purchase plus the player's post-purchase lifetime total.TrackPurchaseResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse

Catalog

get/catalog

Read the game's items + currencies catalog.

Single-shot read of every item + currency configured for the calling game. Studios call this once at boot and cache locally; it pairs with `events.listForPlayer` (which inlines reward-bundle previews) to render the full game UI without a parallel client-side catalog. Game is derived from the API key.

Responses

  • 200Items + currencies for the calling game.CatalogResponse
  • 401Missing or invalid API key.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse

Gifts

get/players/:externalId/friends/gifts/catalog

What this player may gift, and how often.

The studio's gifting allowlist — every live catalog row a designer flagged giftable — plus the game's cooldown and daily-limit configuration and how many gifts the caller has already sent in the last 24h. Everything a gift picker needs in one call. `type: 'currency'` covers progression items (XP) as well as spendable currencies. Returns `403 gifting_disabled` when the game hasn't enabled gifting. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

  • 200The gifting allowlist + limits.GiftCatalogResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/friends/gifts

The player's gift inbox.

Gifts this player received, newest first, each with the sender's identity and the delivering grant's status. Pass `?status=pending` for just the unclaimed ones, and `?limit=` (1–200, default 50). Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
status"pending"
limitinteger

Responses

  • 200Received gifts.GiftListResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/friends/gifts

Send a gift to a friend.

Sends an item or economy resource to an accepted friend. The catalog decides what may travel: `resourceKey` must name a live row flagged giftable, and `amount` must be within that row's `giftMaxAmount`. When the row is configured to cost the sender, their own balance is debited in the same transaction (which requires platform-managed inventory). Delivery is a PENDING grant on the recipient: unlike other rewards it does NOT deposit on creation, so the gift stays unopened until claimed via `POST .../friends/gifts/{giftId}/claim` (or the generic grant-claim endpoint). Refusals: `403 gifting_disabled`, `403 not_friends`, `403 gift_not_allowed`, `400 gift_amount_invalid`, `429 gift_cooldown`, `429 gift_limit_reached`, `409 gift_insufficient_balance`. Pass `idempotencyKey` so a retry returns the original gift instead of tripping the cooldown. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Request body (required)

FieldTypeDescription
friendCodestring
externalPlayerIdstring
typerequired"item" | "currency"
resourceKeyrequiredstring
amountrequiredinteger
messagestring | null
idempotencyKeystring

Responses

  • 201Gift sent (or the original returned, on an idempotent replay).GiftResponse
  • 400Request body failed validation.ErrorResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
get/players/:externalId/friends/gifts/sent

Gifts this player has sent.

The outbox, newest first — useful for showing "waiting to be opened" state and for a client to work out its own per-friend cooldowns. Same `?status=pending` and `?limit=` parameters as the inbox. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
status"pending"
limitinteger

Responses

  • 200Sent gifts.GiftListResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse
post/players/:externalId/friends/gifts/:giftId/claim

Claim a received gift.

Flips the gift's delivering grant to `claimed` and — in a platform-managed game — deposits the contents into the player's inventory / wallet right then, which is the payout a gift grant deliberately deferred. Replays on an already-claimed gift return the same row (idempotent); an expired one returns `409 gift_expired`. Player-secret gated.

Path parameters

FieldTypeDescription
externalIdrequiredstring
giftIdrequiredstring

Responses

  • 200Gift claimed.GiftResponse
  • 401Missing or invalid API key.ErrorResponse
  • 403API key permission set does not allow this action.ErrorResponse
  • 404Resource not found.ErrorResponse
  • 409Conflict (e.g., attempt already finished, lobby still forming).ErrorResponse
  • 429Rate limited. Either the per-player attempt cap was exhausted for the current window, or the per-minute request budget for this bucket (`sdk_read` / `sdk_write` / `server_api`) was exceeded. Responses include `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `Retry-After` headers.ErrorResponse