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

# Financial Transactions

> Handle BET, WIN, and VOID operations to deduct, credit, or refund player funds during gameplay.

PlayStarters calls your wallet endpoint with `type: "BET"`, `"WIN"`, or `"VOID"` to move funds during gameplay.

| Type   | Effect on balance               | Notes                                                           |
| ------ | ------------------------------- | --------------------------------------------------------------- |
| `BET`  | **Deduct** the amount.          | If the player lacks funds, reject with `400` (see below).       |
| `WIN`  | **Credit** the amount.          | Includes `parentTransactionId` referencing the original bet.    |
| `VOID` | **Credit** (refund) the amount. | Sent when a round is cancelled. Includes `parentTransactionId`. |

## Request

```json theme={null}
{
  "playerId": "your_unique_user_id",
  "type": "BET",
  "amount": 10.0,
  "currency": "EUR",
  "gameId": "game_uuid",
  "roundId": "round_uuid",
  "requestId": "unique_transaction_id",
  "parentTransactionId": "original_bet_id"
}
```

### Field reference

<ResponseField name="playerId" type="string">
  Your unique identifier for the player.
</ResponseField>

<ResponseField name="type" type="string">
  `BET`, `WIN`, or `VOID`.
</ResponseField>

<ResponseField name="amount" type="number">
  Transaction amount in the player's currency. Always positive.
</ResponseField>

<ResponseField name="currency" type="string">
  ISO 4217 currency code.
</ResponseField>

<ResponseField name="gameId" type="string">
  UUID of the game the transaction belongs to.
</ResponseField>

<ResponseField name="roundId" type="string">
  Identifier for the game round. Groups related BET/WIN/VOID transactions together.
</ResponseField>

<ResponseField name="requestId" type="string">
  Unique identifier for this transaction. Use it as your idempotency key — see [Idempotency](/api/wallet/idempotency).
</ResponseField>

<ResponseField name="parentTransactionId" type="string">
  Sent only for `WIN` and `VOID`. References the `requestId` of the original `BET` so you can correlate them.
</ResponseField>

<Note>
  Even if `parentTransactionId` is absent or does not match a known transaction, always respond with HTTP 200 and apply the credit.
</Note>

## Success response — 200 OK

Return the player's updated balance after applying the transaction:

```json theme={null}
{
  "balance": 140.50
}
```

## Insufficient funds (BET only)

If the player does not have enough balance to cover a `BET`, you **must** reject the request with HTTP `400 Bad Request` and the following body so the game provider can block the spin:

```json theme={null}
{
  "msg": "Insufficient user credit"
}
```

<Warning>
  Only reject `BET` operations with `400`. `WIN` and `VOID` must always succeed — they credit funds back to the player. If a `WIN` or `VOID` arrives for a `parentTransactionId` you don't recognize, log it and still respond `200 OK` with the player's current balance.
</Warning>

<Tip>
  Every transaction includes a `requestId`. Persist it server-side and return the stored balance on retries instead of re-applying the movement. See [Idempotency](/api/wallet/idempotency) for details.
</Tip>
