> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/StakeEngine/web-sdk/llms.txt
> Use this file to discover all available pages before exploring further.

# RGS Fetcher

> Type-safe HTTP client for communicating with the Remote Game Server

The **Remote Game Server (RGS)** is the backend that manages game sessions, processes bets, and returns game books (the `state` array of ordered `bookEvent` objects). `rgsFetcher` is a thin, type-safe HTTP client that wraps all RGS communication. Response types are inferred automatically from an auto-generated OpenAPI schema, so endpoint calls are fully typed end-to-end.

## rgsFetcher.post

```typescript theme={null}
rgsFetcher.post<T extends keyof paths, TResponse>(
  options: {
    url: T;
    rgsUrl: string;
    variables?: paths[T]['post']['requestBody']['content']['application/json'];
  }
): Promise<TResponse>
```

Sends a `POST` request to `https://{rgsUrl}{url}`. The response type `TResponse` defaults to `paths[T]['post']['responses'][200]['content']['application/json']`, so you get full type inference from the schema with no manual annotation required.

Logs `console.error` if the HTTP status is not `200`.

<ParamField path="url" type="keyof paths" required>
  The RGS endpoint path. Must be one of the paths defined in `schema.ts`. TypeScript will reject any string that is not a valid key.

  Available POST paths: `'/wallet/authenticate'`, `'/wallet/balance'`, `'/wallet/play'`, `'/wallet/end-round'`, `'/bet/event'`, `'/bet/action'`, `'/session/start'`, `'/game/search'`.
</ParamField>

<ParamField path="rgsUrl" type="string" required>
  The RGS hostname (without protocol), for example `'rgs.example.com'`. The full request URL is constructed as `https://{rgsUrl}{url}`.
</ParamField>

<ParamField path="variables" type="paths[T]['post']['requestBody']['content']['application/json']">
  The request body. The type is inferred from the schema for the given `url`, so TypeScript will tell you exactly which fields are required for each endpoint.
</ParamField>

## rgsFetcher.get

```typescript theme={null}
rgsFetcher.get<T extends keyof paths, TResponse>(
  options: {
    url: T;
    rgsUrl: string;
  }
): Promise<TResponse>
```

Sends a `GET` request to `https://{rgsUrl}{url}`. Response type is inferred from the schema the same way as `post`.

Logs `console.error` if the HTTP status is not `200`.

<ParamField path="url" type="keyof paths" required>
  The RGS endpoint path.
</ParamField>

<ParamField path="rgsUrl" type="string" required>
  The RGS hostname (without protocol).
</ParamField>

## Schema and type inference

