# Transaction (Site Endpoint)

Called when a bet or win occurs. Your backend must update the user balance and return the updated value.

## Endpoint

```
POST https://{YOUR_SITE}/gold_api
```

**Content-Type:** `application/json`

**Method:** `transaction`

## Request

### Slot transaction

```json
{
    "method": "transaction",
    "agent_code": "your_agent_code",
    "agent_secret": "your_agent_secret",
    "agent_balance": 10000000,
    "user_code": "test",
    "user_token": "c3041c6d9146a164387fa454eff7b432",
    "user_balance": 99200,
    "game_type": "slot",
    "slot": {
        "provider_code": "PRAGMATIC",
        "game_code": "vs20midas",
        "type": "BASE",
        "bet_money": 1000,
        "win_money": 200,
        "round_id": 63792613432127,
        "txn_id": "64a83f2fc597acc9004eec52c3f84c30",
        "txn_id_v2": "64a83f2fc597acc9004eec52c3f84c30",
        "txn_type": "debit_credit",
        "is_end": true
    }
}
```

### Free tour transaction

A round of a free tour (see [Create Tour](https://my.nexusggr.com/app/docs/integration/freespin-tour-api/create-tour)) is a slot transaction with four `tour_*` fields added to `slot`. Here the win of the tour's 4th round of 10; see [Free tour rounds](#free-tour-rounds) for the whole sequence.

```json
{
    "method": "transaction",
    "agent_code": "your_agent_code",
    "agent_secret": "your_agent_secret",
    "agent_balance": 9930000,
    "user_code": "test",
    "user_token": "c3041c6d9146a164387fa454eff7b432",
    "user_balance": 104000,
    "game_type": "slot",
    "slot": {
        "provider_code": "PRAGMATIC",
        "game_code": "vs20doghouse",
        "type": "BASE",
        "bet_money": 0,
        "win_money": 3500,
        "round_id": 63792613432140,
        "txn_id": "9d2f4b7e1a3c48d6b05e7f21c8a9d3e4",
        "txn_id_v2": "9d2f4b7e1a3c48d6b05e7f21c8a9d3e4",
        "txn_type": "credit",
        "is_end": true,
        "tour_id": "free_tour_777",
        "tour_rest_count": 6,
        "tour_total_win": 15500,
        "tour_end": false
    }
}
```

### Live transaction

```json
{
    "method": "transaction",
    "agent_code": "your_agent_code",
    "agent_secret": "your_agent_secret",
    "agent_balance": 10000000,
    "user_code": "test",
    "user_token": "c3041c6d9146a164387fa454eff7b432",
    "user_balance": 102000,
    "game_type": "live",
    "info": "{\"gameresult\":{\"pp\":\"0.0\",\"bb\":\"0.0\",\"gameType\":\"baccarat\",\"perfectPair\":\"false\",\"banker_pair\":\"false\",\"code\":\"0\",\"bighand\":\"false\",\"bg\":\"0.0\",\"player_pair\":\"false\",\"bp\":\"0.0\",\"result\":\"player\",\"score\":\"8\",\"bnc\":\"0.0\",\"sm\":\"2.5\",\"id\":\"15676627318\",\"table\":\"pwnhicogrzeodk79\",\"eitherPair\":\"false\",\"gameId\":\"15676627318\",\"b\":\"0.0\",\"s6\":\"0.0\",\"natural\":\"true\",\"playerBonus\":\"true\",\"pnc\":\"2.0\",\"ep\":\"0.0\",\"bankerBonus\":\"false\",\"prp\":\"0.0\",\"p\":\"2.0\",\"pb\":\"2.0\",\"t\":\"0.0\",\"super6\":\"false\",\"time\":\"00:40:15\",\"smallhand\":\"true\",\"seq\":2304,\"value\":\"player\"}}",
    "live": {
        "provider_code": "EVOLUTION",
        "game_code": "100",
        "type": "baccarat",
        "bet_money": 2000,
        "win_money": 4000,
        "round_id": 15676627318,
        "txn_id": "b7e12d4a8f0c4519a2d6e3b81f5c9047",
        "txn_id_v2": "b7e12d4a8f0c4519a2d6e3b81f5c9047",
        "txn_type": "debit_credit"
    }
}
```

### Sportsbook transaction

```json
{
    "method": "transaction",
    "agent_code": "your_agent_code",
    "agent_secret": "your_agent_secret",
    "agent_balance": 10000000,
    "user_code": "test",
    "user_token": "c3041c6d9146a164387fa454eff7b432",
    "user_balance": 102000,
    "game_type": "SB",
    "info": "{\"couponCode\":\"000000561435\",\"status\":\"pending\",\"totalOdds\":3.73,\"potentialWin\":18.64,\"stake\":5,\"payout\":0,\"betslips\":[{\"id\":120,\"sportName\":\"Football\",\"countryName\":\"World\",\"leagueName\":\"Club Friendlies\",\"matchName\":\"Odds - Stromsgodset\",\"homeTeam\":\"Odds\",\"awayTeam\":\"Stromsgodset\",\"marketName\":\"1X2\",\"oddName\":\"W1\",\"oddRate\":1.46,\"oddPoint\":\"696729566|1|1|0\"}],\"settlementData\":{}}",
    "SB": {
        "provider_code": "SPORTSBOOK",
        "game_code": "SPORTSBOOK",
        "type": "accumulator",
        "bet_money": 5,
        "win_money": 0,
        "round_id": 561435,
        "txn_id": "44097c196a8b59b7371ee2ca6fe83999",
        "txn_id_v2": "44097c196a8b59b7371ee2ca6fe83999",
        "txn_type": "debit"
    }
}
```

### Mini game (MN) transaction

```json
{
    "method": "transaction",
    "agent_code": "your_agent_code",
    "agent_secret": "your_agent_secret",
    "agent_balance": 10000000,
    "user_code": "test",
    "user_token": "c3041c6d9146a164387fa454eff7b432",
    "user_balance": 99200,
    "game_type": "MN",
    "MN": {
        "provider_code": "SPRIBE",
        "game_code": "minigame_01",
        "type": "BASE",
        "bet_money": 1000,
        "win_money": 200,
        "round_id": 123456789,
        "txn_id": "3f0a6c1de95b47829c04a7be2d18f635",
        "txn_id_v2": "3f0a6c1de95b47829c04a7be2d18f635",
        "txn_type": "debit_credit"
    }
}
```

### Request fields

<table><thead><tr><th width="144">Field</th><th width="90">Type</th><th width="90">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>method</code></td><td>string</td><td>Yes</td><td>Always <code>transaction</code></td></tr><tr><td><code>agent_code</code></td><td>string</td><td>Yes</td><td>Agent code</td></tr><tr><td><code>agent_secret</code></td><td>string</td><td>Yes</td><td>Agent secret key</td></tr><tr><td><code>agent_balance</code></td><td>number</td><td>Yes</td><td>Your agent balance on the platform, with this transaction already applied</td></tr><tr><td><code>user_code</code></td><td>string</td><td>Yes</td><td>User identifier</td></tr><tr><td><code>user_token</code></td><td>string</td><td>No</td><td>User session token. Can be missing or empty, e.g. on a transaction that is sent again</td></tr><tr><td><code>user_balance</code></td><td>number</td><td>Yes</td><td>User balance as your site last returned it, before this transaction</td></tr><tr><td><code>game_type</code></td><td>string</td><td>Yes</td><td>Provider type (see the table below)</td></tr><tr><td><code>slot</code> / <code>live</code> / <code>SB</code> / <code>MN</code> / <code>FH</code></td><td>object</td><td>Yes</td><td>Game object, under the key named by <code>game_type</code></td></tr><tr><td><code>info</code></td><td>string</td><td>Conditional</td><td>Live and sportsbook only: stringified JSON with bet/result details (see below)</td></tr></tbody></table>

### Game object fields

**Important:** The game detail object key **must match** the `game_type` value.

> Example: if `"game_type": "slot"`, the payload must include a `"slot": { ... }` object. If `"game_type": "SB"`, use `"SB": { ... }`.

| game\_type | Provider Type |
| ---------- | ------------- |
| `slot`     | Slot          |
| `live`     | Live Casino   |
| `SB`       | Sportsbook    |
| `MN`       | Mini Game     |
| `FH`       | Fish          |

Fields inside the game object (`slot` / `live` / `SB` / `MN` / `FH`):

<table><thead><tr><th width="144">Field</th><th width="90">Type</th><th width="90">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>provider_code</code></td><td>string</td><td>Yes</td><td>Game provider code</td></tr><tr><td><code>game_code</code></td><td>string</td><td>Yes</td><td>Game identifier</td></tr><tr><td><code>type</code></td><td>string</td><td>Yes</td><td>Bet/round type (e.g. <code>BASE</code>, <code>baccarat</code>)</td></tr><tr><td><code>bet_money</code></td><td>number</td><td>Yes</td><td>Bet amount</td></tr><tr><td><code>win_money</code></td><td>number</td><td>Yes</td><td>Win amount</td></tr><tr><td><code>round_id</code></td><td>integer</td><td>Yes</td><td>Unique ID for one bet. Every transaction the bet produces shares it</td></tr><tr><td><code>txn_id</code></td><td>string</td><td>Yes</td><td>Unique per transaction: every inner spin of a bet has its own. Deduplicate on this field.<br>Since October 15, 2026 (UTC). Before that date it was the <code>round_id</code> as a string, the same on every transaction of one bet.</td></tr><tr><td><code>txn_id_v2</code></td><td>string</td><td>Yes</td><td>The same value as <code>txn_id</code>.<br><strong>Deprecated on October 31, 2026 (UTC):</strong> use <code>txn_id</code> instead.</td></tr><tr><td><code>txn_type</code></td><td>string</td><td>Yes</td><td><code>debit</code>, <code>credit</code>, or <code>debit_credit</code></td></tr><tr><td><code>is_end</code></td><td>boolean</td><td>Conditional</td><td>Sent only when <code>provider_code</code> is <code>PRAGMATIC</code> or <code>PGSOFT</code>. <code>true</code> on the transaction that ends the bet</td></tr><tr><td><code>tour_id</code></td><td>string</td><td>Conditional</td><td>Free tour rounds only: the <code>tour_id</code> given in <code>tour_create</code></td></tr><tr><td><code>tour_rest_count</code></td><td>integer</td><td>Conditional</td><td>Free tour rounds only: rounds left in the tour after this transaction</td></tr><tr><td><code>tour_total_win</code></td><td>number</td><td>Conditional</td><td>Free tour rounds only: what the tour has won so far, this transaction included</td></tr><tr><td><code>tour_end</code></td><td>boolean</td><td>Conditional</td><td>Free tour rounds only: <code>true</code> when the tour ends with this transaction: its last round is over, or its time ran out</td></tr><tr><td><code>bonus_id</code></td><td>string</td><td>Conditional</td><td>Bonus rounds only: the <code>bonus_id</code> given in <code>bonus_create</code></td></tr><tr><td><code>bonus_total_win</code></td><td>number</td><td>Conditional</td><td>Bonus rounds only: what the bonus has won so far, this transaction included</td></tr><tr><td><code>bonus_end</code></td><td>boolean</td><td>Conditional</td><td>Bonus rounds only: <code>true</code> on the transaction that ends the bonus round</td></tr></tbody></table>

The four `tour_*` fields are sent together, and only on free tour rounds (free tours run on `PRAGMATIC` games for now): paid rounds carry none of them. See [Free tour rounds](#free-tour-rounds).

The three `bonus_*` fields are sent together, and only on the transactions of a bonus round (see [Create Bonus](https://my.nexusggr.com/app/docs/integration/bonus-api/create-bonus)). After `bonus_end`, what the bonus did not pay comes back to your agent balance.

> **`round_id` and `txn_id`**
>
> One bet is not always one payout. A bet can play out over several **inner spins** — tumbling wins, free game rounds, the closing collect — and every one of them is sent as its own transaction.
>
> * `round_id` — one bet (integer). Every transaction that bet produces carries the same value.
> * `txn_id` — unique per inner spin (string). No two transactions ever share it.
>
> **Deduplicate on `txn_id`.** `round_id` is unique per *bet*, not per transaction, so treating it as an idempotency key makes your site drop the win of a round it already booked the bet for.

> **Warning:** **`txn_id` changed on October 15, 2026 (UTC).** Before that date it was the `round_id` as a string, shared by every transaction of one bet. Since then it carries the `txn_id_v2` value, unique per transaction. `txn_id_v2` is deprecated on October 31, 2026 (UTC): if you deduplicate on `txn_id_v2`, move to `txn_id` before then. Both carry the same value until then, so the move needs no change to the IDs you stored from October 15 on. A transaction first sent before October 15 and sent again later arrives with its `txn_id_v2` value in `txn_id`, so match it against the `txn_id_v2` you stored for it.

### Live / Sportsbook `info` field

The `info` field (top-level, for live and sportsbook) is a **stringified JSON** object with bet/result details.

**Sportsbook `info` fields:**

| Field            | Description                                                                                                                  |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `couponCode`     | Bet coupon code                                                                                                              |
| `status`         | `pending`, `won`, `lost`, `cashedout`, or `canceled`                                                                         |
| `totalOdds`      | Combined odds                                                                                                                |
| `potentialWin`   | Potential payout                                                                                                             |
| `stake`          | Bet stake                                                                                                                    |
| `payout`         | Actual payout                                                                                                                |
| `betslips`       | Array of `{ id, sportName, countryName, leagueName, matchName, homeTeam, awayTeam, marketName, oddName, oddRate, oddPoint }` |
| `settlementData` | Settlement details object                                                                                                    |

## Transaction Type Reference

`txn_type` values: `debit`, `credit`, `debit_credit`

| Type           | Description             | `bet_money`         | `win_money`         |
| -------------- | ----------------------- | ------------------- | ------------------- |
| `debit`        | Only send bet amount    | Valid               | Invalid (don't use) |
| `credit`       | Only send win amount    | Invalid (don't use) | Valid               |
| `debit_credit` | Send bet and win amount | Valid               | Valid               |

### Txn examples

One bet (`round_id`) can produce several transactions, each with its own `txn_id`.

```json
// debit — bet only
{ "txn_type": "debit", "bet_money": 2000, "win_money": 0, "round_id": 123456789, "txn_id": "64a83f2fc597acc9004eec52c3f84c30", "txn_id_v2": "64a83f2fc597acc9004eec52c3f84c30" }

// credit — win of an inner spin (same round_id, new txn_id)
{ "txn_type": "credit", "bet_money": 0, "win_money": 1500, "round_id": 123456789, "txn_id": "5c81b0af73e2496db1fa08c6d437e9a2", "txn_id_v2": "5c81b0af73e2496db1fa08c6d437e9a2" }

// credit — win of the next inner spin of that same bet
{ "txn_type": "credit", "bet_money": 0, "win_money": 400, "round_id": 123456789, "txn_id": "e04fd920a1b74c8fb2c3576ad8e1490f", "txn_id_v2": "e04fd920a1b74c8fb2c3576ad8e1490f" }

// debit_credit — the next bet, settled in one transaction
{ "txn_type": "debit_credit", "bet_money": 2000, "win_money": 1500, "round_id": 123456790, "txn_id": "a1b2c3d4e5f6789012345678abcdef01", "txn_id_v2": "a1b2c3d4e5f6789012345678abcdef01" }
```

### Free tour rounds

A free tour is played like any slot session: each of its rounds reaches your site as ordinary transactions, with `tour_id`, `tour_rest_count`, `tour_total_win` and `tour_end` added to `slot`.

* **No bet.** The tour pays its rounds, not the player: a tour round starts with `bet_money` `0`, so there is nothing to take from the player's balance. Its win comes like any other (`credit`), and you add `win_money` to the player's balance and answer with the new balance as usual. The tour's prize was taken from your agent balance when the tour was created.
* **Where the tour stands.** `tour_rest_count` and `tour_total_win` describe the tour once this transaction is applied: the rounds still to play, and what the tour has paid out so far.
* **The end.** `tour_end` is `true` on the tour's last transaction: its last round is over, or its time ran out during a round. A tour that expires between rounds, or that you cancel, sends no further transaction: what it did not pay out comes back to your agent balance (see [Create Tour](https://my.nexusggr.com/app/docs/integration/freespin-tour-api/create-tour) and [Cancel Tour](https://my.nexusggr.com/app/docs/integration/freespin-tour-api/cancel-tour)).
* **Handled like any transaction.** Deduplicate on `txn_id`. A transaction sent again carries the same tour fields.

The `slot` part of a tour of 10 rounds, `tour_id` `free_tour_777`:

```json
// round 4 starts: the tour pays it, so no bet; 6 rounds are left after it, 12,000 paid so far
{ "txn_type": "debit", "bet_money": 0, "win_money": 0,
  "round_id": 63792613432140, "txn_id": "1f6c0e9a4b2d47c3a8e5d9b07f3a6c21", "txn_id_v2": "1f6c0e9a4b2d47c3a8e5d9b07f3a6c21",
  "tour_id": "free_tour_777", "tour_rest_count": 6, "tour_total_win": 12000, "tour_end": false }

// round 4 pays 3,500 (same round_id, new txn_id): the tour has paid 15,500 now
{ "txn_type": "credit", "bet_money": 0, "win_money": 3500,
  "round_id": 63792613432140, "txn_id": "9d2f4b7e1a3c48d6b05e7f21c8a9d3e4", "txn_id_v2": "9d2f4b7e1a3c48d6b05e7f21c8a9d3e4",
  "tour_id": "free_tour_777", "tour_rest_count": 6, "tour_total_win": 15500, "tour_end": false }

// round 10, the last, wins nothing: a single transaction, and the tour ends with it
{ "txn_type": "debit_credit", "bet_money": 0, "win_money": 0,
  "round_id": 63792613432171, "txn_id": "c47e2a9f05b84d1e93a6f8b2d0e5c719", "txn_id_v2": "c47e2a9f05b84d1e93a6f8b2d0e5c719",
  "tour_id": "free_tour_777", "tour_rest_count": 0, "tour_total_win": 69960, "tour_end": true }
```

## Response

### Success

Must return the updated user balance:

```json
{
    "status": 1,
    "user_balance": 1000
}
```

The server stores `user_balance` as the user's balance (a missing or non-numeric value is stored as `0`).

### Failure

```json
{
    "status": 0,
    "msg": "INSUFFICIENT_USER_FUNDS"
}
```

`status: 0` refuses a transaction that carries a bet (`bet_money` greater than `0`): the server rolls it back on its side, and later transactions of the same `round_id` that carry no bet are refused without being sent to your site. A transaction without a bet is not refused by `status: 0`: it stays settled and is not sent again. `msg` is only logged.

No answer within 5 seconds, a network error or an HTTP status other than 2xx leaves the result unknown: the server keeps the transaction settled on its side, flags it for reconciliation, and the transaction may be sent to your site again with the same `txn_id`.
