# Transactions

THNDR calls this endpoint to notify the Operator of a transaction request, instructing them to either debit or credit the player’s balance.

#### Endpoint

```url
POST {operatorURL}/thndr/transactions
```

### Bet Transaction

The **BET** Transaction is sent by THNDR to notify the Operator of a wager placed by a player.

The Operator must process this request to **debit the player’s balance** (and optionally record a potential reward).

<br>

```json
{
   "type": "BET",
   "transactionId": "a395479b-7d31-406e-abab-2dd66a61d5ee-BET",
   "requestedAt": "2025-08-21T14:30:00.123Z",
   "userId": "{USER_ID}",
   "sessionId": "{SESSION_ID}",
   "roundId": "a395479b-7d31-406e-abab-2dd66a61d5ee",
   "currency": "USD",
   "amount": 120,
   "gameId": "solitaire",
   "reward": 200,
   "serviceFee": 20
}
```

* `transactionId` - Unique transaction identifier. Must be persisted by the Operator for idempotency and rollback handling.
* `requestedAt` - The date and time when the request was initially made, in ISO 8601 format (e.g., 2025-08-21T14:30:00.123Z).
* `userId` - Player identifier on the Operator’s platform.
* `sessionId` - The session identifier provided by the Operator when the game was launched.
* `roundId` - Identifier of the game round this transaction belongs to.
* `currency` - Player's wallet currency provided by the Operator when the game was launched (read more in [Currencies](/integration/server-webhooks/currencies.md)).
* `amount` - Bet amount, in the smallest unit of the currency (e.g., cents for USD, pence for GBP).
* `gameId` - Game identifier. Possible values: `solitaire`, `blocks`, `twentyone`, `blackjack`, `slots`, `plinko` .
* `reward` - The possible payout in the smallest unit of the currency if this bet wins (shown for info, do not credit yet).
* `serviceFee` - Service fee portion included in `amount` (info-only); Operator must debit **only `amount`**, not `amount + serviceFee`.

#### Error Handling

If the player does not have sufficient funds, the Operator must return:

```
HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "errors": [
    {
      "code": "INSUFFICIENT_BALANCE",
      "isClientSafe": true
    }
  ]
}
```

{% hint style="info" %}
You must pass "isClientSafe": true in the response for it to be passed to the client.
{% endhint %}

### Win Transaction

The **WIN** transaction is sent by THNDR to notify the Operator that a player has won a round.

The Operator must process this request to **credit the player’s balance**.

```json
{
   "type": "WIN",
   "transactionId": "a395479b-7d31-406e-abab-2dd66a61d5ee-WIN",
   "requestedAt": "2025-08-21T14:30:00.123Z",
   "userId": "{USER_ID}",
   "sessionId": "{SESSION_ID}",
   "roundId": "a395479b-7d31-406e-abab-2dd66a61d5ee",
   "currency": "USD",
   "amount": 200,
   "gameId": "solitaire",
   "roomId": "{ROOM_ID}"
}

```

* `transactionId` - Unique transaction identifier. Must be persisted by the Operator for idempotency and rollback handling.
* `requestedAt` - The date and time when the request was initially made, in ISO 8601 format (e.g., 2025-08-21T14:30:00.123Z).
* `userId` - Player identifier on the Operator’s platform.
* `sessionId` - The session identifier provided by the Operator when the game was launched.
* `roundId` - Identifier of the game round this transaction belongs to.
* `currency` - Player's wallet currency provided by the Operator when the game was launched (read more in [Currencies](/integration/server-webhooks/currencies.md)).
* `amount` - Win amount, in the smallest unit of the currency (e.g., cents for USD, pence for GBP).
* `gameId` - Game identifier. Possible values: `solitaire`, `blocks`, `twentyone`, `blackjack`, `slots`, `plinko`.
* `roomId` - Identifier for the game room. Players sharing the same roomId are participating in the same PvP match.

### Lose Transaction

The **LOSE** transaction is sent by THNDR to notify the Operator that a player has lost a round.

The Operator might process this request to **record a loss**.<br>

```json
{
   "type": "LOSE",
   "transactionId": "a395479b-7d31-406e-abab-2dd66a61d5ee-LOSE",
   "requestedAt": "2025-08-21T14:30:00.123Z",
   "userId": "{USER_ID}",
   "sessionId": "{SESSION_ID}",
   "roundId": "a395479b-7d31-406e-abab-2dd66a61d5ee",
   "currency": "USD",
   "gameId": "solitaire",
   "roomId": "{ROOM_ID}"
}

```