`schema.ts` is auto-generated by [openapi-typescript](https://github.com/drwpow/openapi-typescript) and should not be edited by hand. It exports a `paths` interface that maps every endpoint to its request and response shapes.

```typescript theme={null}
// Auto-inferred — no type annotation needed
const data = await rgsFetcher.post({
  url: '/wallet/authenticate',
  rgsUrl: 'rgs.example.com',
  variables: { sessionID: 'abc-123', language: 'en' },
});
// data is typed as components['schemas']['res_authenticate']
```

## RGS endpoints

The following endpoints are defined in `schema.ts`.

### POST /wallet/authenticate

Validates a `sessionID` with the operator. Must be called at game start before any other wallet action.

**Request body** (`req_authenticate`):

<ParamField path="sessionID" type="string (uuid)" required>
  The session ID passed to the game iframe via URL parameters.
</ParamField>

<ParamField path="language" type="string">
  RGS game language.
</ParamField>

**Response** (`res_authenticate`): includes `status`, `balance`, `round` (the active bet, if any), and `config` (bet levels, modes, and jurisdiction settings).

***

### POST /wallet/balance

Fetches the current player balance. Most other wallet responses already include the balance, so this endpoint is typically used only for periodic polling.

**Request body** (`req_Balance`): `{ sessionID }`

**Response** (`res_Balance`): `{ balance, status, error }`

***

### POST /wallet/play

Triggers a play (debit). The player's balance is reduced by `amount` and the RGS returns the game result in `round.state`.

**Request body** (`req_play`):

<ParamField path="sessionID" type="string (uuid)" required>
  Active session ID.
</ParamField>

<ParamField path="amount" type="number" required>
  Bet amount as an integer. Currency is an integer — `1000` represents `$10.00`. Multiply the player-facing bet by `API_AMOUNT_MULTIPLIER` before sending.
</ParamField>

<ParamField path="currency" type="string" required>
  Currency code (e.g. `'USD'`).
</ParamField>

<ParamField path="mode" type="string" required>
  Bet mode (e.g. `'BASE'`, `'SUPERSPIN'`). Valid modes are defined per-game in the `config` returned by `/wallet/authenticate`.
</ParamField>

<ParamField path="meta" type="Record<string, never>">
  Optional metadata passed through to the game without RGS validation.
</ParamField>

**Response** (`res_play`): `{ status, balance, round, error }`. The book of events is at `round.state`.

***

### POST /wallet/end-round

Closes the active round. No further actions can be made for this round; the RGS sends a payout request to the operator.

**Request body** (`req_end_round`): `{ sessionID }`

**Response** (`res_end_round`): `{ balance, status, error }`

***

### POST /bet/event

Tracks progress through a bet. Sends an event string that is saved to the RGS database alongside the bet. Used by `recordBookEvent` to checkpoint which book event the client has processed.

**Request body** (`req_event`):

<ParamField path="sessionID" type="string (uuid)" required>
  Active session ID.
</ParamField>

<ParamField path="event" type="string">
  An arbitrary event string. In practice this is the `bookEvent.index` cast to a string.
</ParamField>

**Response** (`res_event`): `{ event, status, error }`

***

### POST /bet/action

Triggers an additional in-round action for games that support them (e.g. a "gamble" or "hold" decision). The `action` field determines whether the RGS sends an additional bet to the operator (`BET`) or routes the request directly to the game (`DECISION`).

**Request body** (`req_action`):

<ParamField path="sessionID" type="string (uuid)" required>
  Active session ID.
</ParamField>

<ParamField path="action" type="string" required>
  Action type: `'BET'` or `'DECISION'`.
</ParamField>

<ParamField path="meta" type="Record<string, never>">
  Optional metadata.
</ParamField>

**Response** (`res_action`): `{ status, balance, action, error }`

***

### POST /session/start

Operator-facing endpoint. An operator calls this to start a session and receive a game iframe URL. Send this request to the **mock-casino endpoint** of the environment, not the RGS directly.

**Request body** (`req_sess_start`):

<ParamField path="currency" type="string" required>
  Currency the player is playing in.
</ParamField>

<ParamField path="token" type="string | object" required>
  A session token from the casino side.
</ParamField>

<ParamField path="balance" type="BalanceObject">
  Starting balance. Defaults to `100000` (= \$1000.00).
</ParamField>

<ParamField path="setBalance" type="boolean">
  When `true`, sets the player's balance to the value in `balance`. Defaults to `false`.
</ParamField>

**Response** (`res_sess_start`): `{ url, error }` — the `url` is passed into the game iframe.

***

### POST /game/search

Searches for game books matching criteria. Used internally for development tooling.

**Request body** (`req_search`): `{ mode, search }` where `search` accepts `bookID`, `kind`, `symbol`, `hasWild`, `wildMult`, `gameType`.

**Response** (`res_search`): `{ balance, round, error }`

## Error handling

When the RGS returns a non-200 HTTP status, `rgsFetcher` logs the error to the console:

```typescript theme={null}
if (response.status !== 200) console.error('error', response);
```

It does not throw. The caller receives whatever JSON the server returned. Check `response.status?.statusCode` in the returned data for application-level errors. The `StatusCode` enum covers the following values:

| Code      | Meaning                                                   |
| --------- | --------------------------------------------------------- |
| `SUCCESS` | Operation completed successfully                          |
| `ERR_SCR` | Invalid secret                                            |
| `ERR_OPT` | Invalid operator ID                                       |
| `ERR_IPB` | Insufficient player balance                               |
| `ERR_IS`  | Invalid session token / session timeout                   |
| `ERR_ATE` | Failed user authentication / authentication token expired |
| `ERR_GLE` | Gambling limits exceeded                                  |
| `ERR_BNF` | Bet not found                                             |
| `ERR_BE`  | Player already has an active bet                          |
| `ERR_UE`  | General server error (with rollback)                      |
| `ERR_GE`  | General server error (without rollback)                   |

## Usage example

The higher-level `rgs-requests` package wraps `rgsFetcher` into named functions. Prefer these over calling `rgsFetcher` directly.

```typescript theme={null}
import {
  requestAuthenticate,
  requestBet,
  requestEndRound,
  requestEndEvent,
} from 'rgs-requests';

// 1. Authenticate on game load
const auth = await requestAuthenticate({
  sessionID,
  rgsUrl,
  language: 'en',
});

const config = auth.config; // bet levels, modes, jurisdiction flags
const activeRound = auth.round; // resume an interrupted round, if any

// 2. Place a bet
const bet = await requestBet({
  sessionID,
  rgsUrl,
  currency: 'USD',
  amount: 1.00,  // multiplied by API_AMOUNT_MULTIPLIER before sending
  mode: 'BASE',
});

const bookEvents = bet.round?.state; // the ordered list of game events

// 3. Play through all book events
await playBookEvents(bookEvents);

// 4. Record the final event index
await requestEndEvent({
  sessionID,
  rgsUrl,
  eventIndex: bookEvents.at(-1).index,
});

// 5. End the round
await requestEndRound({ sessionID, rgsUrl });
```

### Calling rgsFetcher directly

If you need to call an endpoint not covered by `rgs-requests`, use `rgsFetcher` directly:

```typescript theme={null}
import { rgsFetcher } from 'rgs-fetcher';

const result = await rgsFetcher.post({
  url: '/bet/action',
  rgsUrl: 'rgs.example.com',
  variables: {
    sessionID: 'abc-123',
    action: 'DECISION',
  },
});
```

## BetType utility

The `rgs-requests` package also exports a `BetType<TBookEvent>` utility for typing the `round` field of a bet response with your game's specific `BookEvent` union:

```typescript theme={null}
import type { BetType } from 'rgs-requests';
import type { BookEvent } from './typesBookEvent';

// round.state is typed as BookEvent[]
type Bet = BetType<BookEvent>;
```
