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
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