# Vecto Games — Integration Reference (for coding agents)

Everything needed to integrate the Vecto game catalogue into a casino, in one
self-contained document. You integrate **once** and every game works; only the
`game` code changes.

**Model:** a standard seamless (transactional) wallet integration. **You keep the
player's money.** Vecto hosts the game, RNG and provably-fair engine in an iframe
and calls **your** wallet endpoint in real time to debit a bet and credit a win.

- API base URL: `https://api.vectogames.com`
- Sign up / get keys: `https://client.vectogames.com/sign-up`
- Company + catalogue overview: `https://vectogames.com/llm.md`

---

## 1. Auth & money

- **Operator → Vecto calls:** send your key as the header `X-API-Key: <apiKey>`.
- **Money:** every amount is an **integer in minor units at ×100000** (5 implied
  decimals). `$1.00 = 100000`, `$3.56 = 356000`, `$100.00 = 10000000`. This scale
  supports crypto denominations.
- **Signing (optional, recommended in production):** requests and callbacks can be
  HMAC-signed. Headers: `X-Vecto-Timestamp: <unix seconds>` and
  `X-Vecto-Signature: hex(HMAC_SHA256(secretKey, "<timestamp>.<rawBody>"))`.
  Reject if `|now - timestamp| > 300s`.

## 2. Games catalogue

| `game` | type | mechanic |
|---|---|---|
| `elevator` | crash | climbing multiplier; cash out before the breakdown floor |
| `storm` | crash (live multiplayer) | predict which city the storm strikes |
| `wander` | crash | cross lanes for a higher multiplier; selectable difficulty |
| `tunnel` | crash | descend a mine; deeper = higher; cash out before collapse |
| `paradrop` | crash (continuous) | multiplier climbs as the plane drops; optional risky ceiling |
| `crown-of-anuket` | slot (1024 ways) | ways slot with free spins + buy-feature (in development) |

`GET /api/games` returns the live catalogue and each game's configured RTP.

## 3. Launch a game session (server → server)

`POST https://api.vectogames.com/api/sessions` with `X-API-Key`.

```jsonc
// request
{
  "game": "elevator",             // one of the game codes above
  "playerId": "op-player-42",     // YOUR player id
  "currency": "USD",
  "language": "en",               // optional, ISO-639-1; default "en"
  "mode": "real",                 // "real" | "demo" (demo never calls your wallet); default "real"
  "returnUrl": "https://casino.example/lobby", // optional
  "nickname": "luckyMax"          // optional
}
// 200 response
{
  "token": "ses_3f2a…",           // opaque, single player + game, short-lived to open
  "launchUrl": "https://api.vectogames.com/play/elevator?token=ses_3f2a…&lang=en",
  "expiresAt": "2026-06-06T12:05:00Z"
}
```

## 4. Embed the game

```html
<iframe src="<launchUrl>" allow="autoplay; fullscreen" allowfullscreen
  sandbox="allow-scripts allow-same-origin allow-popups"
  style="width:100%;height:100%;border:0" title="Vecto game"></iframe>
```

**Keep `allow="fullscreen"`.** An iframe is denied fullscreen by default, so
without it the browser blocks every fullscreen request from inside the frame and
the in-game fullscreen button does nothing for your players. If you cannot add
the attribute, listen for the `fullscreen` message below and call
`iframe.requestFullscreen()` from your own page instead.

Responsive on desktop + mobile. Optional `&fit=width` on the launch URL fills the
slot width; omit for contain (letterbox). The game posts messages to your page:
`{ source: "vecto", type, game, ...payload }` — check `data.source === "vecto"`
and switch on `data.type`:

| `type` | payload | when |
|---|---|---|
| `ready` | — | game loaded |
| `balance` | `{ balance }` | balance changed (minor units) |
| `round` | `{ roundId, bet, payout, win, multiplier }` | round settled |
| `error` | `{ message }` | unrecoverable error |
| `fullscreen` | — | player tapped fullscreen but the frame is not allowed to fullscreen itself; call `iframe.requestFullscreen()` |

## 5. Seamless wallet — the endpoint YOU implement

Vecto `POST`s JSON to your wallet URL for every money movement. Each call carries
your `operatorId`, is signed (§1), and is **idempotent by `transactionId`**.
Respond `200` with `{ "balance": <minor units> }` or `{ "error": { "code": "…" } }`.