* `transactionId` - Unique transaction identifier. Must be persisted by the Operator for idempotency.
* `requestedAt` - The date and time when the request was initially made, in ISO 8601 format (e.g., 2025-08-21T14:30:00.123Z).
* `userId` - Player identifier on the Operator’s platform.
* `sessionId` - The session identifier provided by the Operator when the game was launched.
* `roundId` - Identifier of the game round this transaction belongs to.
* `currency` - Player's wallet currency provided by the Operator when the game was launched (read more in [Currencies](/integration/server-webhooks/currencies.md)).
* `gameId` - Game identifier. Possible values: `solitaire`, `blocks`, `twentyone`, `blackjack`, `slots`, `plinko` .
* `roomId` - Identifier for the game room. Players sharing the same roomId are participating in the same PvP match.

### Draw Transaction

The **DRAW** transaction is sent by THNDR to notify the Operator that a player has tied a round.

The Operator must process this request to **credit the player’s balance**.

```json
{
   "type": "DRAW",
   "transactionId": "a395479b-7d31-406e-abab-2dd66a61d5ee-DRAW",
   "requestedAt": "2025-08-21T14:30:00.123Z",
   "userId": "{USER_ID}",
   "sessionId": "{SESSION_ID}",
   "roundId": "a395479b-7d31-406e-abab-2dd66a61d5ee",
   "currency": "USD",
   "amount": 200,
   "gameId": "solitaire",
   "roomId": "{ROOM_ID}"
}
```

* `transactionId` - Unique transaction identifier. Must be persisted by the Operator for idempotency and rollback handling.
* `requestedAt` - The date and time when the request was initially made, in ISO 8601 format (e.g., 2025-08-21T14:30:00.123Z).
* `userId` - Player identifier on the Operator’s platform.
* `sessionId` - The session identifier provided by the Operator when the game was launched.
* `roundId` - Identifier of the game round this transaction belongs to.
* `currency` - Player's wallet currency provided by the Operator when the game was launched (read more in [Currencies](/integration/server-webhooks/currencies.md)).
* `amount` - Win amount, in the smallest unit of the currency (e.g., cents for USD, pence for GBP).
* `gameId` - Game identifier. Possible values: `solitaire`, `blocks`, `twentyone`, `blackjack`, `slots`, `plinko` .
* `roomId` - Identifier for the game room. Players sharing the same roomId are participating in the same PvP match.

### Rollback Transaction

The **ROLLBACK** transaction is sent by THNDR to request the Operator to **reverse a previously processed BET transaction**, in cases of error, cancellation, or game rollback.

The Operator must ensure that the original transaction is undone and the player’s balance is correctly updated.

```json
{
   "type": "ROLLBACK",
   "transactionId": "a395479b-7d31-406e-abab-2dd66a61d5ee-ROLLBACK",
   "requestedAt": "2025-08-21T14:30:00.123Z",
   "originalTransactionId": "a395479b-7d31-406e-abab-2dd66a61d5ee-BET",
   "userId": "{USER_ID}",
   "sessionId": "{SESSION_ID}",
   "roundId": "a395479b-7d31-406e-abab-2dd66a61d5ee",
   "currency": "USD",
   "gameId": "solitaire"
}
```

* `transactionId` - Unique transaction identifier. Must be persisted by the Operator for idempotency.
* `requestedAt` - The date and time when the request was initially made, in ISO 8601 format (e.g., 2025-08-21T14:30:00Z).
* `originalTransactionId` - The transactionId of the original BET transaction being rolled back.
* `userId` - Player identifier on the Operator’s platform.
* `sessionId` - The session identifier provided by the Operator when the game was launched.
* `roundId` - Identifier of the game round this transaction belongs to.
* `currency` - Player's wallet currency provided by the Operator when the game was launched (read more in [Currencies](/integration/server-webhooks/currencies.md)).
* `gameId` - Game identifier. Possible values: `solitaire`, `blocks`, `twentyone`, `blackjack`, `slots`, `plinko` .

{% hint style="warning" %}
Important: If a system crash occurs before receiving a response from the BET transaction, you may receive rollback requests for transaction ids that were never persisted in your database (i.e., the user was not credited). These requests must be ignored, and a 200 status code must be returned.
{% endhint %}

### Signature Verification

Verify the request signature using raw request body as the request payload. More in the [Request Signing](/integration/server-webhooks/request-signing.md) section.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.thndr.io/integration/server-webhooks/transactions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
