API Documentation
Complete integration guide for operators to implement callback endpoints and launch ExaGaming games seamlessly.
Integration Process
Implement Endpoints
Create 6 callback endpoints: authenticate, bet, win, rollback, game-close, and funds
Configure Hostname
Provide Exa with your callback server hostname and path appendage
Add Branding
Optionally provide a logo URL for game branding (optional)
Receive Credentials
Exa provides secret key and operator_id for secure communication
Basic Terminology
PLAYER ACCESS TOKEN
Token created and passed as query parameter on launch game URL. Bets can be placed until token expires. Win and rollback are accepted even after expiry.
OPERATOR
Customer's project (e.g., brand/casino) that integrates games by API.
X-OPERATOR-ID
ID of the operator received in the header during API calls.
X-OPERATOR-SIGNATURE
HMAC SHA256 hashed value for request validation.
Server Information
| Environment | Server Type | URL |
|---|---|---|
|
Production
|
API Server | user-api.exagaming.com |
|
Production
|
Games Server | user.exagaming.com |
|
Staging
|
API Server | user-api-staging.exagaming.com
|
|
Staging
|
Games Server | user-staging.exagaming.com
|
|
Development
|
API Server | user-api-dev.exagaming.com
|
|
Development
|
Games Server | user-dev.exagaming.com |
Building Game Catalogue
Retrieve game metadata to construct game access URLs and view available games.
<ENV_URL>/api/v1/operator/<operator_id>/game-list
No authentication required
{
"data": [
{
"id": 2,
"gameCategory": "crash_game",
"name": "Follow The Arrow",
"launchUrl": "/follow-the-arrow",
"thumbnailUrl": "example.com/follow-the-arrow.jpg",
"isActive": true,
"settings": {
"minOdds": 1,
"maxOdds": 100,
"minAutoRate": 1.01
}
}
]
}
Response Fields
| Field | Type | Description | Required |
|---|---|---|---|
id
|
Number | ID of the game |
Yes
|
gameCategory
|
String | Category: crash_game, slot_game, fast_game |
Yes
|
name
|
String | Display name of the game |
Yes
|
launchUrl
|
String | URL appendage to launch the game |
Yes
|
thumbnailUrl
|
String | Thumbnail image URL |
No
|
isActive
|
Boolean | Is game currently active |
Yes
|
settings
|
Object | Game-specific settings |
No
|
Launching a Game
To launch a game, make a POST request to the launch endpoint. The API returns a launch URL that can be used in an iframe or as a direct redirection target.
https://user-api.exagaming.com/api/v1/game/launch
Content-Type: application/json
Request Parameters
| Field | Type | Description | Required |
|---|---|---|---|
gameId
|
Integer | ID of the game to launch |
Yes
|
token
|
String | Player session token |
Yes
|
currency
|
String | Currency code (e.g., EUR, USD) |
Yes
|
operator
|
Integer | Your assigned operator ID |
Yes
|
lang
|
String | Language code (default is 'en') |
No
|
isDemo
|
Boolean | Set to true for fun/demo mode launch |
No
|
{
"gameId": 13,
"token": "ecd263727ae055f74fdf...",
"currency": "EUR",
"operator": 1,
"lang": "en",
"isDemo": false
}
{
"status": "success",
"message": "Launch URL generated",
"timestamp": "2025-07-12T00:00:00.000Z",
"data": {
"launchUrl": "https://games...",
"token": "ecd263727...",
"currency": "EUR",
"lang": "en",
"operator": 1
}
}
Error Responses
| Code | Message | Description |
|---|---|---|
|
400
|
Missing required parameter | One or more required fields were not sent |
|
401
|
Invalid or expired token | Authentication failed for session token |
|
500
|
Internal Server Error | Something went wrong on the server |
Important Notes
- Ensure the session token is valid and associated with an active player
- The generated launchUrl can be used in an iframe or as a direct redirection target
- Default language is 'en' if lang is not specified
Salient Features
Multiple Games per User
The system allows a single player to run multiple games simultaneously. Operators are responsible for maintaining proper token/user relationships.
Idempotency of Transactions
Methods with transactionId should be idempotent. If called with the
same ID, return the same result without new transactions.
Response Statuses
status: 0 indicates
success.status: > 0 indicates an error (see
Error Codes).
Callback API Endpoints
Implement these 6 endpoints on your server. Include x-operator-id andx-operator-signature headers. Return 200 OK.
/authenticate
Authenticate the token and get player info. Must return the same user ID for a particular player regardless of token changes.
Request Fields
| Field | Type | Description | Required |
|---|---|---|---|
token
|
String | The operatorUserToken generated at login |
Yes
|
Headers
| Field | Type | Description | Required |
|---|---|---|---|
x-operator-id
|
Number | Operator ID |
Yes
|
x-operator-signature
|
String | HMAC_SHA_256 signature |
Yes
|
Response Fields
| Field | Type | Description | Required |
|---|---|---|---|
status
|
Number | 0 if success, > 0 if error |
Yes
|
wallet.balance
|
Float | Player wallet balance |
Yes
|
wallet.currency
|
String | ISO 4217 currency code |
Yes
|
user.id
|
String | Unique player ID |
Yes
|
user.firstName
|
String | Player first name |
No
|
user.lastName
|
String | Player last name |
No
|
user.userName
|
String | Player username |
Yes
|
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
}
{
"status": 0,
"user": {
"id": "1",
"firstName": "Demo",
"lastName": "One",
"userName": "example_user"
},
"wallet": {
"currency": "USD",
"balance": 1000
}
}
/bet
Debit player account with bet amount. Multiple bet calls can be made within one game round until closed by a win call.
Request Fields
| Field | Type | Description | Required |
|---|---|---|---|
user.token
|
String | Player validation token |
Yes
|
user.id
|
String | User code of the operator player |
Yes
|
amount
|
Number | Amount to deduct for the bet |
Yes
|
gameId
|
Number | Unique Game ID |
Yes
|
roundId
|
Number | Round ID where bet was placed |
Yes
|
transactionId
|
String | Unique debit transaction ID |
Yes
|
betId
|
String | Unique bet ID (in tuple [gameId, betId]) |
Yes
|
currencyId
|
String | Numeric currency ID |
Yes
|
currencyCode
|
String | Currency code (USD, EUR) |
Yes
|
Response Fields
| Field | Type | Description | Required |
|---|---|---|---|
status
|
Number | 0 if success, > 0 if error |
Yes
|
wallet.balance
|
Number | Updated player balance |
Yes
|
wallet.currency
|
String | ISO 4217 currency code |
Yes
|
{
"user": {
"id": "1",
"token": "eyJhbGciOiJIUzI1..."
},
"amount": 1,
"roundId": 1,
"gameId": 1,
"transactionId": "game-bet-1-1",
"betId": "1",
"currencyId": "1",
"currencyCode": "USD"
}
{
"status": 0,
"wallet": {
"currency": "USD",
"balance": 999
}
}
/win
Credit player account with win amount. Amount may be zero to mark non-winning rounds. Closes the game round.
Request Fields
| Field | Type | Description | Required |
|---|---|---|---|
user.token
|
String | Player validation token |
Yes
|
user.id
|
String | User code of the operator player |
Yes
|
amount
|
Number | Amount to credit for the win |
Yes
|
gameId
|
Number | Unique Game ID |
Yes
|
roundId
|
Number | Round ID where bet was placed |
Yes
|
transactionId
|
String | Unique credit transaction ID |
Yes
|
debitTransactionId
|
String | Corresponding debit transaction ID |
Yes
|
betId
|
String | Unique bet ID (in tuple [gameId, betId]) |
Yes
|
currencyId
|
String | Numeric currency ID |
Yes
|
currencyCode
|
String | Currency code (USD, EUR) |
Yes
|
{
"user": {
"id": "1",
"token": "eyJhbGciOiJIUzI1..."
},
"amount": 10.00,
"roundId": 1,
"gameId": 1,
"transactionId": "game-win-1-1",
"debitTransactionId": "game-bet-1-1",
"betId": "1",
"currencyId": "1",
"currencyCode": "USD"
}
{
"status": 0,
"wallet": {
"currency": "USD",
"balance": 1009
}
}
/rollback
Rollback a bet transaction after unknown status or failed bet call. Increases player balance by the transaction amount.
Request Fields
| Field | Type | Description | Required |
|---|---|---|---|
user.token
|
String | Player validation token |
Yes
|
user.id
|
String | User code of the operator player |
Yes
|
amount
|
Number | Amount of the transaction |
Yes
|
gameId
|
Number | Unique Game ID |
Yes
|
roundId
|
Number | Round ID where bet was placed |
Yes
|
originalTransactionId
|
String | Original debit transaction ID to rollback |
Yes
|
rollbackTransactionId
|
String | Unique rollback transaction ID |
Yes
|
betId
|
String | Unique bet ID (in tuple [gameId, betId]) |
Yes
|
currencyId
|
String | Numeric currency ID |
Yes
|
currencyCode
|
String | Currency code (USD, EUR) |
Yes
|
{
"user": {
"id": "1",
"token": "eyJhbGciOiJIUzI1..."
},
"amount": 1.00,
"roundId": 1,
"gameId": 1,
"originalTransactionId": "game-bet-1-1",
"rollbackTransactionId": "rb-1",
"betId": "1",
"currencyId": "1",
"currencyCode": "USD"
}
{
"status": 0,
"wallet": {
"currency": "USD",
"balance": 1000
}
}
/funds
Get the current status and details of the player's wallet.
Request Fields
| Field | Type | Description | Required |
|---|---|---|---|
token
|
String | The operatorUserToken generated at login |
Yes
|
currency
|
String | Currency code for reference |
No
|
Response Fields
| Field | Type | Description | Required |
|---|---|---|---|
status
|
Number | 0 if success, > 0 if error |
Yes
|
wallet.balance
|
Number | Player wallet balance (floating point) |
Yes
|
wallet.currency
|
String | ISO 4217 currency code |
Yes
|
{
"token": "eyJhbGciOiJIUzI1...",
"currencyCode": "USD"
}
{
"status": 0,
"wallet": {
"currency": "USD",
"balance": 1000
}
}
/game-close
Called when the game application is closed.
Request Fields
| Field | Type | Description | Required |
|---|---|---|---|
user.token
|
String | Player validation token |
Yes
|
user.id
|
String | User code of the operator player |
Yes
|
Response Fields
| Field | Type | Description | Required |
|---|---|---|---|
status
|
Number | 0 if success, > 0 if error |
Yes
|
{
"user": {
"id": "1",
"token": "eyJhbGciOiJIUzI1..."
}
}
{
"status": 0
}
Error Codes
| Status | Name | Description |
|---|---|---|
|
1
|
SessionNotFoundError |
Session is not found |
|
2
|
InsufficientFundsError |
Balance is not sufficient, will reject the bet |
|
3
|
UserIsBlockedError |
User is blocked |
|
4
|
- |
For any unidentified error |
|
5
|
DailyBettingLimitReachedError
|
Daily betting limit reached |
|
6
|
WeeklyBettingLimitReachedError
|
Weekly betting limit reached |
|
7
|
MonthlyBettingLimitReachedError
|
Monthly betting limit reached |
Note: Any non-zero response or non-200 HTTP status code will mark the transaction as failed.
For bet calls: The bet will be
rejected.
For credit/rollback: Transaction marked as failed, but bet
remains successful. Exa will retry every 20 seconds until resolved.
Server Whitelisting
Whitelist these IPs for callbacks to go through:
| Environment | IP Address |
|---|---|
| Production | 3.67.123.26 |
| Staging | 18.195.38.202
|
| Development | 13.235.153.111
|
Code Snippets
Validating Signature
function signatureVerificationMiddleware(req, res, next) {
const secretKey = config.get('operator.secret_key');
const isValid = verifyHMACSignature(
req.body,
req.headers['X-OPERATOR-SIGNATURE'],
secretKey
);
if (isValid) {
next();
} else {
next(new BaseError(InvalidSignatureErrorType));
}
}