Skip to content

Wallet API Overview

Beexar uses the Seamless Wallet pattern. Your operator server acts as the player’s wallet — Beexar never holds funds. During gameplay, Beexar sends HTTP POST requests to your configured callback URLs.

flowchart LR
    Player -->|plays| Beexar
    Beexar -->|"POST /balance"| Operator
    Beexar -->|"POST /betwin"| Operator
    Beexar -->|"POST /rollback"| Operator
    Beexar -->|"POST /finish"| Operator
    Beexar -.->|"POST /freespins/finish (optional)"| Operator

All requests flow from Beexar to the Operator. The operator never calls these endpoints — they implement them.

You configure 4 callback URLs in the Beexar backoffice for each operator, and a fifth if you issue freespins:

Callback Endpoint Purpose
balance_url POST /balance Return player’s current balance
betwin_url POST /betwin Debit (bet) and/or credit (win) — atomic
rollback_url POST /rollback Reverse previous transactions
finish_url POST /finish Round completion signal
freespins_finish_url POST /freespins/finish Optional. Credit what a freespins issue won — see /freespins/finish

All amount, balance, total_bet, and total_win fields are transmitted as string representations of decimal numbers.

Example Currency Decimal value
"10.50" USD 10.50 USD
"0.01" USD 0.01 USD
"100.00" EUR 100.00 EUR
"1.12345678" BTC 1.12345678 BTC

Rules:

  • Amounts are always positive (or zero for rollback); a /freespins/finish amount may be zero
  • Maximum 18 decimal places (supports crypto precision)
  • Pattern: ^\d+(\.\d{1,18})?$
  • Currency codes: ISO 4217 (USD, EUR) or custom tokens (CUSTOM_* format, up to 32 chars)

Every request includes an X-REQUEST-SIGN header with an HMAC-SHA256 signature of the request body. See Authentication for details and code samples.

If the signature is invalid, respond with HTTP 400 and api_code 403:

{
"code": "invalid_argument",
"msg": "Invalid signature",
"meta": {
"api_code": "403",
"api_message": "Invalid signature"
}
}

All error responses follow the Twirp format:

{
"code": "invalid_argument",
"msg": "Player has not enough funds to process an action.",
"meta": {
"api_code": "100",
"api_message": "Player has not enough funds to process an action.",
"balance": "50.00"
}
}
Field Type Required Description
code string Yes Twirp error code: "invalid_argument" (HTTP 400) or "internal" (HTTP 500)
msg string Yes Human-readable error description
meta.api_code string Yes Numeric API error code (see Error Handling)
meta.api_message string Yes API error message
meta.balance string Conditional Current balance — required when api_code is 100, 105, or 106

Every bet, win, and rollback transaction includes a unique id_provider. Your wallet must handle idempotency:

  • If an id_provider has already been processed, return the original response (same balance, same transaction IDs)
  • Do NOT process the transaction again (no double-debit, no double-credit)
  • This applies to all transaction types: bet, win, and rollback
  • /freespins/finish is idempotent in the same way on its issue_id: a repeat returns the balance you answered the first time and credits nothing

A round is a complete game cycle identified by round_id. Every round follows this lifecycle:

stateDiagram-v2
    direction LR
    [*] --> Active: First /betwin
    Active --> Active: /betwin, /rollback
    Active --> [*]: /betwin finished=true
    Active --> [*]: /finish
/betwin (bet + win, finished=true)

One request with bet and win transactions. The finished: true flag closes the round — no separate /finish call needed.

/betwin (bet, finished=false) → /betwin (win, finished=true)

Two BetWin requests within a single round_id: the bet is debited when the drop starts, the win is credited when it lands. A drop that wins nothing closes with its bet: /betwin (bet, finished=true).

/betwin (bet, finished=false) → /betwin (win, finished=true)
/betwin (bet, finished=false) → /finish

The bet is debited when the round starts and any number of hits follow on the game server, with no wallet calls. A cash out credits the win. Dynamite ends the round with nothing to pay: it closes with /finish, and no zero win is sent.

  1. All rounds must be finished — every round that starts with a bet will eventually be closed (via finished: true or /finish)
  2. Transactions share the same round_id — use this to group them
  3. Each transaction has a unique id_provider — use this for idempotency
  4. Rollbacks can happen mid-round — e.g., in crash, a win whose wallet call failed during cashout is rolled back
  5. The finished flag eliminates the /finish call — for simple games, the round is complete in a single BetWin request

sequenceDiagram
    participant Operator
    participant Beexar
    participant Game as Game Frontend
    participant Wallet as Operator Wallet

    Note over Operator,Wallet: 1. Session Creation
    Operator->>Beexar: POST /api/v1/softswiss/launcher/real
    Beexar-->>Operator: { launch_url }

    Note over Operator,Wallet: 2. Game Load
    Operator->>Game: Embed launch_url in iframe
    Game->>Beexar: Load game with token
    Beexar->>Wallet: POST /balance
    Wallet-->>Beexar: { balance: "500.00" }
    Beexar-->>Game: Show game UI

    Note over Operator,Wallet: 3. Gameplay (dice example)
    Game->>Beexar: Player bets 10 USD
    Beexar->>Wallet: POST /betwin (bet=10, win=19.80, finished=true)
    Wallet-->>Beexar: { balance: "509.80", transactions }
    Beexar-->>Game: Show result

    Note over Operator,Wallet: 4. Error Recovery
    Game->>Beexar: Player bets 5 USD
    Beexar->>Wallet: POST /betwin (bet=5)
    Wallet-->>Beexar: 200 OK
    Note right of Beexar: Game engine error
    Beexar->>Wallet: POST /rollback (original bet)
    Wallet-->>Beexar: { balance: "509.80" }