# Luiri Operator Integration Guide

This guide is for casino/operator backend teams integrating Luiri Gaming titles through signed launch sessions and server-side wallet callbacks.

## 1. Architecture

The casino site owns player login, KYC, deposits, withdrawals, and the player wallet. Luiri owns game launch, game runtime, session/round ledger, callback delivery, reconciliation, and platform fee accounting.

Flow:

1. Player opens a Luiri game inside the operator casino website.
2. Operator backend signs `POST /api/v1/launch` with its Luiri API key and secret.
3. Luiri validates signature, origin domain, game access, wallet mode, and live approval.
4. Luiri creates a short-lived session token and returns an iframe URL.
5. Unity WebGL reads `?token=...` and asks Luiri for session config.
6. Luiri calls the operator wallet for balance, debit, credit, and rollback.
7. Unity only displays returned state and animations.

## 2. Required Environment

```bash
LUIRI_BASE_URL=https://luirigaming.com
LUIRI_API_KEY=lk_live_...
LUIRI_API_SECRET=...
LUIRI_WALLET_SECRET=...
```

Never expose `LUIRI_API_SECRET` or `LUIRI_WALLET_SECRET` in browser JavaScript.

## 3. Install The SDK

The SDK is a dependency-free ESM file:

```js
import {
  createLuiriClient,
  createWalletCallbackAdapter,
  readRawBody
} from "https://luirigaming.com/sdk/luiri-node-client.mjs";
```

You may also vendor the file from `/sdk/luiri-node-client.mjs` into your backend repo.

## 4. Machine-Readable API Contract

Import the OpenAPI contract into Postman, Swagger, Insomnia, or your backend test suite:

```text
https://luirigaming.com/openapi/luiri-v1.json
https://luirigaming.com/api/v1/openapi
```

The contract covers:

- `GET /api/v1/games`
- `POST /api/v1/launch`
- Unity runtime session config and round APIs
- Operator wallet callback payloads as OpenAPI webhooks
- HMAC security headers and common error responses

## 5. What The Operator Must Build

| Area | Requirement |
|---|---|
| Backend launch route | Authenticated casino users trigger a backend call to `POST /api/v1/launch` |
| Iframe host page | Casino frontend opens only the returned `launchUrl` or `iframe` HTML |
| Wallet callbacks | HTTPS `balance`, `debit`, `credit`, and `rollback` endpoints |
| Idempotency ledger | Store `idempotencyKey`, `roundId`, `transactionId`, balance, and external reference |
| Reconciliation | Match operator wallet rows against Luiri session, round, callback, and fee-ledger rows |
| Error handling | Retry transport failures with the same key; reject duplicate financial operations |

## 6. Signed Launch

```js
import { createLuiriClient, createIdempotencyKey } from "https://luirigaming.com/sdk/luiri-node-client.mjs";

const luiri = createLuiriClient({
  apiKey: process.env.LUIRI_API_KEY,
  apiSecret: process.env.LUIRI_API_SECRET,
  baseUrl: process.env.LUIRI_BASE_URL
});

const launch = await luiri.launchGame(
  {
    gameId: "jetx-cash",
    operatorPlayerId: "player_10291",
    currency: "INR",
    locale: "en",
    originDomain: "https://casino.example",
    returnUrl: "https://casino.example/lobby"
  },
  {
    idempotencyKey: createIdempotencyKey({
      prefix: "launch",
      operatorPlayerId: "player_10291",
      sessionId: "entry",
      roundId: "initial",
      operation: "open"
    })
  }
);

console.log(launch.launchUrl);
console.log(launch.iframe);
```

The operator frontend should open only the returned iframe. It should never sign launch requests directly.

## 7. Wallet Callback Routes

Luiri calls four operator endpoints:

| Endpoint | Purpose |
|---|---|
| Balance | Return current player wallet balance |
| Debit | Deduct bet amount at round start |
| Credit | Add payout amount at winning settlement |
| Rollback | Reverse a previous debit for failed/cancelled round |

All wallet routes must:

- accept JSON `POST`
- verify `x-luiri-wallet-signature`
- return `{ "balance": number, "currency": "INR", "externalRef": "..." }`
- be idempotent using `idempotencyKey`
- reject duplicate rollback attempts with a different key

## 8. Runtime Round Flow

Unity calls Luiri runtime endpoints only after a valid launch token exists:

| Luiri endpoint | Purpose |
|---|---|
| `GET /api/game/session/{token}/config` | Reads session, game settings, balance snapshot, and bridge endpoints |
| `POST /api/game/rounds/start` | Debits operator wallet before the round animation result |
| `POST /api/game/rounds/settle` | Credits payout when the round wins and records GGR/service fee |
| `POST /api/game/rounds/rollback` | Reverses a started debit after failure/cancelled round |

The operator website should not call these runtime endpoints directly except in controlled QA tooling. In production, Unity uses them through the iframe token.

## 9. Reference Wallet Server

```bash
PORT=4100 LUIRI_WALLET_SECRET=... node operator-wallet-reference-server.mjs
```

The reference server prints:

```text
Balance URL:  http://localhost:4100/wallet/balance
Debit URL:    http://localhost:4100/wallet/debit
Credit URL:   http://localhost:4100/wallet/credit
Rollback URL: http://localhost:4100/wallet/rollback
```

For production, expose the same routes over HTTPS.

## 10. Certification And Go-Live

Before live launch is allowed:

1. Save live wallet callback URLs and wallet secret in Luiri operator portal.
2. Add the production casino domain to the allowlist.
3. Run wallet callback certification.
4. Certification must pass balance, debit, credit, and rollback in live mode.
5. Certification must be fresh within 30 days.
6. Create a sandbox iframe launch.
7. Request go-live approval.

Luiri blocks live launch if certification is missing, failed, skipped, in test mode, stale, or invalidated by wallet config changes.

## 11. Idempotency Rules

Use stable idempotency keys:

```text
wallet:{playerId}:{sessionId}:{roundId}:{operation}
```

The same request with the same key must return the original result. A repeated wallet request with a new key must be treated as a new transaction and should be rejected if it would duplicate a round debit or rollback.

## 12. API Status Codes

| Code | Meaning | Operator action |
|---|---|---|
| `200` | Request accepted | Store returned token/session/round/balance |
| `400` | Validation or lifecycle blocked | Fix request body, wallet config, live gate, or bet/session state |
| `401` | Authentication failed | Check API key, raw-body HMAC, timestamp, and secret |
| `404` | Token not found | Create a fresh launch token |
| `409` | Replay or idempotency conflict | Do not create a second financial operation |
| `429` | Launch rate limited | Back off and retry after the request window |

## 13. Reconciliation

Match records by:

- `sessionId`
- `roundId`
- `transactionId`
- `idempotencyKey`
- `externalRef`

Operators should reconcile wallet ledger rows with Luiri callback delivery logs and Luiri fee wallet statements.

## 14. Common Errors

| Error | Fix |
|---|---|
| Invalid signature | Verify raw body is unchanged before HMAC verification |
| Domain not allowed | Add exact production origin in Luiri portal |
| Wallet certification failed | Fix endpoint response/status and rerun certification |
| Duplicate rollback | Return prior result only for same idempotency key; reject new keys |
| Live launch blocked | Complete certification, sandbox launch, service wallet, and admin approval |
