Kraty
API reference

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. This page is the machine-derived companion — auto-generated from openapi.sdk.json on every build, so it can't drift from the implementation.

Health

Connectivity probes.

get/ping

Cheap auth probe.

Returns 200 if the supplied API key validates. Use as a connectivity smoke test before issuing real SDK calls.

Responses

  • 200Authenticated.PingResponse
  • 401Missing or invalid API key.ErrorResponse

Events

Start and progress event attempts.

get/players/:externalId/events

List events with active windows for a player.

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

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
status"active"

Responses

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

Start an attempt.

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

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring

Request body (required)

FieldTypeDescription
playerContextobject
idempotencyKeystring

Responses

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

Report progress on an active attempt.

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

Path parameters

FieldTypeDescription
externalIdrequiredstring
eventKeyrequiredstring
attemptIdrequiredstring

Request body (required)

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

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

Leaderboards

Read live and finalized leaderboards.

get/leaderboards/:leaderboardId

Read a leaderboard.

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

Path parameters

FieldTypeDescription
leaderboardIdrequiredstring

Query parameters

FieldTypeDescription
limitinteger
includeSelfboolean | null
externalIdstring

Responses

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

Subscribe to live score updates over Server-Sent Events.

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

Path parameters

FieldTypeDescription
leaderboardIdrequiredstring

Responses

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

Grants

Pull, claim, and open reward grants.

get/players/:externalId/pending-grants

List a player's unclaimed grants.

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

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
limitinteger

Responses

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

Claim a grant.

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

Path parameters

FieldTypeDescription
externalIdrequiredstring
grantIdrequiredstring

Request body

FieldTypeDescription
idempotencyKeystring

Responses

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

Open a crate grant.

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

Path parameters

FieldTypeDescription
externalIdrequiredstring
grantIdrequiredstring

Responses

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

Lobbies

Poll matchmaking lobbies between start retries.

get/lobbies/:lobbyId

Poll a lobby waiting to fill.

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

Path parameters

FieldTypeDescription
lobbyIdrequiredstring

Responses

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

Players

post/players/:externalId/register

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

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

Path parameters

FieldTypeDescription
externalIdrequiredstring

Query parameters

FieldTypeDescription
forceboolean | null

Responses

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

Inventory

get/players/:externalId/inventory

List the player's platform-managed inventory.

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

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

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

Atomically decrement an item quantity.

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

Path parameters

FieldTypeDescription
externalIdrequiredstring
itemKeyrequiredstring

Request body (required)

FieldTypeDescription
quantityrequiredinteger
reasonstring
idempotencyKeystring

Responses

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

List the player's wallet entries.

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

Path parameters

FieldTypeDescription
externalIdrequiredstring

Responses

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

Atomically decrement a wallet balance.

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

Path parameters

FieldTypeDescription
externalIdrequiredstring
economyKeyrequiredstring

Request body (required)

FieldTypeDescription
amountrequiredinteger
reasonstring
idempotencyKeystring

Responses

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

Catalog

get/catalog

Read the game's items + currencies catalog.

Single-shot read of every item + currency configured for the calling game. Studios call this once at boot and cache locally — 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