{
  "openapi": "3.1.0",
  "info": {
    "title": "Snowball Casino Partner API",
    "version": "0.1.0",
    "summary": "Transfer-wallet integration for operators.",
    "description": "Snowball Casino Partner API, **v0.1** (2026-10-06). Transfer-wallet model: you keep the player's real balance;\nto play, your server moves chips **in** to the Snowball wallet, and moves them **out** when the player is done.\nSnowball is only responsible for the integer chips inside the wallet.\n\n## Conventions\n\n* **Money** is always an **integer number of chips** (no decimals, no currency conversion; what one chip is worth is\n  your decision). `amount` must be a positive integer up to `9007199254740991`.\n* **Format**: JSON, UTF-8, `Content-Type: application/json`. Timestamps are **epoch milliseconds (UTC)**.\n  Day boundaries (reports, daily limits) are **UTC+8**.\n* **Request size** at most 64 KB (batch player creation at most 200 players).\n* **Pagination** is cursor based: `?limit=1..200` (default 50) and `&cursor=<opaque>`. Responses are\n  `{ \"items\": [...], \"nextCursor\": null | \"...\" }`, ordered by time ascending with a stable id tiebreak.\n* **Response headers**: every response carries `X-Trace-Id` (quote it when asking us for help) and rate-limit headers.\n* **IDs**: `playerId` is the Snowball id (always starts with `u_`, never changes). `externalPlayerId` is *your* player\n  number (must **not** start with `u_`). Everywhere a path says `{playerId}` you may pass either; the server first\n  matches `playerId` exactly, then `externalPlayerId`.\n* **Errors**: HTTP status plus `{ \"error\": \"<code>\", \"message\": \"...\", \"traceId\": \"...\" }`. Programs must only\n  switch on `error`; `message` is an English hint and may change.\n\n## Authentication (HMAC-SHA256)\n\nEvery request to this API is signed. See the **Signing** section on the documentation home page for the exact\nalgorithm, test vectors and Node / PHP code. Required headers: `X-Partner-Id`, `X-Key-Id`, `X-Timestamp`,\n`X-Nonce`, `X-Signature`.\n\nServer-side checks, in order: IP allow-list (403 `ip_not_allowed`, before the signature is looked at) → partner/key\nexists and is enabled → timestamp within 5 minutes → constant-time signature check → nonce recorded (5-minute TTL,\na bad signature does not consume a nonce) → rate limit. Authentication failures are all answered `401` without\nsaying which part failed, except `timestamp_out_of_window` and `replay`.\n\n## Idempotency (transfers)\n\n`requestId` (1-64 chars, `[A-Za-z0-9_.:-]`) is unique **per partner, forever**.\n\n* Same `requestId` + same player / direction / amount → the **original result** again, `replayed: true`, HTTP 200,\n  no money moves twice.\n* Same `requestId` + different parameters → `409 idempotency_conflict`, no money moves.\n* Timeout / 5xx / dropped connection: **retry with the same `requestId`**, or look it up with\n  `GET /transfers/{requestId}` (`completed` or `not_found`; there is no visible \"in progress\" state, and the lookup is\n  consistent within 60 seconds even in a crash window).\n* Business errors (`insufficient`, `seated`, ...) do **not** burn the `requestId`: once the condition is met you may\n  retry with the same one. Only a successfully completed transfer locks its parameters.\n\n## Rate limits\n\n| Scope | Default |\n|---|---|\n| Per partner, total | 50 req/s, burst 100 |\n| Transfers in / out | 20 req/s per partner; 5 req/s per player |\n| History / reports | 10 req/s per partner, `limit` at most 200 |\n| Launch exchange (browser) | 20 per minute per IP |\n\nOver the limit: `429 rate_limited` with `Retry-After` (seconds). Headers: `X-RateLimit-Limit`,\n`X-RateLimit-Remaining`, `X-RateLimit-Reset` (epoch seconds).\n\n## Browser-side endpoint (not part of the 23, unsigned)\n\n`POST https://play.snowballcsn.app/api/launch/exchange` with `{ \"launchToken\": \"lt_...\" }` turns a launch token into a\nnormal player session (`{ token, expiresAt, uid, partnerId }`). The Snowball web app calls it for you when the browser\nlands on the `launchUrl`; you normally never call it yourself.\n",
    "contact": {
      "name": "Snowball Casino partner integration"
    },
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://partner-api-sandbox.snowballcsn.app/v1",
      "description": "Sandbox (fake chips, separate tenant, separate keys)"
    },
    {
      "url": "https://partner-api.snowballcsn.app/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "SnowballHmac": []
    }
  ],
  "tags": [
    {
      "name": "System",
      "description": "Connectivity and clock check."
    },
    {
      "name": "Players",
      "description": "Create, find and suspend players. Explicit creation is optional; `POST /launch` with an `externalPlayerId` creates the player on first use."
    },
    {
      "name": "Launch",
      "description": "One-time launch tokens that put a player's browser straight into the game."
    },
    {
      "name": "Wallet",
      "description": "Move chips in and out, read the balance and look up transfers."
    },
    {
      "name": "History",
      "description": "Wallet ledger and per-round bets and net results."
    },
    {
      "name": "Reports",
      "description": "Reconciliation totals, realized RTP and rake."
    },
    {
      "name": "Settings",
      "description": "Operator-controlled limits, bot mode and Texas table types."
    },
    {
      "name": "Webhook",
      "description": "Optional signed event delivery from Snowball to you."
    },
    {
      "name": "Sandbox",
      "description": "Only exists on the sandbox host."
    }
  ],
  "paths": {
    "/ping": {
      "get": {
        "x-endpoint-no": 1,
        "operationId": "ping",
        "tags": [
          "System"
        ],
        "summary": "Check signature and clock",
        "description": "Verifies that your signature, key and IP allow-list work and returns the server clock.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/ping' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273601000' \\\n  -H 'X-Nonce: n01a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 51956529db7782e6d9eb83466cfc4a203bf81f6f4403c13f8ae105dba6bfd7a8'\n```\n",
        "responses": {
          "200": {
            "description": "Signature accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PingResponse"
                },
                "example": {
                  "ok": true,
                  "serverTime": 1791273600123,
                  "partnerId": 12,
                  "env": "sandbox"
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273601000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n01a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "51956529db7782e6d9eb83466cfc4a203bf81f6f4403c13f8ae105dba6bfd7a8"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/ping' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273601000' \\\n  -H 'X-Nonce: n01a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 51956529db7782e6d9eb83466cfc4a203bf81f6f4403c13f8ae105dba6bfd7a8'"
          }
        ]
      }
    },
    "/players": {
      "post": {
        "x-endpoint-no": 2,
        "operationId": "createPlayer",
        "tags": [
          "Players"
        ],
        "summary": "Create a player (optional)",
        "description": "Pre-registers a player. You do not need this: `POST /launch` with an `externalPlayerId` creates the player on\nfirst use.\n\n* `externalPlayerId` is unique inside your partner account and is the idempotency key: creating the same one again\n  returns the existing player with `created: false` (`requestId` is only logged).\n* `username` omitted or `null` → generated as your partner prefix plus a 4-6 digit sequence (for example `ab0001`).\n  A custom `username` must match `^[a-z0-9_]{3,24}$`, must carry your partner prefix (enforced) and must be\n  unique site-wide (`409 username_taken`).\n* `displayName` (at most 16 chars) is shown at the table; defaults to the username. `lang` is stored only.\n* **No password is issued.** Partner players cannot use the normal login (`403 partner_login_only`); they only\n  enter through launch tokens.\n* Daily bonus is **off** by default for partner players (you can turn it on in `PUT /limits`).\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273603000' \\\n  -H 'X-Nonce: n03a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: e7b47520385f39612fedeca8a3243d0c3170ab5fe6f4208f51b47bc30dd4ee7c' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"requestId\":\"reg-88421\",\"externalPlayerId\":\"ops-user-88421\",\"username\":null,\"displayName\":\"Alex\",\"lang\":\"en\",\"validDays\":null}'\n```\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePlayerRequest"
              },
              "example": {
                "requestId": "reg-88421",
                "externalPlayerId": "ops-user-88421",
                "username": null,
                "displayName": "Alex",
                "lang": "en",
                "validDays": null
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Player created (or already existing, see `created`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatePlayerResponse"
                },
                "example": {
                  "created": true,
                  "playerId": "u_9f3c1a2b7d4e5f6a8b90",
                  "username": "ab0001",
                  "externalPlayerId": "ops-user-88421",
                  "status": "active",
                  "balance": 0,
                  "createdAt": 1791273600000
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`insufficient`, `seated`, `idempotency_conflict`, `username_taken`, `player_suspended`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "username_taken": {
                    "summary": "Username already used",
                    "value": {
                      "error": "username_taken",
                      "message": "username is already taken",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273603000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n03a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "e7b47520385f39612fedeca8a3243d0c3170ab5fe6f4208f51b47bc30dd4ee7c"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273603000' \\\n  -H 'X-Nonce: n03a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: e7b47520385f39612fedeca8a3243d0c3170ab5fe6f4208f51b47bc30dd4ee7c' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"requestId\":\"reg-88421\",\"externalPlayerId\":\"ops-user-88421\",\"username\":null,\"displayName\":\"Alex\",\"lang\":\"en\",\"validDays\":null}'"
          }
        ]
      },
      "get": {
        "x-endpoint-no": 5,
        "operationId": "listPlayers",
        "tags": [
          "Players"
        ],
        "summary": "List and search players",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273602000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n02a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "85993b95bf001154ad7d49f44e6eb689e97632df83a0f4713eda8c93a77a0cae"
          },
          {
            "name": "q",
            "in": "query",
            "description": "Substring match on username / display name.",
            "schema": {
              "type": "string",
              "maxLength": 64
            }
          },
          {
            "name": "externalPlayerId",
            "in": "query",
            "description": "Exact match.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/PlayerStatus"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of players.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlayerPage"
                },
                "example": {
                  "items": [
                    {
                      "playerId": "u_9f3c1a2b7d4e5f6a8b90",
                      "username": "ab0001",
                      "externalPlayerId": "ops-user-88421",
                      "displayName": "Alex",
                      "status": "active",
                      "balance": 1500000,
                      "seated": true,
                      "currentTable": "newbie-show-6",
                      "lastLoginAt": 1791273500000,
                      "createdAt": 1791273000000
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/players?limit=50' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273602000' \\\n  -H 'X-Nonce: n02a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 85993b95bf001154ad7d49f44e6eb689e97632df83a0f4713eda8c93a77a0cae'\n```\n",
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/players?limit=50' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273602000' \\\n  -H 'X-Nonce: n02a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 85993b95bf001154ad7d49f44e6eb689e97632df83a0f4713eda8c93a77a0cae'"
          }
        ]
      }
    },
    "/players/batch": {
      "post": {
        "x-endpoint-no": 3,
        "operationId": "createPlayersBatch",
        "tags": [
          "Players"
        ],
        "summary": "Create up to 200 players",
        "description": "Send either `count` (auto-numbered usernames, optional `prefix`) or an explicit `players` list. Re-sending the same\n`batchId` returns the same result without creating anything new.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players/batch' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273604000' \\\n  -H 'X-Nonce: n04a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 255db1d972344c9c08707a515bd48cd92917ee9da033bf5b90f3b273aa6f8b34' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"batchId\":\"batch-2026-10-06-a\",\"players\":[{\"externalPlayerId\":\"ops-user-1001\",\"displayName\":\"Mia\"},{\"externalPlayerId\":\"ops-user-1002\"}]}'\n```\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              },
              "examples": {
                "explicit": {
                  "summary": "Explicit list",
                  "value": {
                    "batchId": "batch-2026-10-06-a",
                    "players": [
                      {
                        "externalPlayerId": "ops-user-1001",
                        "displayName": "Mia"
                      },
                      {
                        "externalPlayerId": "ops-user-1002"
                      }
                    ]
                  }
                },
                "counted": {
                  "summary": "Auto-numbered",
                  "value": {
                    "batchId": "batch-2026-10-06-b",
                    "count": 50,
                    "validDays": null
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The players of the batch (same body on replay).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                },
                "example": {
                  "items": [
                    {
                      "playerId": "u_11aa22bb33cc44dd55ee",
                      "username": "ab0002",
                      "externalPlayerId": "ops-user-1001"
                    },
                    {
                      "playerId": "u_66ff77aa88bb99cc00dd",
                      "username": "ab0003",
                      "externalPlayerId": "ops-user-1002"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`insufficient`, `seated`, `idempotency_conflict`, `username_taken`, `player_suspended`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "idempotency_conflict": {
                    "summary": "batchId reused with different content",
                    "value": {
                      "error": "idempotency_conflict",
                      "message": "batchId was already used with different parameters",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273604000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n04a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "255db1d972344c9c08707a515bd48cd92917ee9da033bf5b90f3b273aa6f8b34"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players/batch' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273604000' \\\n  -H 'X-Nonce: n04a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 255db1d972344c9c08707a515bd48cd92917ee9da033bf5b90f3b273aa6f8b34' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"batchId\":\"batch-2026-10-06-a\",\"players\":[{\"externalPlayerId\":\"ops-user-1001\",\"displayName\":\"Mia\"},{\"externalPlayerId\":\"ops-user-1002\"}]}'"
          }
        ]
      }
    },
    "/players/{playerId}": {
      "get": {
        "x-endpoint-no": 4,
        "operationId": "getPlayer",
        "tags": [
          "Players"
        ],
        "summary": "Player detail",
        "description": "Status, balance, whether the player is seated, and last login.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273605000' \\\n  -H 'X-Nonce: n05a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: d6b2af02790276126df194a282dbec064bbb199013f9b32ea0b1237b1e4443a4'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273605000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n05a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "d6b2af02790276126df194a282dbec064bbb199013f9b32ea0b1237b1e4443a4"
          },
          {
            "$ref": "#/components/parameters/PlayerRef"
          }
        ],
        "responses": {
          "200": {
            "description": "The player.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Player"
                },
                "example": {
                  "playerId": "u_9f3c1a2b7d4e5f6a8b90",
                  "username": "ab0001",
                  "externalPlayerId": "ops-user-88421",
                  "displayName": "Alex",
                  "status": "active",
                  "balance": 1500000,
                  "seated": true,
                  "currentTable": "newbie-show-6",
                  "lastLoginAt": 1791273500000,
                  "createdAt": 1791273000000
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273605000' \\\n  -H 'X-Nonce: n05a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: d6b2af02790276126df194a282dbec064bbb199013f9b32ea0b1237b1e4443a4'"
          }
        ]
      }
    },
    "/players/{playerId}/status": {
      "post": {
        "x-endpoint-no": 6,
        "operationId": "setPlayerStatus",
        "tags": [
          "Players"
        ],
        "summary": "Suspend or restore a player",
        "description": "Suspending also kicks the player off the table and closes the session. Naturally idempotent.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/status' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273606000' \\\n  -H 'X-Nonce: n06a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 55cbc4365c60c34c0932efc8a13a79494cacb3821ce6f55fcd5e6ab4547fdfe0' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"status\":\"suspended\"}'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273606000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n06a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "55cbc4365c60c34c0932efc8a13a79494cacb3821ce6f55fcd5e6ab4547fdfe0"
          },
          {
            "$ref": "#/components/parameters/PlayerRef"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "status"
                ],
                "properties": {
                  "status": {
                    "$ref": "#/components/schemas/PlayerStatus"
                  }
                }
              },
              "example": {
                "status": "suspended"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "New status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "playerId",
                    "status"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "playerId": {
                      "type": "string"
                    },
                    "status": {
                      "$ref": "#/components/schemas/PlayerStatus"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "playerId": "u_9f3c1a2b7d4e5f6a8b90",
                  "status": "suspended"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/status' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273606000' \\\n  -H 'X-Nonce: n06a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 55cbc4365c60c34c0932efc8a13a79494cacb3821ce6f55fcd5e6ab4547fdfe0' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"status\":\"suspended\"}'"
          }
        ]
      }
    },
    "/players/{playerId}/kick": {
      "post": {
        "x-endpoint-no": 8,
        "operationId": "kickPlayer",
        "tags": [
          "Players"
        ],
        "summary": "Force the player off the table",
        "description": "Immediately disconnects the player and stands them up. Chips that were on the table are returned to the wallet\n(shortly afterwards), after which they can be transferred out. Naturally idempotent. Use this when\n`transfer-out` answered `409 seated`.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/kick' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273607000' \\\n  -H 'X-Nonce: n07a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 72cf7ab9bc93fe5c45fa618c5aceb0e0c05627216bd11af9603d1d5afaaa8228'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273607000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n07a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "72cf7ab9bc93fe5c45fa618c5aceb0e0c05627216bd11af9603d1d5afaaa8228"
          },
          {
            "$ref": "#/components/parameters/PlayerRef"
          }
        ],
        "responses": {
          "200": {
            "description": "Kicked (also returned when the player was not connected).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "playerId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "playerId": {
                      "type": "string"
                    },
                    "wasSeated": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "playerId": "u_9f3c1a2b7d4e5f6a8b90",
                  "wasSeated": true
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/kick' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273607000' \\\n  -H 'X-Nonce: n07a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 72cf7ab9bc93fe5c45fa618c5aceb0e0c05627216bd11af9603d1d5afaaa8228'"
          }
        ]
      }
    },
    "/launch": {
      "post": {
        "x-endpoint-no": 7,
        "operationId": "launch",
        "tags": [
          "Launch"
        ],
        "summary": "Create a launch token and URL",
        "description": "Your backend calls this, then redirects the player's browser to `launchUrl`. Pass **either** `externalPlayerId` or\n`playerId`. With an `externalPlayerId` that does not exist yet, the player is **created automatically** (upsert;\n`displayName` and `lang` apply, rules as in `POST /players`); the same `externalPlayerId` always maps to the same\nplayer. No password is issued.\n\nOptional `game` (`texas` or `baccarat`): with it, the launch URL goes straight to table selection of that game;\nwithout it the player lands in the Snowball lobby. `tableId` jumps to a specific table.\n\nToken rules: **single use**, default 60 seconds (`ttlSeconds` 10-300), stored only as a SHA-256 hash. Reuse or\nexpiry → `401 launch_token_invalid`. A suspended player → `403 banned`. A new session kicks an older one\n(`kicked: replaced`). Partner sessions last 12 hours without sliding (`sessionHours` in `PUT /limits`, 1-24).\n\n`returnUrl` must be on your allow-listed domains (else `400 bad_return_url`): the game then shows a \"back\" button\nand logout redirects there. The web app may be embedded in an iframe only from your allow-listed domains; a new\nwindow or full-page redirect is recommended.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/launch' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273608000' \\\n  -H 'X-Nonce: n08a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 12fb91fe97d76f39eb52683eb3dfe1c265050faeb2a90887381dc0b6a99a87c6' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"externalPlayerId\":\"ops-user-88421\",\"displayName\":\"Alex\",\"game\":\"baccarat\",\"tableId\":null,\"lang\":\"en\",\"returnUrl\":\"https://ops.example.com/lobby\",\"ttlSeconds\":60}'\n```\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LaunchRequest"
              },
              "example": {
                "externalPlayerId": "ops-user-88421",
                "displayName": "Alex",
                "game": "baccarat",
                "tableId": null,
                "lang": "en",
                "returnUrl": "https://ops.example.com/lobby",
                "ttlSeconds": 60
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token and ready-to-use URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LaunchResponse"
                },
                "example": {
                  "playerId": "u_9f3c1a2b7d4e5f6a8b90",
                  "created": true,
                  "launchToken": "lt_6b1f0c4e2a9d83f7b5c61e0a4d92f3b8c7e15a60d4f2b9e83c7a1d05f6e48b29",
                  "launchUrl": "https://play.snowballcsn.app/?launch=lt_6b1f0c4e2a9d83f7b5c61e0a4d92f3b8c7e15a60d4f2b9e83c7a1d05f6e48b29&game=baccarat&lang=en&ret=https%3A%2F%2Fops.example.com%2Flobby",
                  "expiresAt": 1791273660000
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273608000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n08a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "12fb91fe97d76f39eb52683eb3dfe1c265050faeb2a90887381dc0b6a99a87c6"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/launch' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273608000' \\\n  -H 'X-Nonce: n08a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 12fb91fe97d76f39eb52683eb3dfe1c265050faeb2a90887381dc0b6a99a87c6' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"externalPlayerId\":\"ops-user-88421\",\"displayName\":\"Alex\",\"game\":\"baccarat\",\"tableId\":null,\"lang\":\"en\",\"returnUrl\":\"https://ops.example.com/lobby\",\"ttlSeconds\":60}'"
          }
        ]
      }
    },
    "/players/{playerId}/balance": {
      "get": {
        "x-endpoint-no": 9,
        "operationId": "getBalance",
        "tags": [
          "Wallet"
        ],
        "summary": "Wallet balance",
        "description": "`balance` is the wallet only; chips sitting on a table are not part of it. `seated` is also `true` while a\nbaccarat player has unsettled bets.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/balance' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273609000' \\\n  -H 'X-Nonce: n09a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 6dfa8dc6bbc738eb2e59f38fdb928a3c32590505abf9176d1d0b689a08a975aa'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273609000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n09a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "6dfa8dc6bbc738eb2e59f38fdb928a3c32590505abf9176d1d0b689a08a975aa"
          },
          {
            "$ref": "#/components/parameters/PlayerRef"
          }
        ],
        "responses": {
          "200": {
            "description": "Balance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                },
                "example": {
                  "playerId": "u_9f3c1a2b7d4e5f6a8b90",
                  "balance": 1500000,
                  "seated": true,
                  "currentTable": "newbie-show-6",
                  "asOf": 1791273600123
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/balance' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273609000' \\\n  -H 'X-Nonce: n09a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 6dfa8dc6bbc738eb2e59f38fdb928a3c32590505abf9176d1d0b689a08a975aa'"
          }
        ]
      }
    },
    "/players/{playerId}/transfer-in": {
      "post": {
        "x-endpoint-no": 10,
        "operationId": "transferIn",
        "tags": [
          "Wallet"
        ],
        "summary": "Transfer chips in (you → Snowball)",
        "description": "Credits the player's wallet. Allowed while the player is seated (the chips are available for the next buy-in / bet).\nIdempotent by `requestId`, see the idempotency section in the API description. The transaction id is\ndeterministic: `ptr:{partnerId}:{requestId}`.\n\n`ref` (optional, at most 64 chars) is stored verbatim in the ledger for your reconciliation.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/transfer-in' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273610000' \\\n  -H 'X-Nonce: n10a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 04e1c8d4d9a3673f4d78851a67ff6e6cc20be1675bd8ddc04a700eb76e670418' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"requestId\":\"dep-20261006-0001\",\"amount\":500000,\"ref\":\"ops-order-77\"}'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273610000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n10a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "04e1c8d4d9a3673f4d78851a67ff6e6cc20be1675bd8ddc04a700eb76e670418"
          },
          {
            "$ref": "#/components/parameters/PlayerRef"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransferRequest"
              },
              "example": {
                "requestId": "dep-20261006-0001",
                "amount": 500000,
                "ref": "ops-order-77"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transfer completed (or replayed).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransferResponse"
                },
                "example": {
                  "ok": true,
                  "replayed": false,
                  "transferId": "tin_2c9e51f7a0b3",
                  "txId": "ptr:12:dep-20261006-0001",
                  "requestId": "dep-20261006-0001",
                  "type": "transfer_in",
                  "amount": 500000,
                  "balance": 1500000,
                  "ts": 1791273600000
                }
              }
            }
          },
          "400": {
            "description": "Invalid request. Codes: `bad_request`, `bad_amount`, `amount_out_of_range`, `bad_request_id`, `bad_username`,\n`bad_range`, `bad_limits`, `bad_return_url`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_amount": {
                    "summary": "Not a positive integer",
                    "value": {
                      "error": "bad_amount",
                      "message": "amount must be a positive integer",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "amount_out_of_range": {
                    "summary": "Outside minTransfer/maxTransfer",
                    "value": {
                      "error": "amount_out_of_range",
                      "message": "amount is outside the allowed transfer range",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`insufficient`, `seated`, `idempotency_conflict`, `username_taken`, `player_suspended`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "idempotency_conflict": {
                    "summary": "Same requestId, different parameters",
                    "value": {
                      "error": "idempotency_conflict",
                      "message": "requestId was already used with different parameters",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "player_suspended": {
                    "summary": "Player is suspended",
                    "value": {
                      "error": "player_suspended",
                      "message": "player is suspended; transfers in are not accepted",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/Maintenance"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/transfer-in' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273610000' \\\n  -H 'X-Nonce: n10a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 04e1c8d4d9a3673f4d78851a67ff6e6cc20be1675bd8ddc04a700eb76e670418' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"requestId\":\"dep-20261006-0001\",\"amount\":500000,\"ref\":\"ops-order-77\"}'"
          }
        ]
      }
    },
    "/players/{playerId}/transfer-out": {
      "post": {
        "x-endpoint-no": 11,
        "operationId": "transferOut",
        "tags": [
          "Wallet"
        ],
        "summary": "Transfer chips out (Snowball → you)",
        "description": "Debits the wallet. Send `amount`, or `all: true` to take the entire balance (the response `amount` is the actual\nfigure; a zero balance is `409 insufficient`).\n\n* `409 insufficient`: `amount` is more than the wallet balance (the balance never goes negative).\n* `409 seated`: the player is seated at a Texas table or has an unfinished buy-in, **or has unsettled baccarat\n  bets**. The body carries `retryable: true` and `currentTable`. Either call `POST /players/{playerId}/kick` and\n  retry, or let the player leave the seat in game. **Chips on a table are not wallet balance and cannot be\n  transferred out.**\n* The seated check and the debit are one atomic step, so a bet or buy-in racing with the transfer sees the\n  balance after the debit.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/transfer-out' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273611000' \\\n  -H 'X-Nonce: n11a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 74ab9a6c83c9d7b4c31d5b01a1478de42ef3214625b3a31c45c8b5b4928c0a22' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"requestId\":\"wd-20261006-0042\",\"amount\":200000,\"ref\":\"ops-order-78\"}'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273611000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n11a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "74ab9a6c83c9d7b4c31d5b01a1478de42ef3214625b3a31c45c8b5b4928c0a22"
          },
          {
            "$ref": "#/components/parameters/PlayerRef"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransferOutRequest"
              },
              "examples": {
                "amount": {
                  "value": {
                    "requestId": "wd-20261006-0042",
                    "amount": 200000,
                    "ref": "ops-order-78"
                  }
                },
                "all": {
                  "value": {
                    "requestId": "wd-20261006-0043",
                    "all": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transfer completed (or replayed).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransferResponse"
                },
                "example": {
                  "ok": true,
                  "replayed": false,
                  "transferId": "tout_7d41b9e20c55",
                  "txId": "ptr:12:wd-20261006-0042",
                  "requestId": "wd-20261006-0042",
                  "type": "transfer_out",
                  "amount": 200000,
                  "balance": 1300000,
                  "ts": 1791273700000
                }
              }
            }
          },
          "400": {
            "description": "Invalid request. Codes: `bad_request`, `bad_amount`, `amount_out_of_range`, `bad_request_id`, `bad_username`,\n`bad_range`, `bad_limits`, `bad_return_url`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_amount": {
                    "summary": "Not a positive integer",
                    "value": {
                      "error": "bad_amount",
                      "message": "amount must be a positive integer",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`insufficient` (amount above balance, or `all` on a zero balance), `seated` (seated, unfinished buy-in, or\nunsettled baccarat bets; `retryable: true`), `idempotency_conflict`, `player_suspended`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient": {
                    "summary": "More than the wallet balance",
                    "value": {
                      "error": "insufficient",
                      "message": "amount exceeds wallet balance",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "seated": {
                    "summary": "Seated or unsettled bets",
                    "value": {
                      "error": "seated",
                      "message": "player is seated or has unsettled bets",
                      "traceId": "tr_8c1e0f7a52",
                      "retryable": true,
                      "currentTable": "newbie-show-6"
                    }
                  },
                  "idempotency_conflict": {
                    "summary": "Same requestId, different parameters",
                    "value": {
                      "error": "idempotency_conflict",
                      "message": "requestId was already used with different parameters",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/Maintenance"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/transfer-out' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273611000' \\\n  -H 'X-Nonce: n11a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 74ab9a6c83c9d7b4c31d5b01a1478de42ef3214625b3a31c45c8b5b4928c0a22' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"requestId\":\"wd-20261006-0042\",\"amount\":200000,\"ref\":\"ops-order-78\"}'"
          }
        ]
      }
    },
    "/transfers/{requestId}": {
      "get": {
        "x-endpoint-no": 12,
        "operationId": "getTransfer",
        "tags": [
          "Wallet"
        ],
        "summary": "Look up a transfer by requestId",
        "description": "For reconciliation after a timeout. There is no in-progress state: the transfer either completed or does not exist.\n`not_found` is returned with HTTP 200 and means no transfer with that `requestId` exists for your partner account.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/transfers/dep-20261006-0001' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273612000' \\\n  -H 'X-Nonce: n12a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 0cf2add8a2a2529be7c6778132acaed9697247797c8ea378701a1d1ec2bc2b63'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273612000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n12a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "0cf2add8a2a2529be7c6778132acaed9697247797c8ea378701a1d1ec2bc2b63"
          },
          {
            "name": "requestId",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/RequestId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lookup result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransferLookup"
                },
                "examples": {
                  "completed": {
                    "value": {
                      "status": "completed",
                      "transfer": {
                        "transferId": "tin_2c9e51f7a0b3",
                        "txId": "ptr:12:dep-20261006-0001",
                        "requestId": "dep-20261006-0001",
                        "playerId": "u_9f3c1a2b7d4e5f6a8b90",
                        "type": "transfer_in",
                        "amount": 500000,
                        "balance": 1500000,
                        "ref": "ops-order-77",
                        "ts": 1791273600000
                      }
                    }
                  },
                  "not_found": {
                    "value": {
                      "status": "not_found"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/transfers/dep-20261006-0001' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273612000' \\\n  -H 'X-Nonce: n12a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 0cf2add8a2a2529be7c6778132acaed9697247797c8ea378701a1d1ec2bc2b63'"
          }
        ]
      }
    },
    "/players/{playerId}/transactions": {
      "get": {
        "x-endpoint-no": 13,
        "operationId": "listPlayerTransactions",
        "tags": [
          "History"
        ],
        "summary": "Player wallet ledger",
        "description": "`from` / `to` are epoch ms, half-open `[from, to)`. Default: last 30 days; maximum span 92 days (else\n`400 bad_range`). `amount` is signed from the player's point of view (credits positive, debits negative);\n`balance` is the wallet balance **after** that row and never negative. Texas hand results are not wallet rows (chips\non the table); see `/rounds`.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/transactions?from=1791187200000&limit=50&to=1791273600000&type=transfer_in%2Ctransfer_out' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273613000' \\\n  -H 'X-Nonce: n13a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: ef7a899ce4e4364464e226c2ac0e79f158491bcc13a539c31c19fc5175c1029a'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273613000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n13a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "ef7a899ce4e4364464e226c2ac0e79f158491bcc13a539c31c19fc5175c1029a"
          },
          {
            "$ref": "#/components/parameters/PlayerRef"
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/TxType"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of ledger rows.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionPage"
                },
                "example": {
                  "items": [
                    {
                      "txId": "ptr:12:dep-20261006-0001",
                      "type": "transfer_in",
                      "amount": 500000,
                      "balance": 1500000,
                      "ref": "ops-order-77",
                      "game": null,
                      "ts": 1791273600000
                    },
                    {
                      "txId": "buyin:8841",
                      "type": "buy_in",
                      "amount": -300000,
                      "balance": 1200000,
                      "game": "texas",
                      "ref": "newbie-show-6",
                      "ts": 1791273700000
                    },
                    {
                      "txId": "bacbet:4412-1",
                      "type": "bet",
                      "amount": -50000,
                      "balance": 1150000,
                      "game": "baccarat",
                      "ref": "bac-newbie-1#4412",
                      "ts": 1791273800000
                    },
                    {
                      "txId": "bacpay:4412-1",
                      "type": "payout",
                      "amount": 100000,
                      "balance": 1250000,
                      "game": "baccarat",
                      "ref": "bac-newbie-1#4412",
                      "ts": 1791273820000
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/transactions?from=1791187200000&limit=50&to=1791273600000&type=transfer_in%2Ctransfer_out' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273613000' \\\n  -H 'X-Nonce: n13a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: ef7a899ce4e4364464e226c2ac0e79f158491bcc13a539c31c19fc5175c1029a'"
          }
        ]
      }
    },
    "/players/{playerId}/rounds": {
      "get": {
        "x-endpoint-no": 14,
        "operationId": "listPlayerRounds",
        "tags": [
          "History"
        ],
        "summary": "Bets and net result per round / hand",
        "description": "One row per round, with the **net** (won minus lost) of each.\n\n* **Baccarat**: `bets[]`, `staked`, `returned`, `net = returned - staked`, `result`.\n* **Texas**: `net` is after rake. `staked` / `returned` are `null` (player-versus-player, not meaningful). Hole cards\n  and action detail are **not** exposed through this API.\n* `capped: true` means the round hit the win cap from `PUT /limits` and the payout was truncated.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/rounds?from=1791187200000&limit=50&to=1791273600000' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273614000' \\\n  -H 'X-Nonce: n14a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: e2c6bca059fbd5ee44e15c0cb6e596c1707899c39d588fe0e64c07a4e8abd975'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273614000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n14a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "e2c6bca059fbd5ee44e15c0cb6e596c1707899c39d588fe0e64c07a4e8abd975"
          },
          {
            "$ref": "#/components/parameters/PlayerRef"
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "name": "game",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Game"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of rounds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoundPage"
                },
                "example": {
                  "items": [
                    {
                      "game": "baccarat",
                      "roundId": "bac-newbie-1#4412",
                      "tableId": "bac-newbie-1",
                      "tier": "newbie",
                      "ts": 1791273820000,
                      "bets": [
                        {
                          "type": "player",
                          "amount": 50000
                        },
                        {
                          "type": "playerPair",
                          "amount": 5000
                        }
                      ],
                      "staked": 55000,
                      "returned": 105000,
                      "net": 50000,
                      "capped": false,
                      "result": {
                        "winner": "player",
                        "playerPoints": 8,
                        "bankerPoints": 5
                      }
                    },
                    {
                      "game": "texas",
                      "roundId": "newbie-wait-1-381",
                      "tableId": "newbie-wait-1",
                      "tier": "newbie",
                      "ts": 1791273900000,
                      "staked": null,
                      "returned": null,
                      "net": -12000,
                      "rake": 0,
                      "capped": false,
                      "result": {
                        "showdown": true
                      }
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/players/u_9f3c1a2b7d4e5f6a8b90/rounds?from=1791187200000&limit=50&to=1791273600000' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273614000' \\\n  -H 'X-Nonce: n14a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: e2c6bca059fbd5ee44e15c0cb6e596c1707899c39d588fe0e64c07a4e8abd975'"
          }
        ]
      }
    },
    "/transactions": {
      "get": {
        "x-endpoint-no": 15,
        "operationId": "listTransactions",
        "tags": [
          "History"
        ],
        "summary": "Partner-wide ledger (reconciliation)",
        "description": "Same row shape as the per-player ledger, plus `playerId` and `username`. For daily reconciliation pull only\n`type=transfer_in,transfer_out`.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/transactions?from=1791187200000&limit=50&to=1791273600000&type=transfer_in%2Ctransfer_out' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273615000' \\\n  -H 'X-Nonce: n15a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 0a478e4994c56cfb2bfd9a5b7efc85884337c4d417413a148c033f105ae7bdda'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273615000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n15a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "0a478e4994c56cfb2bfd9a5b7efc85884337c4d417413a148c033f105ae7bdda"
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/TxType"
          },
          {
            "name": "playerId",
            "in": "query",
            "description": "Restrict to one player (`playerId` or `externalPlayerId`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of ledger rows.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerTransactionPage"
                },
                "example": {
                  "items": [
                    {
                      "txId": "ptr:12:dep-20261006-0001",
                      "type": "transfer_in",
                      "amount": 500000,
                      "balance": 1500000,
                      "ref": "ops-order-77",
                      "game": null,
                      "ts": 1791273600000,
                      "playerId": "u_9f3c1a2b7d4e5f6a8b90",
                      "username": "ab0001"
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/transactions?from=1791187200000&limit=50&to=1791273600000&type=transfer_in%2Ctransfer_out' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273615000' \\\n  -H 'X-Nonce: n15a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 0a478e4994c56cfb2bfd9a5b7efc85884337c4d417413a148c033f105ae7bdda'"
          }
        ]
      }
    },
    "/reports/summary": {
      "get": {
        "x-endpoint-no": 16,
        "operationId": "reportSummary",
        "tags": [
          "Reports"
        ],
        "summary": "Daily transfer, turnover and win summary",
        "description": "Per UTC+8 day: transfers in / out, turnover, player win, rake and active players, plus totals.\n\nIdentity for your own checks: `Σ(transferIn − transferOut) = Δ(player wallet total) + Δ(chips at tables)`. The\nresponse includes `walletTotal` and `atTables` so you can verify it.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/reports/summary?from=1791187200000&to=1791273600000' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273616000' \\\n  -H 'X-Nonce: n16a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 01ba580a5b712a668a010867c4580c03394c0f4f7ed94a30cf68f1d03035ba40'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273616000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n16a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "01ba580a5b712a668a010867c4580c03394c0f4f7ed94a30cf68f1d03035ba40"
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "name": "groupBy",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "day"
              ],
              "default": "day"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Summary rows.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SummaryReport"
                },
                "example": {
                  "items": [
                    {
                      "day": "2026-10-06",
                      "transferIn": 5000000,
                      "transferOut": 1200000,
                      "net": 3800000,
                      "turnover": 8200000,
                      "playerWin": -150000,
                      "rake": 18000,
                      "activePlayers": 42
                    }
                  ],
                  "totals": {
                    "transferIn": 5000000,
                    "transferOut": 1200000,
                    "net": 3800000,
                    "turnover": 8200000,
                    "playerWin": -150000,
                    "rake": 18000
                  },
                  "walletTotal": 2600000,
                  "atTables": 1200000
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/reports/summary?from=1791187200000&to=1791273600000' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273616000' \\\n  -H 'X-Nonce: n16a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 01ba580a5b712a668a010867c4580c03394c0f4f7ed94a30cf68f1d03035ba40'"
          }
        ]
      }
    },
    "/reports/rtp": {
      "get": {
        "x-endpoint-no": 23,
        "operationId": "reportRtp",
        "tags": [
          "Reports"
        ],
        "summary": "Realized return and rake",
        "description": "By day, game and Texas table type.\n\n* **Baccarat**: `realizedRTP = returned / staked` over real-player bets, with `n` and `lowSample: true` below 5,000\n  rounds. This is a **measured outcome** and swings heavily on small samples. Rule-defined theoretical values:\n  banker 98.94%, player 98.76%, tie 85.64%.\n* **Texas** has no RTP (player versus player): the row gives `humanNet`, `botNet` and `rake`, and\n  `botNet + humanNet + rake = 0`. On `botsOnly` tables `humanNet` is the players' net result against the bots.\n* `mode` is the bot mode in force for that hand; `day: \"n/a\"` marks hands from before mode tracking.\n* Realized figures are results, **not settings and not promises**.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/reports/rtp?from=1791187200000&to=1791273600000' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273617000' \\\n  -H 'X-Nonce: n17a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 88eb8ea1c64b7feceff8aaadcf40c878c996027cf92259294b07489c110b7fdd'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273617000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n17a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "88eb8ea1c64b7feceff8aaadcf40c878c996027cf92259294b07489c110b7fdd"
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "name": "groupBy",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "day"
              ],
              "default": "day"
            }
          },
          {
            "name": "tableType",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "botsOnly",
                "mixed",
                "all"
              ],
              "default": "all"
            }
          },
          {
            "name": "game",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Game"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Report rows.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RtpReport"
                },
                "example": {
                  "items": [
                    {
                      "day": "2026-10-06",
                      "game": "texas",
                      "tableType": "botsOnly",
                      "mode": "normal",
                      "hands": 1840,
                      "humanStaked": null,
                      "humanNet": -61200,
                      "botNet": 61200,
                      "rake": 0,
                      "realizedReturn": null
                    },
                    {
                      "day": "2026-10-06",
                      "game": "baccarat",
                      "tableType": null,
                      "hands": 912,
                      "staked": 41230000,
                      "returned": 40695000,
                      "realizedRTP": 0.987,
                      "rake": 0,
                      "n": 912,
                      "lowSample": true
                    }
                  ],
                  "totals": {
                    "hands": 2752,
                    "rake": 0
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/reports/rtp?from=1791187200000&to=1791273600000' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273617000' \\\n  -H 'X-Nonce: n17a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 88eb8ea1c64b7feceff8aaadcf40c878c996027cf92259294b07489c110b7fdd'"
          }
        ]
      }
    },
    "/limits": {
      "get": {
        "x-endpoint-no": 17,
        "operationId": "getLimits",
        "tags": [
          "Settings"
        ],
        "summary": "Read operator limits",
        "description": "Every field comes back as `{ value, platformMin, platformMax }`; values you write must lie inside the platform\nbounds. Changes are audit-logged and take effect from the **next round / next bet**; bets already placed are not\naffected.\n\n| Setting | Meaning |\n|---|---|\n| `tiers.{newbie,mid,high}.{minBet,maxBet,sideMax}` | Baccarat table limits and tie/pair side-bet cap per tier. Platform defaults: newbie 1K-50K, mid 5K-500K, high 50K-5M; tie/pair 5K / 50K / 500K. |\n| `tiers.*.{minBuyIn,maxBuyIn}` | Texas buy-in range per tier. |\n| `maxPayoutPerBet` | Cap on the payout (stake included) of one bet. Checked **at bet time**: a stake whose payout would exceed it is rejected `bet_limit` (the player is shown the largest allowed stake). Never silently truncated. |\n| `maxWinPerRound` | Cap on one player's net win in one baccarat/roulette round. Applied **at settlement**; the excess is not paid and the round is flagged `capped: true`. |\n| `maxWinPerDay` | Cap on a player's net win per UTC+8 day. Once reached, later settlements that day are truncated to the remaining headroom and, at zero, new bets are refused `daily_win_cap`. Resets at 00:00 UTC+8. For Texas the cap does not truncate hands; once reached the player cannot make new buy-ins for the rest of the day. |\n| `dailyBonus.{enabled,amount}` | Daily login bonus; off for partner players by default. |\n| `minTransfer`, `maxTransfer` | Allowed transfer size (guards against fat-finger amounts). |\n| `sessionHours` | Partner session length, 1-24, default 12. |\n\n**Not settable**: baccarat / roulette payouts and drawing rules (RTP follows from the rules), Texas shuffling and\ndealing. Attempting to write them is rejected with `bad_limits`.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/limits' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273618000' \\\n  -H 'X-Nonce: n18a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: d9b8d5b3743990f7693ee1a526cb21197ce8b37147ec009819fde2f034f85a40'\n```\n",
        "responses": {
          "200": {
            "description": "Current limits with platform bounds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LimitsView"
                },
                "example": {
                  "tiers": {
                    "newbie": {
                      "minBet": {
                        "value": 1000,
                        "platformMin": 1000,
                        "platformMax": 50000
                      },
                      "maxBet": {
                        "value": 50000,
                        "platformMin": 1000,
                        "platformMax": 50000
                      },
                      "sideMax": {
                        "value": 5000,
                        "platformMin": 1000,
                        "platformMax": 5000
                      }
                    }
                  },
                  "maxPayoutPerBet": {
                    "value": 2000000,
                    "platformMin": 100000,
                    "platformMax": 50000000
                  },
                  "maxWinPerRound": {
                    "value": 5000000,
                    "platformMin": 100000,
                    "platformMax": 100000000
                  },
                  "maxWinPerDay": {
                    "value": 20000000,
                    "platformMin": 100000,
                    "platformMax": 1000000000
                  },
                  "dailyBonus": {
                    "enabled": {
                      "value": false
                    },
                    "amount": {
                      "value": 0,
                      "platformMin": 0,
                      "platformMax": 100000
                    }
                  },
                  "minTransfer": {
                    "value": 1000,
                    "platformMin": 1,
                    "platformMax": 1000000
                  },
                  "maxTransfer": {
                    "value": 100000000,
                    "platformMin": 1000,
                    "platformMax": 9007199254740991
                  },
                  "sessionHours": {
                    "value": 12,
                    "platformMin": 1,
                    "platformMax": 24
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273618000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n18a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "d9b8d5b3743990f7693ee1a526cb21197ce8b37147ec009819fde2f034f85a40"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/limits' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273618000' \\\n  -H 'X-Nonce: n18a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: d9b8d5b3743990f7693ee1a526cb21197ce8b37147ec009819fde2f034f85a40'"
          }
        ]
      },
      "put": {
        "x-endpoint-no": 18,
        "operationId": "putLimits",
        "tags": [
          "Settings"
        ],
        "summary": "Write operator limits",
        "description": "Overwrites the whole limits document with the values sent (omitted fields return to platform defaults).\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X PUT 'https://partner-api-sandbox.snowballcsn.app/v1/limits' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273619000' \\\n  -H 'X-Nonce: n19a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 05324da4ed463bba99c425cc8dde0058a6d3074077990c2f366b0a89a90a465e' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"tiers\":{\"newbie\":{\"minBet\":1000,\"maxBet\":50000,\"sideMax\":5000},\"mid\":{\"minBet\":5000,\"maxBet\":500000,\"sideMax\":50000}},\"maxPayoutPerBet\":2000000,\"maxWinPerRound\":5000000,\"maxWinPerDay\":20000000,\"dailyBonus\":{\"enabled\":false,\"amount\":0},\"minTransfer\":1000,\"maxTransfer\":100000000,\"sessionHours\":12}'\n```\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LimitsWrite"
              },
              "example": {
                "tiers": {
                  "newbie": {
                    "minBet": 1000,
                    "maxBet": 50000,
                    "sideMax": 5000
                  },
                  "mid": {
                    "minBet": 5000,
                    "maxBet": 500000,
                    "sideMax": 50000
                  }
                },
                "maxPayoutPerBet": 2000000,
                "maxWinPerRound": 5000000,
                "maxWinPerDay": 20000000,
                "dailyBonus": {
                  "enabled": false,
                  "amount": 0
                },
                "minTransfer": 1000,
                "maxTransfer": 100000000,
                "sessionHours": 12
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored limits (same shape as GET).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LimitsView"
                },
                "example": {
                  "tiers": {
                    "newbie": {
                      "minBet": {
                        "value": 1000,
                        "platformMin": 1000,
                        "platformMax": 50000
                      },
                      "maxBet": {
                        "value": 50000,
                        "platformMin": 1000,
                        "platformMax": 50000
                      },
                      "sideMax": {
                        "value": 5000,
                        "platformMin": 1000,
                        "platformMax": 5000
                      }
                    }
                  },
                  "maxPayoutPerBet": {
                    "value": 2000000,
                    "platformMin": 100000,
                    "platformMax": 50000000
                  },
                  "maxWinPerRound": {
                    "value": 5000000,
                    "platformMin": 100000,
                    "platformMax": 100000000
                  },
                  "maxWinPerDay": {
                    "value": 20000000,
                    "platformMin": 100000,
                    "platformMax": 1000000000
                  },
                  "dailyBonus": {
                    "enabled": {
                      "value": false
                    },
                    "amount": {
                      "value": 0,
                      "platformMin": 0,
                      "platformMax": 100000
                    }
                  },
                  "minTransfer": {
                    "value": 1000,
                    "platformMin": 1,
                    "platformMax": 1000000
                  },
                  "maxTransfer": {
                    "value": 100000000,
                    "platformMin": 1000,
                    "platformMax": 9007199254740991
                  },
                  "sessionHours": {
                    "value": 12,
                    "platformMin": 1,
                    "platformMax": 24
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273619000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n19a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "05324da4ed463bba99c425cc8dde0058a6d3074077990c2f366b0a89a90a465e"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PUT 'https://partner-api-sandbox.snowballcsn.app/v1/limits' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273619000' \\\n  -H 'X-Nonce: n19a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 05324da4ed463bba99c425cc8dde0058a6d3074077990c2f366b0a89a90a465e' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"tiers\":{\"newbie\":{\"minBet\":1000,\"maxBet\":50000,\"sideMax\":5000},\"mid\":{\"minBet\":5000,\"maxBet\":500000,\"sideMax\":50000}},\"maxPayoutPerBet\":2000000,\"maxWinPerRound\":5000000,\"maxWinPerDay\":20000000,\"dailyBonus\":{\"enabled\":false,\"amount\":0},\"minTransfer\":1000,\"maxTransfer\":100000000,\"sessionHours\":12}'"
          }
        ]
      }
    },
    "/webhook": {
      "get": {
        "x-endpoint-no": 19,
        "operationId": "getWebhook",
        "tags": [
          "Webhook"
        ],
        "summary": "Read webhook settings",
        "description": "See the **Webhook** section on the documentation home page for event shapes, signing and retry policy.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/webhook' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273620000' \\\n  -H 'X-Nonce: n20a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 2dbf915c97363a0d1f54bd7223fa5bc9bc4c7d11c5c7f9e936581db34889796e'\n```\n",
        "responses": {
          "200": {
            "description": "Current settings (the signing secret is never returned here).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSettings"
                },
                "example": {
                  "url": "https://ops.example.com/snowball/hook",
                  "events": [
                    "balance.changed",
                    "transfer.completed"
                  ],
                  "enabled": true,
                  "threshold": 5000000,
                  "coalesceMs": 1000
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273620000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n20a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "2dbf915c97363a0d1f54bd7223fa5bc9bc4c7d11c5c7f9e936581db34889796e"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/webhook' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273620000' \\\n  -H 'X-Nonce: n20a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 2dbf915c97363a0d1f54bd7223fa5bc9bc4c7d11c5c7f9e936581db34889796e'"
          }
        ]
      },
      "put": {
        "x-endpoint-no": 19,
        "operationId": "putWebhook",
        "tags": [
          "Webhook"
        ],
        "summary": "Set webhook URL, events and secret",
        "description": "`url` must be https and publicly reachable. The **first** successful call returns `signingSecret` exactly once;\nsend `resetSecret: true` to rotate it (the new one is again shown once).\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X PUT 'https://partner-api-sandbox.snowballcsn.app/v1/webhook' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273621000' \\\n  -H 'X-Nonce: n21a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 5f6d048e9cdc02f03af9bba4e6bef43114df4df663ce06088dbf4dccc22ea06a' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"url\":\"https://ops.example.com/snowball/hook\",\"events\":[\"balance.changed\",\"transfer.completed\",\"win.big\",\"player.session\"],\"enabled\":true,\"threshold\":5000000,\"coalesceMs\":1000}'\n```\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookWrite"
              },
              "example": {
                "url": "https://ops.example.com/snowball/hook",
                "events": [
                  "balance.changed",
                  "transfer.completed",
                  "win.big",
                  "player.session"
                ],
                "enabled": true,
                "threshold": 5000000,
                "coalesceMs": 1000
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored settings; `signingSecret` only on first set or after `resetSecret`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSettings"
                },
                "example": {
                  "url": "https://ops.example.com/snowball/hook",
                  "events": [
                    "balance.changed",
                    "transfer.completed",
                    "win.big",
                    "player.session"
                  ],
                  "enabled": true,
                  "threshold": 5000000,
                  "coalesceMs": 1000,
                  "signingSecret": "whsec_3f9a0c51d27b4e68a1c3"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273621000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n21a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "5f6d048e9cdc02f03af9bba4e6bef43114df4df663ce06088dbf4dccc22ea06a"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PUT 'https://partner-api-sandbox.snowballcsn.app/v1/webhook' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273621000' \\\n  -H 'X-Nonce: n21a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 5f6d048e9cdc02f03af9bba4e6bef43114df4df663ce06088dbf4dccc22ea06a' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"url\":\"https://ops.example.com/snowball/hook\",\"events\":[\"balance.changed\",\"transfer.completed\",\"win.big\",\"player.session\"],\"enabled\":true,\"threshold\":5000000,\"coalesceMs\":1000}'"
          }
        ]
      }
    },
    "/webhook/test": {
      "post": {
        "x-endpoint-no": 20,
        "operationId": "testWebhook",
        "tags": [
          "Webhook"
        ],
        "summary": "Send a test event",
        "description": "Delivers one signed `webhook.test` event to your configured URL and reports the HTTP status your server gave.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/webhook/test' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273622000' \\\n  -H 'X-Nonce: n22a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 06be7fb91cf850e8b8a2df71de708370babaebfafc7fa6bb442ccbdce05c49fd' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"event\":\"balance.changed\"}'\n```\n",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "description": "Event type to simulate; defaults to `balance.changed`.",
                    "examples": [
                      "balance.changed"
                    ]
                  }
                }
              },
              "example": {
                "event": "balance.changed"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Delivery attempt result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "delivered",
                    "eventId"
                  ],
                  "properties": {
                    "delivered": {
                      "type": "boolean"
                    },
                    "eventId": {
                      "type": "string"
                    },
                    "httpStatus": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Status returned by your endpoint, or null if unreachable."
                    },
                    "durationMs": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "delivered": true,
                  "eventId": "evt_test_01J9Z3K8M2",
                  "httpStatus": 200,
                  "durationMs": 143
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273622000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n22a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "06be7fb91cf850e8b8a2df71de708370babaebfafc7fa6bb442ccbdce05c49fd"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/webhook/test' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273622000' \\\n  -H 'X-Nonce: n22a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 06be7fb91cf850e8b8a2df71de708370babaebfafc7fa6bb442ccbdce05c49fd' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"event\":\"balance.changed\"}'"
          }
        ]
      }
    },
    "/bots/mode": {
      "get": {
        "x-endpoint-no": 21,
        "operationId": "getBotMode",
        "tags": [
          "Settings"
        ],
        "summary": "Read bot mode and schedule",
        "description": "Bot mode is a **playing style only** (`smart`, `normal`, `casual`). It does not change dealing or results and is\n**not an RTP dial**. With no configuration the mode is `normal`.\n\nWindow priority (strongest first): single dates > date range > weekly days > every day > `default`.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/bots/mode' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273623000' \\\n  -H 'X-Nonce: n23a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 9cd8b1c50aabef9828604e10d327ecf9145e59febe4761241c0ae875d6ccc21b'\n```\n",
        "responses": {
          "200": {
            "description": "Rules and the mode in force now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BotModeView"
                },
                "example": {
                  "configured": true,
                  "rules": {
                    "tz": "Asia/Kuala_Lumpur",
                    "switchAt": "00:00",
                    "default": "normal",
                    "windows": [
                      {
                        "days": [
                          5,
                          6
                        ],
                        "from": "20:00",
                        "to": "02:00",
                        "mode": "casual"
                      },
                      {
                        "dates": [
                          "2026-10-10"
                        ],
                        "from": "00:00",
                        "to": "24:00",
                        "mode": "smart"
                      }
                    ]
                  },
                  "override": null,
                  "effective": {
                    "mode": "normal",
                    "scheduled": "normal",
                    "businessDay": "2026-10-06"
                  },
                  "now": 1791273600000
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273623000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n23a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "9cd8b1c50aabef9828604e10d327ecf9145e59febe4761241c0ae875d6ccc21b"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/bots/mode' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273623000' \\\n  -H 'X-Nonce: n23a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 9cd8b1c50aabef9828604e10d327ecf9145e59febe4761241c0ae875d6ccc21b'"
          }
        ]
      },
      "put": {
        "x-endpoint-no": 21,
        "operationId": "putBotMode",
        "tags": [
          "Settings"
        ],
        "summary": "Write bot mode and schedule",
        "description": "Send `rules` (replaces the whole schedule, at most 32 windows), and/or `immediate` (switch now; it lasts at most\n24 hours and ends early when the schedule changes the mode), and/or `clearImmediate: true`. At least one is required.\nTakes effect from the next decision.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X PUT 'https://partner-api-sandbox.snowballcsn.app/v1/bots/mode' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273624000' \\\n  -H 'X-Nonce: n24a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 0363c491d8892345b40207bb0ef72aa06578567f6ef244e996f61e6d96fa1899' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"rules\":{\"tz\":\"Asia/Kuala_Lumpur\",\"switchAt\":\"00:00\",\"default\":\"normal\",\"windows\":[{\"days\":[5,6],\"from\":\"20:00\",\"to\":\"02:00\",\"mode\":\"casual\"}]}}'\n```\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BotModeWrite"
              },
              "examples": {
                "rules": {
                  "value": {
                    "rules": {
                      "tz": "Asia/Kuala_Lumpur",
                      "switchAt": "00:00",
                      "default": "normal",
                      "windows": [
                        {
                          "days": [
                            5,
                            6
                          ],
                          "from": "20:00",
                          "to": "02:00",
                          "mode": "casual"
                        }
                      ]
                    }
                  }
                },
                "immediate": {
                  "value": {
                    "immediate": "smart"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored state (same shape as GET, plus `ok`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BotModeView"
                },
                "example": {
                  "ok": true,
                  "configured": true,
                  "rules": {
                    "tz": "Asia/Kuala_Lumpur",
                    "switchAt": "00:00",
                    "default": "normal",
                    "windows": [
                      {
                        "days": [
                          5,
                          6
                        ],
                        "from": "20:00",
                        "to": "02:00",
                        "mode": "casual"
                      }
                    ]
                  },
                  "override": null,
                  "effective": {
                    "mode": "normal",
                    "scheduled": "normal",
                    "businessDay": "2026-10-06"
                  },
                  "now": 1791273600000
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273624000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n24a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "0363c491d8892345b40207bb0ef72aa06578567f6ef244e996f61e6d96fa1899"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PUT 'https://partner-api-sandbox.snowballcsn.app/v1/bots/mode' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273624000' \\\n  -H 'X-Nonce: n24a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 0363c491d8892345b40207bb0ef72aa06578567f6ef244e996f61e6d96fa1899' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"rules\":{\"tz\":\"Asia/Kuala_Lumpur\",\"switchAt\":\"00:00\",\"default\":\"normal\",\"windows\":[{\"days\":[5,6],\"from\":\"20:00\",\"to\":\"02:00\",\"mode\":\"casual\"}]}}'"
          }
        ]
      }
    },
    "/texas/tables": {
      "get": {
        "x-endpoint-no": 22,
        "operationId": "getTexasTables",
        "tags": [
          "Settings"
        ],
        "summary": "Read Texas table types",
        "description": "Per tier (`newbie`, `mid`, `high`) a table type:\n\n* **`botsOnly`**: your players play only against bots, never with other partners' players. Bot style follows\n  `/bots/mode`. No rake by default (optional). This does **not** set a return rate: bot mode only changes how the\n  bots play, not the deal or the results; the cards come from a verifiable shuffle and bots cannot see anyone's\n  hole cards. Realized results are measured in `/reports/rtp`.\n* **`mixed`**: real players plus bots at the same table, rake collected per `rake{pct,cap,noFlopNoDrop}`, settable per tier.\n\nYour players always sit at their own tables, not shared with other partners.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/texas/tables' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273625000' \\\n  -H 'X-Nonce: n25a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 82c87fb8aad651e056d9f1bbd4f23c9f5245a61878765bfa5126acbf066b43fa'\n```\n",
        "responses": {
          "200": {
            "description": "Current table types.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TexasTables"
                },
                "example": {
                  "tiers": {
                    "newbie": {
                      "type": "botsOnly"
                    },
                    "mid": {
                      "type": "mixed",
                      "rake": {
                        "pct": 5,
                        "cap": 30000,
                        "noFlopNoDrop": true
                      }
                    },
                    "high": {
                      "type": "mixed",
                      "rake": {
                        "pct": 3,
                        "cap": 100000,
                        "noFlopNoDrop": true
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273625000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n25a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "82c87fb8aad651e056d9f1bbd4f23c9f5245a61878765bfa5126acbf066b43fa"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET 'https://partner-api-sandbox.snowballcsn.app/v1/texas/tables' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273625000' \\\n  -H 'X-Nonce: n25a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 82c87fb8aad651e056d9f1bbd4f23c9f5245a61878765bfa5126acbf066b43fa'"
          }
        ]
      },
      "put": {
        "x-endpoint-no": 22,
        "operationId": "putTexasTables",
        "tags": [
          "Settings"
        ],
        "summary": "Write Texas table types",
        "description": "Overwrites the whole document. Applies from the next table that opens / the next hand. Audit-logged.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X PUT 'https://partner-api-sandbox.snowballcsn.app/v1/texas/tables' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273626000' \\\n  -H 'X-Nonce: n26a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: b380911c9d5c9df6a054e9cbb77438cc56be6b68171e78d1cec5436224259884' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"tiers\":{\"newbie\":{\"type\":\"botsOnly\"},\"mid\":{\"type\":\"mixed\",\"rake\":{\"pct\":5,\"cap\":30000,\"noFlopNoDrop\":true}},\"high\":{\"type\":\"mixed\",\"rake\":{\"pct\":3,\"cap\":100000,\"noFlopNoDrop\":true}}}}'\n```\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TexasTables"
              },
              "example": {
                "tiers": {
                  "newbie": {
                    "type": "botsOnly"
                  },
                  "mid": {
                    "type": "mixed",
                    "rake": {
                      "pct": 5,
                      "cap": 30000,
                      "noFlopNoDrop": true
                    }
                  },
                  "high": {
                    "type": "mixed",
                    "rake": {
                      "pct": 3,
                      "cap": 100000,
                      "noFlopNoDrop": true
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored table types.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TexasTables"
                },
                "example": {
                  "tiers": {
                    "newbie": {
                      "type": "botsOnly"
                    },
                    "mid": {
                      "type": "mixed",
                      "rake": {
                        "pct": 5,
                        "cap": 30000,
                        "noFlopNoDrop": true
                      }
                    },
                    "high": {
                      "type": "mixed",
                      "rake": {
                        "pct": 3,
                        "cap": 100000,
                        "noFlopNoDrop": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273626000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n26a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "b380911c9d5c9df6a054e9cbb77438cc56be6b68171e78d1cec5436224259884"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PUT 'https://partner-api-sandbox.snowballcsn.app/v1/texas/tables' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273626000' \\\n  -H 'X-Nonce: n26a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: b380911c9d5c9df6a054e9cbb77438cc56be6b68171e78d1cec5436224259884' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"tiers\":{\"newbie\":{\"type\":\"botsOnly\"},\"mid\":{\"type\":\"mixed\",\"rake\":{\"pct\":5,\"cap\":30000,\"noFlopNoDrop\":true}},\"high\":{\"type\":\"mixed\",\"rake\":{\"pct\":3,\"cap\":100000,\"noFlopNoDrop\":true}}}}'"
          }
        ]
      }
    },
    "/sandbox/players/{playerId}/faucet": {
      "post": {
        "operationId": "sandboxFaucet",
        "tags": [
          "Sandbox"
        ],
        "summary": "Add fake chips (sandbox only)",
        "description": "Exists only on the sandbox host (not part of the 23 production endpoints). Credits any amount of fake chips.\n\nSandbox also accepts the request header `X-Sandbox-Scenario: timeout | 500 | insufficient | seated` on any\nendpoint to force that failure, so you can test your retry and idempotency handling.\n\n**Example request** (signed with the published test secret; header values are real and verifiable with the test vectors on the home page):\n\n```bash\ncurl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/sandbox/players/u_9f3c1a2b7d4e5f6a8b90/faucet' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273627000' \\\n  -H 'X-Nonce: n27a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 1dfe3bb2a831dae2ed7505ef618eeb3b271595dcd26440a8fd20def1865de46c' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"amount\":1000000}'\n```\n",
        "parameters": [
          {
            "name": "X-Partner-Id",
            "in": "header",
            "required": true,
            "description": "Your partner id.",
            "schema": {
              "type": "string"
            },
            "example": "12"
          },
          {
            "name": "X-Key-Id",
            "in": "header",
            "required": true,
            "description": "Key id.",
            "schema": {
              "type": "string"
            },
            "example": "k1"
          },
          {
            "name": "X-Timestamp",
            "in": "header",
            "required": true,
            "description": "Epoch ms; within 5 minutes of our clock.",
            "schema": {
              "type": "string"
            },
            "example": "1791273627000"
          },
          {
            "name": "X-Nonce",
            "in": "header",
            "required": true,
            "description": "16-64 chars, unique for 5 minutes.",
            "schema": {
              "type": "string"
            },
            "example": "n27a1b2c3d4e5f60718293a4b5c6d7e"
          },
          {
            "name": "X-Signature",
            "in": "header",
            "required": true,
            "description": "Hex HMAC-SHA256 of the canonical string (see Signing on the home page). The example value is a real signature of the example request below, made with the published test secret.",
            "schema": {
              "type": "string"
            },
            "example": "1dfe3bb2a831dae2ed7505ef618eeb3b271595dcd26440a8fd20def1865de46c"
          },
          {
            "$ref": "#/components/parameters/PlayerRef"
          },
          {
            "name": "X-Sandbox-Scenario",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "timeout",
                "500",
                "insufficient",
                "seated"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount"
                ],
                "properties": {
                  "amount": {
                    "$ref": "#/components/schemas/Amount"
                  }
                }
              },
              "example": {
                "amount": 1000000
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Credited.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "balance"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "balance": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "balance": 2500000
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "description": "Authentication failed. `bad_signature` (missing header, unknown partner/key, or signature mismatch; not broken\ndown further), `timestamp_out_of_window`, `replay`, `launch_token_invalid`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Signature, key or partner not accepted",
                    "value": {
                      "error": "bad_signature",
                      "message": "signature verification failed",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  },
                  "timestamp_out_of_window": {
                    "summary": "Clock off by more than 5 minutes",
                    "value": {
                      "error": "timestamp_out_of_window",
                      "message": "X-Timestamp is more than 5 minutes from server time",
                      "traceId": "tr_8c1e0f7a52"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST 'https://partner-api-sandbox.snowballcsn.app/v1/sandbox/players/u_9f3c1a2b7d4e5f6a8b90/faucet' \\\n  -H 'X-Partner-Id: 12' \\\n  -H 'X-Key-Id: k1' \\\n  -H 'X-Timestamp: 1791273627000' \\\n  -H 'X-Nonce: n27a1b2c3d4e5f60718293a4b5c6d7e' \\\n  -H 'X-Signature: 1dfe3bb2a831dae2ed7505ef618eeb3b271595dcd26440a8fd20def1865de46c' \\\n  -H 'Content-Type: application/json' \\\n  --data-raw '{\"amount\":1000000}'"
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "SnowballHmac": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Signature",
        "description": "HMAC-SHA256 request signing. Send **all five** headers on every request:\n\n| Header | Value |\n|---|---|\n| `X-Partner-Id` | Your partner id (integer as string) |\n| `X-Key-Id` | Key id (`k1`, `k2`, ...; two keys may be active during rotation) |\n| `X-Timestamp` | Send time, epoch ms. More than 5 minutes off our clock → 401 `timestamp_out_of_window` |\n| `X-Nonce` | 16-64 chars `[A-Za-z0-9_-]`, unique per partner within 5 minutes, else 401 `replay` |\n| `X-Signature` | Lowercase hex of `HMAC_SHA256(secret, canonicalString)` |\n\n`canonicalString` = the following lines joined with `\\n` (no trailing newline):\n`SNOWBALL-HMAC-SHA256-V1`, `partnerId`, `timestamp`, `nonce`, `METHOD` (upper case), `path` (with the `/v1`\nprefix, no query), `canonicalQuery` (keys sorted, then values sorted, `key=value` joined by `&`, RFC 3986\npercent-encoding; empty string if none), `sha256hex(rawBody)` (hash of the empty string when there is no body).\n\nThe secret (64 hex characters) is used as a **UTF-8 string** key, not hex-decoded. Sign the **raw bytes** you send.\nFull algorithm, test vectors and Node / PHP code are on the documentation home page. The \"Authorize\" button in this\nUI cannot compute signatures, so \"Try it out\" is disabled.\n"
      }
    },
    "parameters": {
      "PlayerRef": {
        "name": "playerId",
        "in": "path",
        "required": true,
        "description": "Snowball `playerId` (`u_...`) **or** your `externalPlayerId` (never starts with `u_`).",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64
        },
        "examples": {
          "byPlayerId": {
            "value": "u_9f3c1a2b7d4e5f6a8b90"
          },
          "byExternal": {
            "value": "ops-user-88421"
          }
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        },
        "example": 50
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "description": "Opaque value from the previous page's `nextCursor`.",
        "schema": {
          "type": "string"
        }
      },
      "From": {
        "name": "from",
        "in": "query",
        "description": "Start, epoch ms, inclusive. Default is 30 days before `to`.",
        "schema": {
          "type": "integer",
          "format": "int64"
        },
        "example": 1791187200000
      },
      "To": {
        "name": "to",
        "in": "query",
        "description": "End, epoch ms, exclusive. Default is now. `to - from` may be at most 92 days.",
        "schema": {
          "type": "integer",
          "format": "int64"
        },
        "example": 1791273600000
      },
      "TxType": {
        "name": "type",
        "in": "query",
        "description": "Comma-separated filter of transaction types.",
        "schema": {
          "type": "string"
        },
        "example": "transfer_in,transfer_out"
      }
    },
    "schemas": {
      "ErrorCode": {
        "type": "string",
        "description": "Machine-readable error code. Only this field is stable.",
        "enum": [
          "bad_request",
          "bad_amount",
          "amount_out_of_range",
          "bad_request_id",
          "bad_username",
          "bad_range",
          "bad_limits",
          "bad_return_url",
          "bad_signature",
          "timestamp_out_of_window",
          "replay",
          "launch_token_invalid",
          "ip_not_allowed",
          "partner_disabled",
          "banned",
          "partner_login_only",
          "forbidden_game",
          "player_not_found",
          "transfer_not_found",
          "insufficient",
          "seated",
          "idempotency_conflict",
          "username_taken",
          "player_suspended",
          "payload_too_large",
          "unsupported_media_type",
          "rate_limited",
          "internal",
          "maintenance"
        ]
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message",
          "traceId"
        ],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorCode"
          },
          "message": {
            "type": "string",
            "description": "English hint; not stable."
          },
          "traceId": {
            "type": "string"
          },
          "retryable": {
            "type": "boolean",
            "description": "Present on `seated`."
          },
          "currentTable": {
            "type": "string",
            "description": "Present on `seated`."
          },
          "details": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "Amount": {
        "type": "integer",
        "format": "int64",
        "minimum": 1,
        "maximum": 9007199254740991,
        "description": "Positive integer number of chips."
      },
      "RequestId": {
        "type": "string",
        "pattern": "^[A-Za-z0-9_.:-]{1,64}$",
        "description": "Unique per partner forever."
      },
      "PlayerStatus": {
        "type": "string",
        "enum": [
          "active",
          "suspended"
        ]
      },
      "Game": {
        "type": "string",
        "enum": [
          "texas",
          "baccarat",
          "roulette"
        ],
        "description": "Roulette is listed for forward compatibility and is not included in v1."
      },
      "PingResponse": {
        "type": "object",
        "required": [
          "ok",
          "serverTime",
          "partnerId",
          "env"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "serverTime": {
            "type": "integer",
            "format": "int64",
            "description": "Server clock, epoch ms."
          },
          "partnerId": {
            "type": "integer"
          },
          "env": {
            "type": "string",
            "enum": [
              "sandbox",
              "production"
            ]
          }
        }
      },
      "CreatePlayerRequest": {
        "type": "object",
        "properties": {
          "requestId": {
            "type": "string",
            "description": "Logged only; the idempotency key is `externalPlayerId`."
          },
          "externalPlayerId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "Your player number; must not start with `u_`."
          },
          "username": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-z0-9_]{3,24}$",
            "description": "Omit or null to auto-generate. Must carry your partner prefix."
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 16
          },
          "lang": {
            "type": [
              "string",
              "null"
            ],
            "description": "Stored only."
          },
          "validDays": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Account validity in days; null = no expiry."
          }
        }
      },
      "CreatePlayerResponse": {
        "type": "object",
        "required": [
          "created",
          "playerId",
          "username",
          "status",
          "balance",
          "createdAt"
        ],
        "properties": {
          "created": {
            "type": "boolean",
            "description": "false when the externalPlayerId already existed."
          },
          "playerId": {
            "type": "string",
            "examples": [
              "u_9f3c1a2b7d4e5f6a8b90"
            ]
          },
          "username": {
            "type": "string"
          },
          "externalPlayerId": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/PlayerStatus"
          },
          "balance": {
            "type": "integer"
          },
          "createdAt": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "Player": {
        "type": "object",
        "required": [
          "playerId",
          "username",
          "status",
          "balance",
          "seated"
        ],
        "properties": {
          "playerId": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "externalPlayerId": {
            "type": [
              "string",
              "null"
            ]
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "$ref": "#/components/schemas/PlayerStatus"
          },
          "balance": {
            "type": "integer"
          },
          "seated": {
            "type": "boolean"
          },
          "currentTable": {
            "type": [
              "string",
              "null"
            ]
          },
          "lastLoginAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "createdAt": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "PlayerPage": {
        "type": "object",
        "required": [
          "items",
          "nextCursor"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Player"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "BatchRequest": {
        "type": "object",
        "required": [
          "batchId"
        ],
        "description": "Provide `count` **or** `players` (at most 200).",
        "properties": {
          "batchId": {
            "type": "string",
            "description": "Replaying the same batchId returns the same result."
          },
          "count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 200
          },
          "prefix": {
            "type": "string"
          },
          "validDays": {
            "type": [
              "integer",
              "null"
            ]
          },
          "players": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "type": "object",
              "properties": {
                "externalPlayerId": {
                  "type": "string"
                },
                "username": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "displayName": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "BatchResponse": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "playerId",
                "username"
              ],
              "properties": {
                "playerId": {
                  "type": "string"
                },
                "username": {
                  "type": "string"
                },
                "externalPlayerId": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "LaunchRequest": {
        "type": "object",
        "description": "Provide `externalPlayerId` **or** `playerId`.",
        "properties": {
          "externalPlayerId": {
            "type": "string",
            "description": "Unknown ids are created automatically."
          },
          "playerId": {
            "type": "string"
          },
          "displayName": {
            "type": "string",
            "maxLength": 16
          },
          "game": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "texas",
              "baccarat",
              null
            ],
            "description": "Land directly in this game; omit for the Snowball lobby."
          },
          "tableId": {
            "type": [
              "string",
              "null"
            ]
          },
          "lang": {
            "type": "string"
          },
          "returnUrl": {
            "type": "string",
            "format": "uri",
            "description": "Must be on your allow-listed domains."
          },
          "ttlSeconds": {
            "type": "integer",
            "minimum": 10,
            "maximum": 300,
            "default": 60
          }
        }
      },
      "LaunchResponse": {
        "type": "object",
        "required": [
          "playerId",
          "created",
          "launchToken",
          "launchUrl",
          "expiresAt"
        ],
        "properties": {
          "playerId": {
            "type": "string"
          },
          "created": {
            "type": "boolean"
          },
          "launchToken": {
            "type": "string",
            "description": "One-time token, `lt_` + 64 hex."
          },
          "launchUrl": {
            "type": "string",
            "format": "uri"
          },
          "expiresAt": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "Balance": {
        "type": "object",
        "required": [
          "playerId",
          "balance",
          "seated",
          "asOf"
        ],
        "properties": {
          "playerId": {
            "type": "string"
          },
          "balance": {
            "type": "integer"
          },
          "seated": {
            "type": "boolean",
            "description": "Also true for baccarat players with unsettled bets."
          },
          "currentTable": {
            "type": [
              "string",
              "null"
            ]
          },
          "asOf": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "TransferRequest": {
        "type": "object",
        "required": [
          "requestId",
          "amount"
        ],
        "properties": {
          "requestId": {
            "$ref": "#/components/schemas/RequestId"
          },
          "amount": {
            "$ref": "#/components/schemas/Amount"
          },
          "ref": {
            "type": "string",
            "maxLength": 64,
            "description": "Stored verbatim in the ledger."
          }
        }
      },
      "TransferOutRequest": {
        "type": "object",
        "required": [
          "requestId"
        ],
        "description": "Send `amount` or `all: true`.",
        "properties": {
          "requestId": {
            "$ref": "#/components/schemas/RequestId"
          },
          "amount": {
            "$ref": "#/components/schemas/Amount"
          },
          "all": {
            "type": "boolean"
          },
          "ref": {
            "type": "string",
            "maxLength": 64
          }
        }
      },
      "TransferResponse": {
        "type": "object",
        "required": [
          "ok",
          "replayed",
          "transferId",
          "txId",
          "requestId",
          "type",
          "amount",
          "balance",
          "ts"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "replayed": {
            "type": "boolean"
          },
          "transferId": {
            "type": "string"
          },
          "txId": {
            "type": "string",
            "description": "Deterministic: `ptr:{partnerId}:{requestId}`."
          },
          "requestId": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "transfer_in",
              "transfer_out"
            ]
          },
          "amount": {
            "type": "integer"
          },
          "balance": {
            "type": "integer",
            "description": "Wallet balance after the transfer."
          },
          "ts": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "TransferLookup": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "not_found"
            ]
          },
          "transfer": {
            "type": "object",
            "properties": {
              "transferId": {
                "type": "string"
              },
              "txId": {
                "type": "string"
              },
              "requestId": {
                "type": "string"
              },
              "playerId": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "transfer_in",
                  "transfer_out"
                ]
              },
              "amount": {
                "type": "integer"
              },
              "balance": {
                "type": "integer"
              },
              "ref": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "ts": {
                "type": "integer",
                "format": "int64"
              }
            }
          }
        }
      },
      "Transaction": {
        "type": "object",
        "required": [
          "txId",
          "type",
          "amount",
          "balance",
          "ts"
        ],
        "properties": {
          "txId": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "transfer_in",
              "transfer_out",
              "buy_in",
              "cash_out",
              "bet",
              "payout",
              "refund",
              "adjustment",
              "daily_bonus"
            ]
          },
          "amount": {
            "type": "integer",
            "description": "Signed from the player's point of view."
          },
          "balance": {
            "type": "integer",
            "description": "Wallet balance after this row; never negative."
          },
          "ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "game": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "texas",
              "baccarat",
              "roulette",
              null
            ]
          },
          "ts": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "TransactionPage": {
        "type": "object",
        "required": [
          "items",
          "nextCursor"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Transaction"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "PartnerTransactionPage": {
        "type": "object",
        "required": [
          "items",
          "nextCursor"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/Transaction"
                },
                {
                  "type": "object",
                  "properties": {
                    "playerId": {
                      "type": "string"
                    },
                    "username": {
                      "type": "string"
                    }
                  }
                }
              ]
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Round": {
        "type": "object",
        "required": [
          "game",
          "roundId",
          "tableId",
          "ts",
          "net"
        ],
        "properties": {
          "game": {
            "$ref": "#/components/schemas/Game"
          },
          "roundId": {
            "type": "string"
          },
          "tableId": {
            "type": "string"
          },
          "tier": {
            "type": "string",
            "enum": [
              "newbie",
              "mid",
              "high"
            ]
          },
          "ts": {
            "type": "integer",
            "format": "int64"
          },
          "bets": {
            "type": "array",
            "description": "Baccarat only.",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "examples": [
                    "player",
                    "banker",
                    "tie",
                    "playerPair",
                    "bankerPair"
                  ]
                },
                "amount": {
                  "type": "integer"
                }
              }
            }
          },
          "staked": {
            "type": [
              "integer",
              "null"
            ]
          },
          "returned": {
            "type": [
              "integer",
              "null"
            ]
          },
          "net": {
            "type": "integer"
          },
          "rake": {
            "type": "integer",
            "description": "Texas only; already deducted from `net`."
          },
          "capped": {
            "type": "boolean"
          },
          "result": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "RoundPage": {
        "type": "object",
        "required": [
          "items",
          "nextCursor"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Round"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SummaryReport": {
        "type": "object",
        "required": [
          "items",
          "totals"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "day": {
                  "type": "string",
                  "format": "date"
                },
                "transferIn": {
                  "type": "integer"
                },
                "transferOut": {
                  "type": "integer"
                },
                "net": {
                  "type": "integer"
                },
                "turnover": {
                  "type": "integer"
                },
                "playerWin": {
                  "type": "integer"
                },
                "rake": {
                  "type": "integer"
                },
                "activePlayers": {
                  "type": "integer"
                }
              }
            }
          },
          "totals": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "walletTotal": {
            "type": "integer",
            "description": "Sum of all your players' wallet balances."
          },
          "atTables": {
            "type": "integer",
            "description": "Chips currently on tables."
          }
        }
      },
      "RtpReport": {
        "type": "object",
        "required": [
          "items",
          "totals"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "day": {
                  "type": "string"
                },
                "game": {
                  "$ref": "#/components/schemas/Game"
                },
                "tableType": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "enum": [
                    "botsOnly",
                    "mixed",
                    null
                  ]
                },
                "mode": {
                  "type": "string"
                },
                "hands": {
                  "type": "integer"
                },
                "staked": {
                  "type": "integer"
                },
                "returned": {
                  "type": "integer"
                },
                "realizedRTP": {
                  "type": "number"
                },
                "n": {
                  "type": "integer"
                },
                "lowSample": {
                  "type": "boolean"
                },
                "humanStaked": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "humanNet": {
                  "type": "integer"
                },
                "botNet": {
                  "type": "integer"
                },
                "rake": {
                  "type": "integer"
                },
                "realizedReturn": {
                  "type": [
                    "number",
                    "null"
                  ]
                }
              }
            }
          },
          "totals": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "LimitField": {
        "type": "object",
        "properties": {
          "value": {},
          "platformMin": {
            "type": "integer"
          },
          "platformMax": {
            "type": "integer"
          }
        }
      },
      "LimitsView": {
        "type": "object",
        "description": "Every leaf is a `LimitField` (`value`, `platformMin`, `platformMax`).",
        "additionalProperties": true,
        "properties": {
          "tiers": {
            "type": "object",
            "additionalProperties": true
          },
          "maxPayoutPerBet": {
            "$ref": "#/components/schemas/LimitField"
          },
          "maxWinPerRound": {
            "$ref": "#/components/schemas/LimitField"
          },
          "maxWinPerDay": {
            "$ref": "#/components/schemas/LimitField"
          },
          "dailyBonus": {
            "type": "object",
            "additionalProperties": true
          },
          "minTransfer": {
            "$ref": "#/components/schemas/LimitField"
          },
          "maxTransfer": {
            "$ref": "#/components/schemas/LimitField"
          },
          "sessionHours": {
            "$ref": "#/components/schemas/LimitField"
          }
        }
      },
      "LimitsWrite": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "tiers": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "minBet": {
                  "type": "integer"
                },
                "maxBet": {
                  "type": "integer"
                },
                "sideMax": {
                  "type": "integer"
                },
                "minBuyIn": {
                  "type": "integer"
                },
                "maxBuyIn": {
                  "type": "integer"
                }
              }
            }
          },
          "maxPayoutPerBet": {
            "type": "integer"
          },
          "maxWinPerRound": {
            "type": "integer"
          },
          "maxWinPerDay": {
            "type": "integer"
          },
          "dailyBonus": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "amount": {
                "type": "integer"
              }
            }
          },
          "minTransfer": {
            "type": "integer"
          },
          "maxTransfer": {
            "type": "integer"
          },
          "sessionHours": {
            "type": "integer",
            "minimum": 1,
            "maximum": 24
          }
        }
      },
      "WebhookSettings": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "balance.changed",
                "win.big",
                "transfer.completed",
                "player.session"
              ]
            }
          },
          "enabled": {
            "type": "boolean"
          },
          "threshold": {
            "type": "integer",
            "description": "Net win that triggers `win.big`."
          },
          "coalesceMs": {
            "type": "integer",
            "description": "Merge `balance.changed` per player within this window; 0 = off."
          },
          "signingSecret": {
            "type": "string",
            "description": "Shown only on first set or after `resetSecret`."
          }
        }
      },
      "WebhookWrite": {
        "type": "object",
        "required": [
          "url",
          "events",
          "enabled"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "https only."
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "balance.changed",
                "win.big",
                "transfer.completed",
                "player.session"
              ]
            }
          },
          "enabled": {
            "type": "boolean"
          },
          "threshold": {
            "type": "integer"
          },
          "coalesceMs": {
            "type": "integer"
          },
          "resetSecret": {
            "type": "boolean"
          }
        }
      },
      "BotMode": {
        "type": "string",
        "enum": [
          "smart",
          "normal",
          "casual"
        ]
      },
      "BotWindow": {
        "type": "object",
        "required": [
          "from",
          "to",
          "mode"
        ],
        "description": "A time window. Selector (pick at most one): `dates` (specific days, strongest), `range` (date range, both ends\nincluded), `days` (weekdays 0=Sunday..6=Saturday on which the window **starts**); none = every day. `from`/`to`\nare `HH:MM` in `tz`; `to` at or before `from` runs past midnight; `24:00` = end of day.\n",
        "properties": {
          "days": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 0,
              "maximum": 6
            }
          },
          "dates": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "date"
            }
          },
          "range": {
            "type": "object",
            "required": [
              "from",
              "to"
            ],
            "properties": {
              "from": {
                "type": "string",
                "format": "date"
              },
              "to": {
                "type": "string",
                "format": "date"
              }
            }
          },
          "from": {
            "type": "string",
            "pattern": "^\\d{1,2}:\\d{2}$"
          },
          "to": {
            "type": "string",
            "pattern": "^\\d{1,2}:\\d{2}$"
          },
          "mode": {
            "$ref": "#/components/schemas/BotMode"
          }
        }
      },
      "BotRules": {
        "type": "object",
        "required": [
          "tz",
          "switchAt",
          "default",
          "windows"
        ],
        "properties": {
          "tz": {
            "type": "string",
            "description": "IANA time zone.",
            "examples": [
              "Asia/Kuala_Lumpur"
            ]
          },
          "switchAt": {
            "type": "string",
            "description": "HH:MM local time at which the business day changes (report grouping)."
          },
          "default": {
            "$ref": "#/components/schemas/BotMode"
          },
          "windows": {
            "type": "array",
            "maxItems": 32,
            "items": {
              "$ref": "#/components/schemas/BotWindow"
            }
          }
        }
      },
      "BotModeView": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "configured": {
            "type": "boolean"
          },
          "rules": {
            "$ref": "#/components/schemas/BotRules"
          },
          "override": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "mode": {
                "$ref": "#/components/schemas/BotMode"
              },
              "since": {
                "type": "integer",
                "format": "int64"
              }
            }
          },
          "effective": {
            "type": "object",
            "properties": {
              "mode": {
                "$ref": "#/components/schemas/BotMode"
              },
              "scheduled": {
                "$ref": "#/components/schemas/BotMode"
              },
              "businessDay": {
                "type": "string",
                "format": "date"
              }
            }
          },
          "now": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "BotModeWrite": {
        "type": "object",
        "minProperties": 1,
        "properties": {
          "rules": {
            "$ref": "#/components/schemas/BotRules"
          },
          "immediate": {
            "$ref": "#/components/schemas/BotMode"
          },
          "clearImmediate": {
            "type": "boolean"
          }
        }
      },
      "Rake": {
        "type": "object",
        "properties": {
          "pct": {
            "type": "number",
            "minimum": 0,
            "description": "Percent of the pot."
          },
          "cap": {
            "type": "integer",
            "description": "Maximum rake per hand, in chips."
          },
          "noFlopNoDrop": {
            "type": "boolean",
            "description": "No rake on hands that end before the flop."
          }
        }
      },
      "TexasTables": {
        "type": "object",
        "required": [
          "tiers"
        ],
        "properties": {
          "tiers": {
            "type": "object",
            "properties": {
              "newbie": {
                "$ref": "#/components/schemas/TexasTier"
              },
              "mid": {
                "$ref": "#/components/schemas/TexasTier"
              },
              "high": {
                "$ref": "#/components/schemas/TexasTier"
              }
            }
          }
        }
      },
      "TexasTier": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "botsOnly",
              "mixed"
            ]
          },
          "rake": {
            "$ref": "#/components/schemas/Rake"
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request. Codes: `bad_request`, `bad_amount`, `amount_out_of_range`, `bad_request_id`, `bad_username`,\n`bad_range`, `bad_limits`, `bad_return_url`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "bad_amount",
              "message": "amount must be a positive integer",
              "traceId": "tr_8c1e0f7a52"
            }
          }
        }
      },
      "Forbidden": {
        "description": "`ip_not_allowed` (checked before the signature), `partner_disabled`, `banned`, `partner_login_only`, `forbidden_game`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "ip_not_allowed",
              "message": "source IP is not on the allow-list",
              "traceId": "tr_8c1e0f7a52"
            }
          }
        }
      },
      "NotFound": {
        "description": "`player_not_found` (does not exist or is not yours) or `transfer_not_found`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "player_not_found",
              "message": "player not found",
              "traceId": "tr_8c1e0f7a52"
            }
          }
        }
      },
      "Conflict": {
        "description": "`insufficient`, `seated`, `idempotency_conflict`, `username_taken`, `player_suspended`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "idempotency_conflict",
              "message": "requestId was already used with different parameters",
              "traceId": "tr_8c1e0f7a52"
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "`payload_too_large`: body above 64 KB.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "payload_too_large",
              "message": "request body exceeds 64 KB",
              "traceId": "tr_8c1e0f7a52"
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "`unsupported_media_type`: body must be `application/json`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "unsupported_media_type",
              "message": "Content-Type must be application/json",
              "traceId": "tr_8c1e0f7a52"
            }
          }
        }
      },
      "RateLimited": {
        "description": "`rate_limited`. Wait `Retry-After` seconds.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds to wait."
          },
          "X-RateLimit-Limit": {
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Remaining": {
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Reset": {
            "schema": {
              "type": "integer"
            },
            "description": "Epoch seconds."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "rate_limited",
              "message": "too many requests",
              "traceId": "tr_8c1e0f7a52"
            }
          }
        }
      },
      "ServerError": {
        "description": "`internal`: our fault. For transfers, **retry with the same `requestId`**.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "internal",
              "message": "internal error",
              "traceId": "tr_8c1e0f7a52"
            }
          }
        }
      },
      "Maintenance": {
        "description": "`maintenance`: maintenance or deployment drain; `Retry-After` is set. Transfers stay available during a game drain.\n",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "maintenance",
              "message": "service is being updated",
              "traceId": "tr_8c1e0f7a52"
            }
          }
        }
      }
    }
  }
}