Skip to content
For LLMsView as Markdown·

PatePlay for Operators

Add PatePlay (HTML5 slots + live tables) to your casino through OneHazel. You never speak PatePlay's wire protocol, never hold PatePlay's signing secret, and never build a PatePlay-shaped payload. You expose your platform's own native provider surface (/provider/v1/*, snake_case, int64 minor units) and point each game's launch template at PatePlay's relay. OneHazel runs the connector that translates PatePlay ⇄ your native shape.

This is a config + seed-data integration. If your platform already exposes the vendor-neutral /provider/v1/* surface (the SIM Casino reference implementation of the contract does), it is near zero-code on your side — you register the provider, mint a key, sync the catalogue, seed a few test players, and verify. The connector, the HMAC verification, the money translation, session auth, jackpots, and free/bonus bets live on OneHazel + PatePlay.

Who does what

PartyOwns
You (operator)Registering the provider; a provider_callback integrator key; the native /provider/v1/* wallet + session surface (your platform feature); the synced catalogue + launch templates on your storefront; a handful of seeded test players; verification.
OneHazelThe PatePlay connector (HMAC verify + money translation + session mapping), the relay/site provisioning, the connection that binds your operator + key + PatePlay environment, and coordinating PatePlay's certification + staging activation.
PatePlayThe game runtime + RGS, the x-api-key/x-api-hmac credential pair, the game catalogue + siteCode, the relay hosts, the hosted certification suite, and activating the staging environment.

You talk to OneHazel. OneHazel talks to PatePlay. You expose native data; OneHazel translates.

How a spin flows

PatePlay hosts the game and runs the RGS. It is a seamless (transfer) wallet: during play PatePlay's RGS calls the connector, which calls your wallet — there is no pre-funded PatePlay balance.

  player clicks Play
        │  your storefront → your backend mints a launch token (plaunch_*)

  redirect/iframe → https://<relay>/?authCode=plaunch_*&siteCode=<siteCode>&game=<code>&language=<lang>
        │  the plaunch_* IS PatePlay's authCode — no OneHazel launcher hop

  PatePlay game runtime  ── /authenticate · /balance · /withdraw · /deposit · /cancel ──┐
        │  each call signed x-api-key + x-api-hmac (HMAC-SHA256 of raw body)             │
        ▼                                                                                │
  OneHazel connector  ── verifies HMAC → resolves session → translates ─────────────────┘
        │  POST /provider/v1/{session/exchange, session/balance, wallet/bet, wallet/win, wallet/rollback}
        ▼  Authorization: Bearer <your provider_callback key>
  YOUR casino wallet  (the ledger; int64 minor units)

Two things make this work and are the only places operators get bitten:

  1. The launch token IS the authCode. Your /session/start mints a one-time launch token; you drop it straight into the relay URL as authCode. There is no launcher hop (unlike some aggregated providers) — the browser goes to the relay directly.
  2. Your surface speaks minor units; the connector converts. You emit balance_minor: 100000 (int64). The connector turns that into PatePlay's decimal string "1000.00". Never emit decimals from /provider/v1/*.

Prerequisites

  • You are a OneHazel operator (operator id / brand provisioned).
  • Your platform exposes the vendor-neutral /provider/v1/* surface — session/start, session/exchange, session/balance, wallet/bet, wallet/win, wallet/rollback, catalog/sync. The full wire contract lives in OPERATOR_API.md (the SIM Casino reference implementation you can build against).
  • An admin CMS where you can register game providers and mint integrator keys.
  • A storefront that renders your game catalogue and can redirect/iframe to a launch URL.
  • From OneHazel/PatePlay: your siteCode, the relay base for your environment, and the list of game codes.

Step 1 — Register the PatePlay provider

In your CMS, register PatePlay as a game provider with the relay base as launch_base_url (games get their per-game template in Step 3).

POST /api/v1/admin/game-providers
{ "name": "PatePlay", "slug": "pateplay", "default_currency": "EUR",
  "launch_base_url": "https://<relay-base>/" }
→ { "id": "gp_…", "slug": "pateplay", "status": "active" }

Step 2 — Mint a provider-callback key and hand it to OneHazel

Mint an integrator key with the provider_callback scope. You get the key string once — copy it immediately.

POST /api/v1/admin/integrator-keys
{ "name": "pateplay-connector", "scopes": ["provider_callback"] }
→ { "key": "sim_live_…", "last4": "…", "is_active": true }   # shown once

Give OneHazel, over a secure channel:

  • the integrator key (the credential the connector presents on every /provider/v1/* call),
  • your casino API base URL (where your /provider/v1/* surface lives — this becomes the connection's provider_base),
  • your operator identity (the OneHazel operator the connection binds to).

The key must carry the provider_callback scope

A key minted without provider_callback authenticates but is rejected on every wallet call (401). If wallet calls 401 after go-live, re-check the scope first.

Step 3 — Catalogue sync

Publish PatePlay's games to your catalogue with POST /provider/v1/catalog/sync (authed with your integrator key). Each entry's launch_url_template points at the relay with {token}/{lang} placeholders your backend fills at launch time:

https://<relay>/?authCode={token}&siteCode=<siteCode>&game=<gameCode>&language={lang}

Classify live-table codes (e.g. the auto-live-roulette-* family) as kind: "casino" and the rest as kind: "slot".

Confirm the games landed in the catalogue your storefront reads:

bash
curl -s 'https://<your-casino-api>/api/v1/public/v2/games?kind=slot&limit=500' \
  | grep -o '"provider_code":"pateplay"' | wc -l     # > 0

Re-sync to add or update games

Adding titles or changing metadata is just another catalog/sync — no operator code change. The sync upserts by the provider game code.

Step 4 — Surface the games and wire launch

Surface the catalogue

Render the synced games on your storefront from your transactional catalogue API (the same table catalog/sync writes to), not a hand-curated CMS list.

Large catalogues and the page cap

If your storefront requests more games than your catalogue endpoint returns per page, whole providers can drop below the cut and silently vanish — request the full page (e.g. limit=500) and page if you exceed it.

Wire launch (the launch-token = authCode model)

When a player clicks Play:

  1. Your storefront asks your backend to mint a launch token. The backend substitutes the template placeholders and returns a launch_url containing a single-use launch token — which is PatePlay's authCode.
  2. Your storefront redirects the browser to that launch_url (or iframes it). The browser hits the relay directly — there is no launcher exchange hop.
  3. PatePlay's runtime calls back with /authenticate (carrying the authCode), which the connector maps to your /session/exchange.

Relay query params (PatePlay Wallet 1.1, camelCase): authCode (20–255 chars, one-time), siteCode, game (default lobby), language (default en), plus optional playerId, playerName, device (desktop|mobile).

Step 5 — The wallet leg (what your surface must return)

As the player plays, PatePlay's RGS calls the connector, which calls your native surface. You implement nothing PatePlay-specific — you return native shapes and the connector converts:

PatePlay call (RGS → connector)Reaches your surface asYou return
/authenticate (authCode)POST /provider/v1/session/exchange{ session: { token }, player: { external_id, currency, balance_minor, name, country } }
/balancePOST /provider/v1/session/balance{ balance_minor, currency }
/init-gamePOST /provider/v1/session/balance (balance echo){ balance_minor, currency }
/withdraw (bet)POST /provider/v1/wallet/betdebit; { status, balance_minor }
/deposit (win)POST /provider/v1/wallet/wincredit; { status, balance_minor }
/withdraw-and-depositwallet/bet only (the 0-value deposit leg is connector bookkeeping; wallet/win fires only if the deposit leg is ever nonzero)debit; { status, balance_minor }
/cancelPOST /provider/v1/wallet/rollbackbets only (0-value deposits are cancelled connector-locally; a credited win is not cancellable)reverse the targeted bet
/check— (connector-local transaction lookup)

session.token and minor units are both load-bearing

/session/exchange MUST return both halves: session: { token } (the wallet-capable session the connector uses on every subsequent call — returning only player breaks everything downstream) and the player block with balance_minor as an int64: 100000 means €1000.00. If you emit 1000.00 or balance instead of balance_minor, the in-game balance breaks.

Step 6 — Seed and fund test players

PatePlay's certification suite and the first live launches run against real players on your platform. Seed a handful (EUR wallets), fund them, and give OneHazel their external_ids — the connector mints certification sessions for them through your existing /session/start, so no bespoke provisioning endpoint is needed.

bash
# register
POST /api/v1/public/auth/register
{ "email":"pp_test_1@…","username":"pp_test_1","password":"…",
  "first_name":"Pate","last_name":"Tester1","country":"MT","currency":"EUR" }
 { "player": { "external_id": "p_…" } }

# fund (login → deposit)
POST /api/v1/me/transactions/deposit   { "amount_minor": 100000, "method": "bank_transfer" }

Hand OneHazel the external_ids over the secure channel (never the passwords).

Step 7 — Verify end-to-end

  1. Config resolves — mint a launch token for a seeded player and a real game code; confirm the relay URL + balance ride along:
    bash
    curl -s -X POST 'https://<your-casino-api>/provider/v1/session/start' \
      -H "Authorization: Bearer <integrator-key>" -H 'Content-Type: application/json' \
      -d '{"idempotency_key":"verify1","player_external_id":"p_…","provider_slug":"pateplay","provider_game_code":"<code>","currency":"EUR","language":"en"}'
    # → { launch_token.token: "plaunch_…", launch_url: "https://<relay>/?authCode=plaunch_…", player.balance_minor: 100000 }
  2. Certification — OneHazel runs PatePlay's hosted suite against the connector; it should reach 100% with no operator change beyond what you shipped.
  3. First /authenticate — after PatePlay activates the environment, the first real /authenticate returns a session + balance; /balance, /withdraw, /deposit, /cancel complete the loop.
  4. Wallet reconciles — check the player's wallet in your admin before and after: a bet debits, a win credits, a cancel restores exactly.

The deltas that matter (PatePlay-specific rules)

  • Auth: x-api-key + x-api-hmac. Lowercase-hex HMAC-SHA256 of the raw request body, keyed by the API secret (never on the wire). Compute over the exact received bytes — never re-serialize the JSON first, or the digest drifts and verification fails with NOT_AUTHORIZED. Reproduce a vector:
    bash
    SECRET='pateplay_example_secret_0123456789'
    BODY='{"authToken":"e16e5e30-3fac-49c9-a12f-4f8d735c29d4","siteCode":"testsite","deviceType":"desktop"}'
    printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -r | cut -d' ' -f1
    # → fd0f39cade451125c24b6d42bf3ad732b592a02ba6d2be0e6723dad39e30e2e1
    OneHazel supplies the full cross-check vector set during onboarding.
  • Money: v1 is 2-decimal currencies only (EUR/USD/…). Zero-decimal currencies (KRW/VND/CLP/PYG/UGX/…) need an ISO-4217 per-currency exponent map on both the connector and the wallet/UI — a planned fast-follow, out of v1.
  • Free/bonus bets: PatePlay marks free bets inline (bonus{free:true}) — the connector does not debit the stake and credits wins per-spin via /wallet/win. If your platform mirrors issuance into a freerounds module, any settle call must carry total_win_minor = 0 — the winnings were already credited per-spin, and a positive settle value double-pays.
  • Jackpots (v1 approximation): jackpotContribution rides inside the stake; a jackpot payout is a normal /wallet/win (round_end). No native jackpot modelling required.
  • Player name/country: /session/exchange carries player.name + country for PatePlay's playerName/country. If they come back empty, the data isn't set on the player or your backend build doesn't return the fields yet — it is not a connector bug.

Troubleshooting

SymptomLikely causeFix
Game won't load: relay "took too long to respond" (TCP timeout, no HTTP status)The PatePlay environment isn't activated yet — the relay is firewalled until PatePlay's "request staging setup" step (which comes after the certification suite)Not a casino or connector bug. Complete certification → OneHazel sends PatePlay the setup pack → PatePlay activates the relay → launches resolve.
Every wallet call NOT_AUTHORIZEDHMAC computed over a re-serialized body, or wrong secretSign the raw received bytes; confirm the secret; match against the vector above.
Every wallet call 401Integrator key missing the provider_callback scope, or a wrong/revoked key in the connectionRe-mint with the scope; confirm OneHazel has the current key in the connection.
/session/exchange returns empty name/countryThe player has no name/country set, or your backend build doesn't return the fieldsSet the player fields; if data is present but the response is empty, deploy the backend build that returns them.
In-game balance shows a wrong number (e.g. 100000.00 or 10.00)Units bug: balance_minor emitted as a decimal, or ÷100 applied twiceEmit balance_minor as an int64; contact OneHazel if your surface is correct and the game still shows a wrong figure.
Games synced but don't appear on the storefrontStorefront reading a curated CMS list, or hitting the catalogue page capPoint the storefront at the transactional catalogue and request the full page (limit=500).
Duplicate-looking wallet response with "duplicate": trueA retry reused the same idempotency_key — success, not failureThe body is the original successful response; treat as accepted.

Day-2 operations

  • Rotating the integrator key — mint the new key, give it to OneHazel, have them update the connection, then revoke the old one. Allow ~30 seconds after OneHazel confirms the update before revoking — the connector briefly caches the connection's decrypted config.
  • Adding / updating games — re-run catalog/sync; verify the new titles in your public catalogue. No operator code change.
  • Zero-decimal currencies — before enabling KRW/VND/CLP/…, coordinate with OneHazel: the ISO-4217 exponent handling must land on the connector and your wallet/UI together. Out of v1.
  • Staging → production — a new PatePlay environment means a new relay base and siteCode; update launch_base_url and re-sync so templates point at the production relay.

Summary checklist

  • [ ] PatePlay provider registered (slug: pateplay, relay launch_base_url)
  • [ ] provider_callback key minted; key + casino API base URL + operator identity handed to OneHazel securely
  • [ ] catalog/sync landed; live-table codes kind: casino, rest kind: slot; titles visible in your public catalogue
  • [ ] Storefront reads the transactional catalogue (full page); launch template → <relay>/?authCode={token}&siteCode=…&game=<code>&language={lang}
  • [ ] Test players seeded + funded; external_ids handed to OneHazel
  • [ ] HMAC signing cross-checked against the vector set
  • [ ] Certification 100%; PatePlay environment activated; first /authenticate + wallet loop verified against the wallet ledger

Reference

The full vendor-neutral contract — every endpoint, the complete error table, idempotency, session semantics, money rules, and a worked reference implementation — is in OPERATOR_API.md (the SIM Casino reference implementation you can build against).

Need help?

If a game won't load, the in-game balance looks wrong, or a bet/win isn't reflected in your ledger, contact OneHazel with the game and player — OneHazel owns the PatePlay integration end-to-end and will diagnose it.