```jsonc
// balance →   { "type":"balance", "operatorId":"…", "playerId":"…", "currency":"USD" }
//        ←   { "balance": 1000000000 }

// bet (debit, synchronous — reject/timeout ⇒ round does not start)
//    →   { "type":"bet", "operatorId":"…", "playerId":"…", "currency":"USD",
//          "amount":10000000, "game":"elevator", "roundId":"rnd_…",
//          "transactionId":"txn_bet_…" }
//    ←   { "balance": 990000000 }                     // or { "error": { "code":"INSUFFICIENT_FUNDS" } }

// win (credit; amount 0 on a loss)
//    →   { "type":"win", "operatorId":"…", "playerId":"…", "currency":"USD",
//          "amount":36000000, "game":"elevator", "roundId":"rnd_…",
//          "transactionId":"txn_win_…", "betTransactionId":"txn_bet_…", "multiplier":3.6 }
//    ←   { "balance": 1026000000 }

// rollback (void a bet after a technical failure; idempotent)
//    →   { "type":"rollback", "operatorId":"…", "playerId":"…", "currency":"USD",
//          "game":"elevator", "roundId":"rnd_…", "transactionId":"txn_rb_…",
//          "betTransactionId":"txn_bet_…" }
//    ←   { "balance": 1000000000 }
```

**Idempotency (critical):** store every `transactionId`; on a repeat, return the
original result without moving money again. `win`/`rollback` are retried with
backoff until acknowledged, so they must be idempotent. The `error` `code` you
return is free-form (any string is treated as a bet rejection); signal insufficient
funds so a top-up prompt can show.

## 6. Settlement webhook (optional, for reconciliation)

If you configure a webhook URL, Vecto `POST`s a signed `round.settled` event after
each round (not for moving money — that already happened in §5). Ack with `2xx`;
non-2xx retries with backoff, so be idempotent on `roundId`.

```jsonc
{ "event":"round.settled", "operatorId":"…", "playerId":"…", "game":"elevator",
  "roundId":"rnd_…", "currency":"USD", "bet":10000000, "payout":36000000,
  "win":true, "multiplier":3.6, "betTransactionId":"txn_bet_…",
  "winTransactionId":"txn_win_…", "occurredAt":"…",
  "fairness": { "serverSeed":"…", "serverSeedHash":"…", "clientSeed":"…", "nonce":1287 } }
```

## 7. Free bets / free spins (optional)

Grant a player house-funded rounds. A free round places **no stake on your wallet**
(no `bet` callback); any win is paid capped at an optional `max_win` and flagged in
the `win` callback with `"freebet": true`, `"offer_reference": <n>`, `"bonus_buy": <bool>`.
All endpoints are `POST` with `X-API-Key`; money is ×100000.

```jsonc
// grant N free rounds to one player
POST /api/freebet/grants/create
{ "user":"op-player-42", "game_code":"tunnel", "bet_value":100000, "bet_count":5,
  "max_win":5000000, "bonus_buy":false, "operator_reference":"promo-abc" }
// → { "grant_uuid":"…", "reference":42, "remaining_count":5, "status":"ACTIVE", … }
```

Other endpoints: `grants/create_bulk` (up to 100 players), `grants/list`,
`grants/status`, `grants/cancel` (only if unused); and offer templates
`offers/create`, `offers/list`, `offers/assign`. `operator_reference` is your
idempotency key. Grant status: `ACTIVE → FINISHED | CANCELLED | EXPIRED | FAILED`.

## 8. Provably fair

Each round commits `SHA-256(serverSeed)` before play and reveals `serverSeed`
after (in the webhook and reporting). Recompute any outcome:

```
POST https://api.vectogames.com/api/verify
{ "game":"tunnel", "serverSeed":"…", "clientSeed":"…", "nonce":1287 }
```

Pass the round's extra reveal fields where relevant: `difficulty` (wander),
`rtp` (tunnel), `rtp` + `risky` (paradrop). Players can also verify in-game.

## 9. Reporting (server → server, `X-API-Key`)

- `GET /api/operators/me` — your account.
- `GET /api/games` — games + live RTP.
- `POST /api/games/rtp` — set a game's RTP (92 / 95 / 97 / 99%).
- `GET /api/rounds?from=&to=&game=&playerId=` — round history + fairness.
- `GET /api/transactions` — bet/win/rollback ledger.
- `GET /api/stats` — staked, paid, GGR, bet count, realized RTP.

## 10. Go-live checklist

- [ ] Keys issued; `secretKey` server-side only.
- [ ] Wallet endpoint implements `balance`/`bet`/`win`/`rollback`, **idempotent**, verifies signatures.
- [ ] Launch → iframe → `postMessage` handled.
- [ ] Currencies, bet limits and RTP configured (back office).
- [ ] Tested in `demo` (no wallet) then `real`.
- [ ] Optional: webhook acked; IP allowlist + signature enforced.

Questions or onboarding: partners@vectogames.com.
