> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kinematic.run/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> These are the customer docs for kinematic, a name written in lowercase except at the start of a sentence. Kinematic provides provably fair casino games, served to a casino's site by a game server: a Cloudflare Worker that the kinematic dashboard deploys into the casino's own Cloudflare account.
> Never put SESSION_SECRET or WALLET_SECRET in code, prompts, logs, commits or chat. Read them from environment variables and ask the person you work with to set them. The dashboard's Integration page shows each secret once.
> Values such as lucky-star, luckystar.example, og-rgs-lucky-star.luckystar.workers.dev, games.luckystar.example and player_48213 are examples. Use the casino's own casino ID, game server origin, element tag, session issuer and currencies: the Instructions for your coding agent on the dashboard's Integration page hold them, or ask the person you work with.
> To debug, start at https://docs.kinematic.run/troubleshooting and https://docs.kinematic.run/reference/errors. The wallet contract is at https://docs.kinematic.run/api/wallet.openapi.yaml.
> Sandbox bets are recorded on Solana devnet. Live game servers record nothing on Solana until the audited mainnet program is deployed.

# Balance

> Read the player's balance in one currency. The call changes nothing.

Answer the current balance and revision with `status: "applied"`. See [Balance reads](https://docs.kinematic.run/integrate/wallet.md#balance-reads).


## OpenAPI

````yaml api/wallet.openapi.yaml POST /balance
openapi: 3.1.0
info:
  title: Wallet API
  version: '1.0'
  summary: The three endpoints your wallet implements for your kinematic game server.
  description: >
    In live mode your game server calls your wallet to debit stakes, credit
    payouts and read balances. You implement these endpoints under the wallet
    URL you set in the dashboard's Settings; the game server appends `debit`,
    `credit` or `balance` to it.


    Every call is a `POST` with a JSON body, signed with your `WALLET_SECRET`.
    Every ID is idempotent: the game server retries a call with the same ID and
    the same body until it gets a valid receipt. Amounts, balances and revisions
    are integer strings in the currency's minor units.
  contact:
    name: kinematic
    email: hello@kinematic.run
servers:
  - url: https://wallet.luckystar.example/kinematic
    description: Your wallet URL from Settings. It must use https.
security: []
tags:
  - name: Wallet
    description: Endpoints your wallet answers. Your game server is the caller.
paths:
  /balance:
    post:
      tags:
        - Wallet
      summary: Read a balance
      description: >
        Returns the player's current balance and your wallet's current revision.
        It changes nothing and needs no idempotency history.


        The game server reads a player's balance at most once every 5 seconds,
        plus once after each wallet events hint you send it. Settlements already
        return the post-operation balance.
      operationId: balance
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/Timestamp'
        - $ref: '#/components/parameters/Signature'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BalanceRequest'
            example:
              id: balance_ace41cf2254913a32f4cb1d7f45eb476
              player: player_48213
              currency: USD
              kind: balance
              amount: '0'
              rounds: []
      responses:
        '200':
          description: The current balance.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Receipt'
              example:
                id: balance_ace41cf2254913a32f4cb1d7f45eb476
                status: applied
                balance: '102400'
                revision: '42'
                currency: USD
        default:
          $ref: '#/components/responses/Ambiguous'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      description: Equals the body's `id`.
      schema:
        type: string
        examples:
          - batch_3a787ce18225e69054f0bfbe34e909d7
    Timestamp:
      name: X-Kinematic-Timestamp
      in: header
      required: true
      description: >
        When the game server signed this attempt, in Unix milliseconds. Refuse a
        call whose timestamp is more than 60 seconds from your clock. A retry
        carries a fresh timestamp.
      schema:
        type: string
        pattern: ^[0-9]{13}$
        examples:
          - '1793629805120'
    Signature:
      name: X-Kinematic-Signature
      in: header
      required: true
      description: >
        Lowercase hex HMAC-SHA256, keyed with your `WALLET_SECRET`, over the
        exact UTF-8 bytes of `timestamp + "." + body`. Compare it in constant
        time before you parse the body, and refuse the call with a status other
        than 200 when it does not match.
      schema:
        type: string
        pattern: ^[0-9a-f]{64}$
        examples:
          - 0315897c76ddcf819b7603a809501ff9ef1dd518187448e6d41597b6d4b7a021
  schemas:
    BalanceRequest:
      type: object
      required:
        - id
        - player
        - currency
        - kind
        - amount
        - rounds
      properties:
        id:
          type: string
          pattern: ^balance_[0-9a-f]{32}$
        player:
          $ref: '#/components/schemas/PlayerId'
        currency:
          $ref: '#/components/schemas/Currency'
        kind:
          type: string
          const: balance
        amount:
          type: string
          const: '0'
        rounds:
          type: array
          maxItems: 0
          items:
            $ref: '#/components/schemas/BetId'
    Receipt:
      type: object
      required:
        - id
        - status
        - balance
        - revision
        - currency
      properties:
        id:
          type: string
          description: The request's `id`.
        status:
          type: string
          enum:
            - applied
            - declined
          description: >-
            `declined` only for a debit the player cannot cover. Credits and
            balance reads are always `applied`.
        balance:
          $ref: '#/components/schemas/MinorUnits'
          description: The player's balance after this operation, in minor units.
        revision:
          $ref: '#/components/schemas/MinorUnits'
          description: >
            Your wallet-wide revision after this operation. It increases with
            every change to the account, including changes outside kinematic.
            Two different balances never share a revision.
        currency:
          $ref: '#/components/schemas/Currency'
          description: The request's `currency`.
    PlayerId:
      type: string
      description: Your stable player ID, the `sub` of the session token.
      pattern: ^[A-Za-z0-9_-]{1,128}$
      examples:
        - player_48213
    Currency:
      type: string
      description: The currency code. Each currency is a separate account of the player.
      pattern: ^[A-Z0-9]{2,12}$
      examples:
        - USD
    BetId:
      type: string
      description: >-
        A bet ID, chosen by the player's browser. The element uses 32 lowercase
        hex characters.
      pattern: ^[A-Za-z0-9_-]{16,80}$
      examples:
        - 1eff8f3759107f88d5d63eaf980a9459
    MinorUnits:
      type: string
      description: >-
        A canonical non-negative integer string in the currency's minor units.
        No decimals, signs or leading zeros.
      pattern: ^(0|[1-9][0-9]{0,18})$
      examples:
        - '9900'
  responses:
    Ambiguous:
      description: >
        Any status other than 200, a timeout after 8 seconds, a redirect, a body
        that is not a JSON object of at most 16 KiB, or a receipt whose `id`,
        `currency` or amounts do not match: the game server cannot tell whether
        the call applied. It keeps the job and sends the same ID and body again
        after 1, 2, 4 and up to 30 seconds. It never treats such an answer as a
        declined debit.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.