Integration Guide · API version 1.0
Gregmorn Hub API
Everything you need to connect your casino platform to Gregmorn Hub: authentication, the game catalog, game sessions, seamless wallet callbacks and the transfer wallet.
Getting started
Stage Start hereBuild and test your integration on Stage. Move to Prod only after acceptance.
Prod Separate setupStage and Prod are fully separate: logins, secret keys and IP allowlists are issued per environment.
Send these to your account manager before integration begins:
Callback URL for seamless wallet callbacks.
IP addresses for allowlisting — separate lists for Stage and Prod.
Stage currency list. Callback URLs are configured per currency.
Seamless wallet
The provider calls your wallet — getBalance, writeBet, rollback — signed with X-Signature.
Callback reference →
Group Sections
Common API Auth, Game Catalog, Game Session
Seamless wallet (callbacks) Webhooks
Transfer wallet (merchant-initiated) Transfer Wallet
Base URL Description
https://office-api-dev.gregmorn.orgSTAGE — auth and game list
https://client-api-dev.gregmorn.orgSTAGE — open game
https://twalletvault.api.games-hub.netTransfer wallet command endpoint
Authentication & signing
The office API uses bearer tokens. Game launch, webhooks and the transfer wallet use an HMAC-SHA256 signature of the request body.
Used for endpoints in the Auth and Game Catalog groups. Obtain an accessToken via POST /auth/login , then send it on every request:
Authorization: Bearer <accessToken>
Context Signature
Webhooks / openGame Hex HMAC-SHA256 over the raw JSON body bytes using the user secret.
Transfer wallet Hex HMAC-SHA256 over the exact raw JSON body using the player-specific secret_api_key.
Sign the exact bytes you send. Serialize the JSON once, sign that string, and send the same string as the body. Re-serializing after signing (reordered keys, extra spaces) will break the signature.
Signing examples
Compute X-Signature
Node.js
Python
PHP
Copy
const crypto = require('crypto' );
const body = JSON.stringify(payload); // send exactly this string
const signature = crypto
.createHmac('sha256' , secret)
.update(body)
.digest('hex' );
// headers: { 'Content-Type': 'application/json', 'X-Signature': signature }
import hmac, hashlib, json
body = json.dumps(payload, separators=("," , ":" )).encode() # send exactly these bytes
signature = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
# headers = {"Content-Type": "application/json", "X-Signature": signature}
$body = json_encode($payload); // send exactly this string
$signature = hash_hmac('sha256' , $body, $secret);
// Verifying an incoming callback:
$raw = file_get_contents('php://input' );
$ok = hash_equals(hash_hmac('sha256' , $raw, $secret), $_SERVER['HTTP_X_SIGNATURE' ] ?? '' );
Common API
Authenticate, fetch the game catalog for a currency, and open a game session for a player.
POST /auth/login
Obtain access token (login)
https://office-api-dev.gregmorn.org
No auth
Login endpoint. Returns an access token, a refresh token and user info.
Request
URL: POST https://office-api-dev.gregmorn.org/auth/login
Content-Type: application/x-www-form-urlencoded
Body fields: login, password
Important: accessToken has a limited TTL. After expiry, call /auth/login again.
Common error: do not send JSON here. Use application/x-www-form-urlencoded, otherwise expect HTTP 400 or 401.
Response
200 returns LoginResponse .
{
"login": "casino_operator",
"password": "Qx9#mK2!pLnR"
}Field values shown as JSON for readability — send them form-encoded.
curl -X POST https://office-api-dev.gregmorn.org/auth/login \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "login=casino_operator" \
--data-urlencode "password=Qx9#mK2!pLnR"
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0ODFlM2M5Yi03N2YyLTRkMWEtYjgzMi05YzVlMGY4YTJkMTQiLCJsb2dpbiI6ImNhc2lub19vcGVyYXRvciIsInJvbGUiOiJVc2VyIiwiaWF0IjoxNzQ1NzQ4MDAwLCJleHAiOjE3NDU4MzQ0MDB9.Xk2mN9pQrL4vJsT8hDfW3uCbYoKgP7nAeRtMzIqVl5c",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0ODFlM2M5Yi03N2YyLTRkMWEtYjgzMi05YzVlMGY4YTJkMTQiLCJ0eXBlIjoicmVmcmVzaCIsImlhdCI6MTc0NTc0ODAwMCwiZXhwIjoxNzQ2MzUyODAwfQ.mP3qRsNvTcYdJkW8xBfL2eAoGhI9ZuQlXrKtDyEwH6n",
"user": {
"id": "481e3c9b-77f2-4d1a-b832-9c5e0f8a2d14",
"login": "casino_operator",
"role": "User",
"currencies": [
{ "currency": "USD", "count": "12450.00" },
{ "currency": "EUR", "count": "8320.50" }
]
}
}
Bad Request — typically caused by sending JSON instead of form-encoded fields.
GET /users/{user_id}/getUserGames/{currencyISO}
Get user games by currency
https://office-api-dev.gregmorn.org
Authorization: Bearer <accessToken>
Returns the list of games available to the user for the given currency.
Path parameters
Name Type Description
user_id required string API user ID.
currencyISO required string Currency in ISO format (e.g., USD, EUR).
Response
200 returns an array of GameCatalogItem .
Request Copy
curl https://office-api-dev.gregmorn.org/users/481e3c9b-77f2-4d1a-b832-9c5e0f8a2d14/getUserGames/USD \
-H "Authorization: Bearer <accessToken>"
Response
200
400
401
Copy
[
{
"id": "integration_a:provider_a:game_001",
"isEnabled": true,
"title": "Fortune Tiger",
"imageUrl": "https://static.gregmorn.org/games/provider_a/game_001_288x210.jpg",
"provider": "PG Soft"
},
{
"id": "integration_b:provider_b:game_042",
"isEnabled": true,
"title": "Speed Roulette",
"imageUrl": "https://static.gregmorn.org/games/provider_b/game_042_288x210.jpg",
"provider": "Evolution"
}
]
Unauthorized — missing or expired access token. Call /auth/login again.
POST /games/openGame
Open game
https://client-api-dev.gregmorn.org
X-Signature · no access token
Opens a game session and returns the game URL.
Requires X-Signature over the raw JSON body.
demo = "1": demo mode, no wallet callbacks.
demo = "0": real gameplay.
callbackUrl: optional override for the admin-panel callback URL.
ip: optional player IP. Required only for some providers — ask support if your provider requires it.
Headers
Name Description
X-Signature required Hex HMAC-SHA256 over raw JSON body bytes using the user secret.
Body
OpenGameRequest — returns OpenGameResponseSuccess or ErrorOpenGame .
Request · real mode with explicit callback URL Copy
{
"currency": "USD",
"demo": "0",
"exitUrl": "https://casino.example.com/lobby",
"gameId": "integration_a:provider_a:game_001",
"language": "en",
"player_login": "alex_morozov_88",
"user_id": "481e3c9b-77f2-4d1a-b832-9c5e0f8a2d14",
"ip": "8.8.8.8",
"callbackUrl": "https://casino.example.com/api/wallet/callback"
}
Response
200
400
409
Copy
{
"status": "success",
"error": "",
"content": {
"game": {
"url": "https://client-api-dev.gregmorn.org/game/pgsoft/fortune-tiger?session=7d3b9e2a-4f1c-8d06-a912-c3e5f7b29041¤cy=USD&lang=en&exit=https%3A%2F%2Fcasino.example.com%2Flobby"
},
"gameRes": {
"sessionId": "7d3b9e2a-4f1c-8d06-a912-c3e5f7b29041"
}
}
}
{
"status": "fail",
"error": "unauthorized",
"code": 409,
"message": "user_id is required"
}
Webhooks — seamless wallet callbacks
The provider calls your callback URL. You hold the balance; every bet, win and rollback is applied by your wallet.
Direction: provider → merchant.
Every callback includes X-Signature — HMAC-SHA256 over the raw body.
Use transactionId as the idempotency key.
Duplicate successful writeBet: return the current balance, do not apply again.
Important: if getBalance returns HTTP 400, do not start the spin. Do not use a default or cached balance.
POST /webhooks/getBalance
Balance callback
Provider → your callback URL
X-Signature
The provider asks for the current player balance.
Requires X-Signature.
Return HTTP 200 + status: "success" only when the balance is confirmed.
Important: HTTP 400 means fail / retry. Do not start the spin. Do not use a default or cached balance.
Headers
Name Description
X-Signature required Hex HMAC-SHA256 over raw JSON body bytes using the user secret.
Body: CallbackGetBalanceRequest · Response: CallbackGetBalanceResponse
Request Copy
{
"cmd": "getBalance",
"login": "alex_morozov_88",
"sessionid": "7d3b9e2a-4f1c-8d06-a912-c3e5f7b29041"
}
Your response
200
400
Copy
{
"balance": 2500,
"currency": "USD",
"error": "",
"login": "alex_morozov_88",
"status": "success"
}
{
"balance": 0,
"currency": "USD",
"error": "player not found",
"login": "alex_morozov_88",
"status": "fail"
}Other cases: unknown_session
POST /webhooks/writeBet
Bet / win callback
Provider → your callback URL
X-Signature
Apply a bet and/or win to the merchant wallet.
Rules
Accept: HTTP 2xx + status: "success".
Reject: HTTP 400+ + status: "fail".
Idempotency key: transactionId.
Duplicate successful transactionId: return HTTP 200 with the current balance, do not apply again.
Important: if the player balance is insufficient for the bet, reject writeBet. Providers do not calculate or reserve funds using getBalance.
Important: the balance in a successful response must be the balance after applying the operation, not before.
bet and win may arrive as numbers or strings — SL-Games and X-Games send strings. Support both.
Headers
Name Description
X-Signature required Hex HMAC-SHA256 over raw JSON body bytes using the user secret.
Body: CallbackWriteBetRequest · Response: CallbackWriteBetResponse
Request · player places a bet (25.00 USD) Copy
{
"cmd": "writeBet",
"bet": 25,
"win": 0,
"login": "alex_morozov_88",
"sessionid": "7d3b9e2a-4f1c-8d06-a912-c3e5f7b29041",
"transactionId": "txn_a3f7c912-d0e5-b841-9f2c-3e6a7d8b01c4",
"round_finished": false,
"info": "{\"gameType\":\"slots\",\"betPerLine\":1.25,\"lines\":20,\"roundId\":\"r_9f4a2c7b\"}"
}Other examples: round_finished_win, bet_and_win_together
Your response
200
400
Copy
{
"balance": 2475,
"currency": "USD",
"error": "",
"login": "alex_morozov_88",
"status": "success"
}Other cases: after_win, after_bet_and_win, duplicate
{
"balance": 5,
"currency": "USD",
"error": "insufficient funds",
"login": "alex_morozov_88",
"status": "fail"
}
POST /webhooks/rollback
Rollback callback
Provider → your callback URL
X-Signature
Roll back the original bet.
transactionId must match the original bet transaction ID.
Restore the balance only once.
Headers
Name Description
X-Signature required Hex HMAC-SHA256 over raw JSON body bytes using the user secret.
Body: CallbackRollbackRequest
Request Copy
{
"cmd": "rollback",
"bet": 25,
"win": 0,
"login": "alex_morozov_88",
"sessionid": "7d3b9e2a-4f1c-8d06-a912-c3e5f7b29041",
"transactionId": "txn_a3f7c912-d0e5-b841-9f2c-3e6a7d8b01c4",
"round_finished": true,
"info": "{\"reason\":\"provider_timeout\",\"originalRound\":\"r_9f4a2c7b\"}",
"gameId": "integration_a:provider_a:game_001"
}
Your response
200
400
Copy
{
"balance": 2500,
"currency": "USD",
"error": "",
"login": "alex_morozov_88",
"status": "success"
}Balance restored after rollback.
{
"balance": 0,
"currency": "USD",
"error": "unknown session",
"login": "alex_morozov_88",
"status": "fail"
}Other cases: already_rolled_back
Transfer wallet (merchant-initiated)
Transfer wallet: merchant → Gregmorn Hub. You move funds in and out of the player's wallet; there are no callbacks.
Wallet commands userCreate, userCash, userInfo
Report commands reportBet, sessionList, sessionLog
Endpoint: POST /apiIndividualWallet/. Signing uses the same X-Signature flow as openGame and webhooks.
POST /apiIndividualWallet/
Transfer wallet command endpoint
https://twalletvault.api.games-hub.net
X-Signature · no bearer token
Single entry point for transfer wallet operations. Required base fields: cmd, user_id.
Commands
cmd Description
userCreate Create player wallet.
userCash Change balance (operation = in | out).
userInfo Return current balance.
reportBet Return aggregated bet/win statistics for one day.
sessionList Return game sessions for the requested date range.
sessionLog Return spin-by-spin details for one session.
Signing
Header: X-Signature
Secret: player-specific secret_api_key, resolved by user_id
Payload: exact raw JSON body bytes
Algorithm: HMAC-SHA256, hex digest
Notes
user_login is required for userCreate, userCash, userInfo and can be used as an optional filter for sessionList.
currency selects the player wallet currency for userCreate, userCash, userInfo; default is USD.
userCash.cash must be a decimal string with up to 2 fractional digits.
Report commands use the same signature model and can request only the last 10 days .
Report totals are calculated from writeBet transactions and adjusted by rollback transactions.
Body: TransferWalletRequest · Response: TransferWalletResponse
Request · create player wallet Copy
{
"cmd": "userCreate",
"user_login": "test_player",
"user_id": "481e3c9b-77f2-4d1a-b832-9c5e0f8a2d14",
"currency": "EUR"
}Other examples: user_cash_in, user_cash_out, user_info, report_bet, session_list, session_log
Response
200
400
500
Copy
{
"status": "ok",
"microtime": 0.004074077606201,
"date_time": "2024-04-12 12:01:40",
"error": "",
"content": {
"id": "test_player",
"player_login": "test_player",
"cash": "0.00"
}
}Command result. Other cases: user_cash_in, user_cash_out, user_info, report_bet, session_list, session_log
{
"status": "error",
"microtime": 0.00042104721069336,
"date_time": "2024-04-12 12:05:02",
"error": "missing X-Signature header",
"content": {
"player_login": "test_player"
}
}Invalid request or business error. Other cases: invalid_signature, insufficient_funds
{
"status": "error",
"microtime": 0.0015549659729004,
"date_time": "2024-04-12 12:06:54",
"error": "internal error",
"content": {
"player_login": "test_player"
}
}Internal server error.
Key data schemas
Reference of the main request and response objects used across the API. required marks mandatory fields.