Skip to content

Operator Wallet API guide

The Operator Wallet API is called by the Star Game platform, on your backend. You choose the base URL (for example https://api.example.com/game-wallet/v1) and enter it as Wallet URL in Console → Integration, per environment. The full machine-readable contract is the OpenAPI reference.

  • HTTPS only, JSON (UTF-8), snake_case fields. Ignore unknown fields: adding fields is not a breaking change.
  • Every request is signed (see Signatures).
  • amount and balance are integer minor units as decimal strings ("1500"), pattern ^-?[0-9]{1,19}$. The currency code and decimal places are the Currency and Decimals you configure in Console → Integration.
  • Identifiers are strings; times are RFC 3339 UTC.
  • Whole-request errors use HTTP status codes with application/problem+json (RFC 9457).
Method Path Purpose
POST /players/authenticate Exchange a launch code for a player and session
POST /players/balance Current balance of a player
POST /transactions Apply a batch of 1–500 debits, credits and rollbacks
GET /transactions/{transaction_id} Look up one transaction (audit and support)

Called once per game launch with the code your App passed through getConfig.

POST /game-wallet/v1/players/authenticate HTTP/1.1
Host: api.example.com
Content-Type: application/json
webhook-id: msg_3f9a0c1e5b7d4e2a9c8b6a4f2e1d0c9b
webhook-timestamp: 1791763200
webhook-signature: v1,K5o0…=
{"launch_code":"lc_7Qm2…","game_id":"lantern","client_ip":"203.0.113.24"}
{
"player_id": "84021734",
"session_id": "gs_1c9e…",
"display_name": "Layla",
"avatar_url": "https://cdn.example.com/a/84021734.png",
"currency": "GOLD",
"balance": "250000",
"language": "ar",
"country": "SA"
}

player_id, session_id, currency and balance are required. An unknown, used or expired code → 401 problem with code: "invalid_launch_code".

{ "player_id": "84021734", "session_id": "gs_1c9e…" }
{ "balance": "248500", "currency": "GOLD" }

Unknown player → 404 player_not_found. Extend the session when this call carries a valid session_id.

A batch of 1–500 transactions (at most your configured maximum batch size).

{
"transactions": [
{
"transaction_id": "lantern:59666:84021734:bet",
"type": "debit",
"player_id": "84021734",
"session_id": "gs_1c9e…",
"amount": "1500",
"currency": "GOLD",
"game_id": "lantern",
"round_id": "lantern:59666",
"room_id": "8880085",
"created_at": "2026-10-12T13:00:18Z",
"details": { "bets": [{ "option": "rose", "amount": "1000" }, { "option": "phoenix", "amount": "500" }] }
},
{
"transaction_id": "lantern:59665:84021734:win",
"type": "credit",
"player_id": "84021734",
"amount": "4500",
"currency": "GOLD",
"game_id": "lantern",
"round_id": "lantern:59665",
"reference_transaction_id": "lantern:59665:84021734:bet"
},
{
"transaction_id": "lantern:59664:84021734:bet:rollback",
"type": "rollback",
"player_id": "84021734",
"game_id": "lantern",
"round_id": "lantern:59664",
"reference_transaction_id": "lantern:59664:84021734:bet"
}
]
}

Response 200 with one result per item, in request order:

{
"results": [
{ "transaction_id": "lantern:59666:84021734:bet", "status": "ok", "balance": "248500", "processed_at": "2026-10-12T13:00:18Z" },
{ "transaction_id": "lantern:59665:84021734:win", "status": "ok", "balance": "253000", "processed_at": "2026-10-12T13:00:18Z" },
{ "transaction_id": "lantern:59664:84021734:bet:rollback", "status": "ok", "balance": "253000", "processed_at": "2026-10-12T13:00:18Z" }
]
}
Field Types Notes
transaction_id all Globally unique, ≤ 128 chars. Your idempotency key.
type all debit, credit or rollback
player_id, game_id all Required
session_id debit The session from authenticate
amount, currency debit, credit Minor units as a string
round_id all Groups all transactions of one round
room_id optional The room the player played from, if any
reference_transaction_id rollback (required), credit (optional) The debit to reverse / the debit being paid out
created_at optional When the platform created the transaction
details optional Human-readable breakdown for your support tools; treat as opaque
status Meaning Booked? What the platform does
ok Booked now or earlier (also a rollback with nothing to reverse) yes / already Done
insufficient_funds Debit refused, include balance no Stake cancelled
session_invalid Debit only: session ended or invalid no Stake cancelled
player_blocked Debit only: player may not play no Stake cancelled
limit_exceeded Debit only: your responsible-gaming or risk limit no Stake cancelled
duplicate_mismatch Same transaction_id, different content no Alert, manual follow-up
reference_not_found Credit whose debit was never booked or was rolled back no Payout not made, recorded
rolled_back Debit arriving after its rollback (tombstone) no Stake cancelled
retry Transient failure (lock timeout etc.) no Resent with the same id

For audit and support only; the platform does not use it in the money path.

{
"transaction_id": "lantern:59666:84021734:bet",
"type": "debit",
"status": "ok",
"amount": "1500",
"balance": "248500",
"rolled_back": false,
"processed_at": "2026-10-12T13:00:18Z"
}

Never received → 404 transaction_not_found.

Whole-request failures use a non-2xx status and an RFC 9457 body. The platform reads the HTTP status and code; type can be any URI you like.

HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 2
{"type":"https://api.example.com/problems/rate_limited","title":"Too many requests","status":429,"code":"rate_limited","detail":"slow down"}
code HTTP When
invalid_signature 401 Missing, wrong or stale signature
invalid_launch_code 401 Unknown, used or expired launch code
malformed_request 400 Body does not match the schema
player_not_found 404 balance for an unknown player
transaction_not_found 404 GET /transactions/{id} never received
not_found 404 Unknown path
rate_limited 429 Send Retry-After
unavailable 503 Outcome unknown for the whole batch; send Retry-After
internal 500 Unexpected error

The platform retries 408, 429, 5xx and timeouts with the same transaction ids. See Error codes & rate limits.

In Console → Integration (Sandbox or Production tab), under Wallet, you declare:

Setting Range Effect
Max batch size 1–500 The platform never puts more transactions in one POST /transactions
Max concurrent requests 1–16 The platform never has more requests in flight to your wallet
Currency A–Z, 0–9, 2–8 chars Sent as currency on debits and credits
Decimals 0–8 How your minor units map to display amounts

Size these for your peak: at the close of a busy betting window many players are debited within a second or two. If you answer 429 or 503, the platform backs off according to Retry-After.

Every request carries three headers (Standard Webhooks):

webhook-id: msg_<random> unique per HTTP attempt
webhook-timestamp: <unix seconds>
webhook-signature: v1,<base64(HMAC-SHA256(key, id + "." + timestamp + "." + raw_body))>

key is the base64-decoded part of your whsec_… secret. Reject timestamps more than 300 s from your clock. During secret rotation the header carries several space-separated signatures; accept the request if any matches. Full details and tested code in five languages: Signature verification.