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.
/pingCheap 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
/timeAuthoritative 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
| Field | Type | Description |
|---|---|---|
| timezone | string |
Responses
- 200Server time.TimeResponse
- 400Request body failed validation.ErrorResponse
- 401Missing or invalid API key.ErrorResponse
Events
Start and progress event attempts.
/players/:externalId/eventsList 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| status | "active" |
Responses
- 200List of active events.EventsListResponse
- 400Request body failed validation.ErrorResponse
- 401Missing or invalid API key.ErrorResponse
/players/:externalId/events/:eventKey/startStart 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| eventKeyrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| playerContext | object | |
| idempotencyKey | string |
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
/players/:externalId/events/:eventKey/attempts/:attemptId/progressReport 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| eventKeyrequired | string | |
| attemptIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| moderequired | "increment" | "set" | |
| metricValue | number | |
| metrics | object | |
| occurredAt | string | |
| idempotencyKey | string | |
| eventTeamId | string |
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
/players/:externalId/event-teams/:eventTeamId/membersA 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| eventTeamIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| cursor | string | |
| limit | integer |
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
/players/:externalId/events/:eventKey/teams/matchFind 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| eventKeyrequired | string |
Request body
| Field | Type | Description |
|---|---|---|
| idempotencyKey | string |
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
/players/:externalId/events/:eventKey/partners/invitesList 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| eventKeyrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| 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
/players/:externalId/events/:eventKey/partners/invitesInvite 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| eventKeyrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| externalPlayerId | string | |
| friendCode | string | |
| idempotencyKey | string |
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
/players/:externalId/events/:eventKey/partners/invites/:eventTeamId/acceptAccept 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| eventKeyrequired | string | |
| eventTeamIdrequired | string |
Request body
| Field | Type | Description |
|---|---|---|
| idempotencyKey | string |
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
/players/:externalId/events/:eventKey/partners/invites/:eventTeamId/declineDecline 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| eventKeyrequired | string | |
| eventTeamIdrequired | string |
Request body
| Field | Type | Description |
|---|---|---|
| idempotencyKey | string |
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
/players/:externalId/events/:eventKey/partners/invites/:eventTeamId/cancelCancel 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| eventKeyrequired | string | |
| eventTeamIdrequired | string |
Request body
| Field | Type | Description |
|---|---|---|
| idempotencyKey | string |
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
/players/:externalId/events/:eventKey/partners/randomGet 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| eventKeyrequired | string |
Request body
| Field | Type | Description |
|---|---|---|
| idempotencyKey | string |
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
/players/:externalId/events/:eventKey/partners/suggestionsPartner 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| eventKeyrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| limit | integer |
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.
/leaderboardsList 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
/event-leaderboards/:leaderboardIdRead 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
| Field | Type | Description |
|---|---|---|
| leaderboardIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| limit | integer | |
| progression | string | |
| includeSelf | boolean | null | |
| externalId | string |
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
/event-leaderboards/:leaderboardId/streamSubscribe 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
| Field | Type | Description |
|---|---|---|
| leaderboardIdrequired | string |
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.
/players/:externalId/pending-grantsList 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| limit | integer |
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
/players/:externalId/grantsCreate 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| kind | GrantKind | → GrantKind |
| entriesrequired | SdkGrantEntry[] | |
| expiresAt | string | |
| metadata | object | |
| idempotencyKey | string |
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
/players/:externalId/grants/:grantId/claimClaim 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| grantIdrequired | string |
Request body
| Field | Type | Description |
|---|---|---|
| idempotencyKey | string |
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
/players/:externalId/crates/:grantId/openOpen 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| grantIdrequired | string |
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.
/lobbies/:lobbyIdPoll a lobby waiting to fill.
Used after `/start` returns 202. Once `status=active`, retry `/start` to get an attempt.
Path parameters
| Field | Type | Description |
|---|---|---|
| lobbyIdrequired | string |
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.
/players/:externalId/daily-loginThe 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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.
/players/:externalId/friend-codeGet (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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| progression | string |
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
/players/:externalId/presenceHeartbeat 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body
| Field | Type | Description |
|---|---|---|
| status | string | 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
/players/:externalId/friendsList 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| progression | string |
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
/players/:externalId/friends/searchSearch players by username.
Case-insensitive search over other players' display names within the same game + environment. Each result carries the caller's relationship to that player (none / friends / request pending). Blocked players are omitted. Player-secret gated.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| qrequired | string | |
| limit | integer | |
| progression | string |
Responses
- 200Matching players.FriendSearchResponse
- 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
/players/:externalId/friends/suggestionsSuggest 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| limit | integer | |
| progression | string |
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
/players/:externalId/friends/requestsList 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| progression | string |
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
/players/:externalId/friends/requestsSend 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| friendCode | string | |
| externalPlayerId | string |
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
/players/:externalId/friends/requests/:requestId/acceptAccept an incoming friend request.
Accepts a pending request addressed to the caller, establishing the friendship. Player-secret gated.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| requestIdrequired | string |
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
/players/:externalId/friends/requests/:requestId/declineDecline an incoming friend request.
Declines (deletes) a pending request addressed to the caller. Player-secret gated.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| requestIdrequired | string |
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
/players/:externalId/friends/requests/:requestIdCancel an outgoing friend request.
Cancels (deletes) a pending request the caller sent. Player-secret gated.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| requestIdrequired | string |
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
/players/:externalId/friends/:friendExternalIdRemove a friend.
Ends an existing friendship (both directions). Player-secret gated.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| friendExternalIdrequired | string |
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
/players/:externalId/blocksList blocked players.
Returns the players the caller has blocked. Player-secret gated.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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
/players/:externalId/blocksBlock 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| friendCode | string | |
| externalPlayerId | string |
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
/players/:externalId/blocks/:blockedExternalIdUnblock a player.
Removes a block the caller had placed. Player-secret gated.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| blockedExternalIdrequired | string |
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.
/players/:externalId/guilds/configThe 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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
/players/:externalId/guildsSearch 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| qrequired | string | |
| country | string | |
| limit | integer | |
| offset | integer | 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
/players/:externalId/guildsFound 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| namerequired | string | |
| description | string | null | |
| badge | string | null | |
| country | string | null | |
| joinType | GuildJoinType | → GuildJoinType |
| metadata | object | |
| idempotencyKey | string |
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
/players/:externalId/guilds/recommendedGuilds this player could join.
Guilds with an open slot: those holding the caller's friends first (`friendCount`), then those with the most members seen in the last 7 days, then the fullest; never the caller's own guild or one that kicked them recently. A weighted random sample, so repeated calls vary. `?country=` filters; `?limit=` 1–25 (default 10). Requires `X-Player-Secret`.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| country | string | |
| limit | integer |
Responses
- 200Recommended guilds.RecommendedGuildsResponse
- 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/:externalId/guilds/:guildIdA guild with its roster.
Profile, leader and members (role, tenure, last seen, online, helps this week). Requires `X-Player-Secret`.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| guildIdrequired | string |
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
/players/:externalId/guilds/:guildId/joinJoin 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| guildIdrequired | string |
Request body
| Field | Type | Description |
|---|---|---|
| message | string | null | |
| idempotencyKey | string |
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
/players/:externalId/guild-requestsThe player's pending join requests.
Outgoing requests still waiting for an answer. Requires `X-Player-Secret`.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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
/players/:externalId/guild-requests/:requestIdCancel one of the player's join requests.
204 on success; 409 `conflict` when it was already answered. Requires `X-Player-Secret`.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| requestIdrequired | string |
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
/players/:externalId/guildThe 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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
/players/:externalId/guildEdit 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| name | string | |
| description | string | null | |
| badge | string | null | |
| country | string | null | |
| joinType | GuildJoinType | → GuildJoinType |
| metadata | object | |
| idempotencyKey | string |
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
/players/:externalId/guild/leaveLeave 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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
/players/:externalId/guild/requestsThe guild's pending join requests.
Oldest first. Needs `accept_requests`. Requires `X-Player-Secret`.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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
/players/:externalId/guild/requests/:requestId/acceptAccept 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| requestIdrequired | string |
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
/players/:externalId/guild/requests/:requestId/declineDecline 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| requestIdrequired | string |
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
/players/:externalId/guild/members/:memberExternalId/kickKick 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| memberExternalIdrequired | string |
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
/players/:externalId/guild/members/:memberExternalId/promotePromote 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| memberExternalIdrequired | string |
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
/players/:externalId/guild/members/:memberExternalId/demoteDemote 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| memberExternalIdrequired | string |
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
/players/:externalId/guild/leaderHand leadership to another member.
Leader only. The caller becomes a co-leader. Requires `X-Player-Secret`.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| externalPlayerIdrequired | string | |
| idempotencyKey | string |
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
/players/:externalId/guild/helpThe 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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
/players/:externalId/guild/helpAsk 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| typerequired | "item" | "currency" | |
| resourceKeyrequired | string | |
| amountrequired | integer | |
| idempotencyKey | string |
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
/players/:externalId/guild/help/:requestId/donateDonate 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| requestIdrequired | string |
Request body
| Field | Type | Description |
|---|---|---|
| amount | integer | |
| idempotencyKey | string |
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
/players/:externalId/guild/help/:requestIdCancel your own help request.
Donations already made stay delivered. Requires `X-Player-Secret`.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| requestIdrequired | string |
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
Chat
Chat (add-on): direct messages, groups, guild chat, channels, the live stream.
/players/:externalId/chat/configThe game's chat rules, as this player sees them.
Which kinds are on and how each filters, the public channels, message limits and custom card types, the player's preferences and moderation standing. 403 `chat_disabled` when chat is off (no add-on, no config, or not in this environment). Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Responses
- 200OK.ChatClientConfigResponse
- 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/:externalId/chat/preferencesThe player's chat preferences.
Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Responses
- 200OK.ChatPreferencesResponse
- 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/:externalId/chat/preferencesSave the player's chat preferences.
`profanityFilter`: true / false / null (follow each kind's default). `allowDirectFrom` narrows who may open a direct conversation. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| profanityFilter | boolean | null | |
| allowDirectFrom | "everyone" | "friends" | "nobody" |
Responses
- 200OK.ChatPreferencesResponse
- 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/:externalId/chat/conversationsThe inbox.
Direct, group and guild conversations, most recent first, with unread counts and the last message (resolved for this viewer, blocked players left out). Channels are listed by `/chat/channels`. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| kind | string | |
| limit | integer | null | |
| offset | integer | null |
Responses
- 200OK.ChatConversationListResponse
- 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/:externalId/chat/unreadUnread totals (the badge).
Muted conversations don't count. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Responses
- 200OK.ChatUnreadResponse
- 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/:externalId/chat/directOpen the direct conversation with another player.
Finds or creates it. Refused when blocked either way (`player_blocked`) or when the game / the other player only allows friends (`chat_direct_not_allowed`). The other player sees it once a message is sent. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| externalPlayerId | string | |
| friendCode | string |
Responses
- 200OK.ChatConversationResponse
- 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/:externalId/chat/groupsCreate a group.
The caller becomes the owner. Members must be friends under the `friends` invite policy; size and per-player caps from the config. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| titlerequired | string | |
| externalPlayerIds | string[] | |
| metadata | object |
Responses
- 201OK.ChatConversationDetailResponse
- 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/:externalId/chat/guildThe player's guild conversation.
409 when the player isn't in a guild. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Responses
- 200OK.ChatConversationResponse
- 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/:externalId/chat/channelsEvery public channel.
Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Responses
- 200OK.ChatChannelListResponse
- 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/:externalId/chat/channels/:channelKeyOne public channel.
Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| channelKeyrequired | string |
Responses
- 200OK.ChatConversationResponse
- 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/:externalId/chat/conversations/:conversationIdOne conversation (with members for direct and group).
Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string |
Responses
- 200OK.ChatConversationDetailResponse
- 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/:externalId/chat/conversations/:conversationIdRename / edit a group (owner, admins).
Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| title | string | |
| metadata | object |
Responses
- 200OK.ChatConversationDetailResponse
- 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/:externalId/chat/conversations/:conversationId/settingsThe player's own settings on a conversation.
`mutedUntil` silences notifications (unread still counts but not in `/chat/unread`); `hidden` removes a direct conversation from the inbox until a new message. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| mutedUntil | string | null | |
| hidden | boolean |
Responses
- 200OK.ChatConversationResponse
- 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/:externalId/chat/conversations/:conversationId/leaveLeave a group (or hide a direct conversation).
An owner leaving hands the group to the longest-serving admin, else member; the last member out archives it. Guild chat and channels can't be left. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string |
Responses
- 200OK.ChatLeaveResponse
- 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/:externalId/chat/conversations/:conversationId/membersAdd members to a group (owner, admins).
Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| externalPlayerIdsrequired | string[] |
Responses
- 200OK.ChatConversationDetailResponse
- 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/:externalId/chat/conversations/:conversationId/members/:memberExternalIdRemove a member (lower rank only), or yourself.
Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string | |
| memberExternalIdrequired | string |
Responses
- 200OK.ChatMemberRemoveResponse
- 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/:externalId/chat/conversations/:conversationId/members/:memberExternalId/roleChange a member's role (owner only).
`owner` hands the group over; the old owner becomes an admin. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string | |
| memberExternalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| rolerequired | "owner" | "admin" | "member" |
Responses
- 200OK.ChatConversationDetailResponse
- 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/:externalId/chat/conversations/:conversationId/messagesA page of messages.
Oldest to newest. `before=<seq>` pages back through history; `after=<seq>` catches up (use it after a stream reconnect). Text is resolved for this viewer; blocked players' messages are left out. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| before | integer | null | |
| after | integer | null | |
| limit | integer | null |
Responses
- 200OK.ChatMessagePageResponse
- 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/:externalId/chat/conversations/:conversationId/messagesSend a message.
Text or a game-defined card (`type: custom`). Runs the profanity and link filters, the rate limit, slow mode and the duplicate check (429 with `retryAfterSeconds`). Refused while muted (`chat_muted`) or chat-banned (`chat_banned`). Same `clientMessageId` = same message. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| type | "text" | "custom" | |
| text | string | null | |
| customType | string | |
| payload | object | |
| replyToId | string | |
| clientMessageId | string | Retry-safe: the same id returns the same message. |
Responses
- 201OK.ChatMessageResponse
- 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/:externalId/chat/conversations/:conversationId/messages/:messageIdEdit your own message.
Within the game's `editWindowSeconds` (403 `chat_edit_not_allowed` after it, or when editing is off). Text messages and custom cards' captions. Runs the same filters and rate limit as a send; moderators keep the earlier versions. Readers get a `message_edited` stream event. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string | |
| messageIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| textrequired | string |
Responses
- 200OK.ChatMessageResponse
- 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/:externalId/chat/conversations/:conversationId/messages/:messageIdDelete a message (your own, or any as a group admin / guild officer).
Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string | |
| messageIdrequired | string |
Responses
- 200OK.ChatDeleteResponse
- 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/:externalId/chat/conversations/:conversationId/readMark read up to a sequence number.
Never moves backwards. Direct and group members get a `read` event on the stream. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| seqrequired | integer |
Responses
- 200OK.ChatReadResponse
- 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/:externalId/chat/conversations/:conversationId/typingSay "is typing…".
Published to the stream (throttled to one per 2 s), never stored. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| conversationIdrequired | string |
Responses
- 200OK.ChatOkResponse
- 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
Moderation
Player safety: reports and the player's moderation standing.
/players/:externalId/reportsThe player's own reports and their status.
Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| limit | integer | null |
Responses
- 200OK.MyReportListResponse
- 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/:externalId/reportsReport another player.
Works in every game (chat or not). Point at messages with `conversationId` + `messageIds` (the reported player's, in a conversation you can read): they're snapshotted as evidence. One open report per reporter and target (reporting again adds to it); 20 per reporter per day. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| targetExternalPlayerIdrequired | string | |
| categoryrequired | "spam" | "harassment" | "hate_speech" | "sexual_content" | "violence" | "self_harm" | "cheating" | "impersonation" | "inappropriate_name" | "other" | |
| context | "chat" | "profile" | "guild" | "gameplay" | "other" | |
| comment | string | null | |
| conversationId | string | |
| messageIds | string[] | |
| guildId | string |
Responses
- 201OK.MyReportResponse
- 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/:externalId/moderation/statusThe player's moderation standing.
Mutes, chat bans and unacknowledged warnings in force, with reasons and end times, so the game can explain them. Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Responses
- 200OK.ModerationStatusResponse
- 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/:externalId/moderation/warnings/:restrictionId/acknowledgeAcknowledge a warning.
Requires `X-Player-Secret`; send `X-Kraty-Chat-Filter: on|off` to choose the profanity filter for this player.
Path parameters
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| restrictionIdrequired | string |
Responses
- 200OK.RestrictionResponse
- 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
/players/:externalId/registerMint 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| force | boolean | 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
/players/:externalId/inventoryList 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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
/players/:externalId/inventory/:itemKey/consumeAtomically 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| itemKeyrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| quantityrequired | integer | |
| reason | string | |
| idempotencyKey | string |
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
/players/:externalId/walletList 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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
/players/:externalId/wallet/:economyKey/debitAtomically 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| economyKeyrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| amountrequired | integer | |
| reason | string | |
| idempotencyKey | string |
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
/players/:externalId/wallet/:economyKey/progressPush 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| economyKeyrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| amountrequired | integer | |
| reason | string | |
| idempotencyKey | string |
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
/players/:externalId/inventory/streamSubscribe 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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
/players/:externalId/purchasesRecord 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| transactionIdrequired | string | |
| storerequired | "app_store" | "google_play" | "steam" | "epic" | "amazon" | "microsoft" | "playstation" | "nintendo" | "web" | "other" | |
| productIdrequired | string | |
| productType | "consumable" | "non_consumable" | "subscription" | |
| amountMinorrequired | integer | |
| currencyrequired | string | |
| receipt | string | |
| purchasedAt | string | |
| metadata | object |
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
/catalogRead 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
/players/:externalId/friends/gifts/catalogWhat 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
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
/players/:externalId/friends/giftsThe 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| status | "pending" | |
| limit | integer |
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
/players/:externalId/friends/giftsSend 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Request body (required)
| Field | Type | Description |
|---|---|---|
| friendCode | string | |
| externalPlayerId | string | |
| typerequired | "item" | "currency" | |
| resourceKeyrequired | string | |
| amountrequired | integer | |
| message | string | null | |
| idempotencyKey | string |
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
/players/:externalId/friends/gifts/sentGifts 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string |
Query parameters
| Field | Type | Description |
|---|---|---|
| status | "pending" | |
| limit | integer |
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
/players/:externalId/friends/gifts/:giftId/claimClaim 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
| Field | Type | Description |
|---|---|---|
| externalIdrequired | string | |
| giftIdrequired | string |
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