v.1.0.0
Change log
| Version | Changes |
|---|---|
| v1.0.0 | - Initial Seamless Wallet API release |
Introduction
This API provides Seamless wallet integration between Optiplay and your Casino. The API consists of three parts: Games API, Wallet API (including bonuses), and optional Free Rounds API.
Tournaments are handled internally by Optiplay's promo engine and are not exposed as a separate partner-facing API here.
It is important to note that one player can only have one currency (monowallet).
OpenAPI Documentation
OpenAPI documentation is available at: https://integration-api.stage.optiplay.io/api/v1/v13 (stage environment).
The documentation includes endpoints for the Games API, Free Rounds API, and Rounds Report, as well as the ability to generate signatures for POST requests.
Required data for integration
Given by Optiplay
| Name | Description | Example |
|---|---|---|
| optiplay_url | Optiplay API URL (stage) | https://integration-api.stage.optiplay.io/:casino_id/api |
| password | Per-casino signature secret | e.g. REPLACE_WITH_YOUR_CASINO_SECRET (illustrative — ask Optiplay integrations for your actual value) |
Given by Casino
| Name | Description | Example |
|---|---|---|
| casino_url | Casino API URL | https://yoursite.com/the/api |
| casino_ip[ ] | Casino IP white list | 127.0.0.1, 192.168.0.1 |
Communication format
- Optiplay request URL to Casino starts with [casino_url]
- Casino request URL to Optiplay starts with [optiplay_url]
- All requests are GET or POST
- All message bodies are JSON
- Messages include Content-Type: application/JSON HTTP header
- Response bodies contain a status field
- Messages containing HTTP body such as HTTP POST requests must be signed for authentication.
- Date format YYYY-MM-DD
- DateTime format is ISO-8601 extended format (YYYY-MM-DDThh:mm:ss)
- Time format hh:mm:ss in GMT(UTC) time zone
- If a request is unsuccessful (status !== 200 || 201) its response will contain an error field with the type of error and a message field with the error description
- All currencies in messages are based on ISO-4217 format – 3 uppercase letters: USD, EUR, etc.
- All languages in messages are based on ISO-639-1 format – 2 lowercase letters: en, es, it, etc.
- All requests are sent using HTTPS protocol.
Money format
Currencies are in ISO-4217 standard format.
Currencies are converted into related precision to maintain integer value. Casino must transform value conforming to the related precision with the currency required.
| Currency | Precision |
|---|---|
| EUR | 2 |
| CLP | 0 |
| USD | 2 |
| COP | 2 |
| JOD | 3 |
Mobile and desktop slot games
All games are presented in both mobile and desktop versions. Optiplay requires a query parameter client and launches the corresponding game client (mobile or desktop) depending on it.
About parameter "home"
The parameter "home" has three use cases, depending on its value, the game client reacts differently:
- "home" is empty or undefined – the game client hides the button “home”;
- "home" = “closePopup” – this case is to handle the game client is opened on a platform’s iframe and the button “home” is pressed;
- "home" is something else – this case is to handle the game client is opened on a separate page and user has to return to a platform site
Balance management
Optiplay does not manage the player's balance, but may store the balances received from the Casino
Response status codes
-
The only acceptable HTTP status codes are 200 or 201
-
API status codes are contained in the response body
-
Status codes are similar to the HTTP status codes:
- The 200 or 201 codes mean a response with successfully processed request;
- The 4XX codes mean bad request;
- The 500 code means something bad and unexpected has happened;
| Code | Description |
|---|---|
| 200, 201 | Successful Response |
| 400 | Bet limit reached |
| 401 | Signature invalid |
| 402 | Insufficient Funds |
| 403 | Game not allowed,Session expired |
| 404 | Page not found, Transaction not found |
| 405 | User is blocked |
| 406 | Withdraw operation already has a deposit action |
| 409 | Something went wrong |
| 422 | Unprocessable Entity (some parameter is invalid) |
| 429 | Too many requests |
| 430 | Freerounds not found |
| 500 | Server error,Unknown Error,Transactions declined |
Implementation note: our error resolver currently maps codes starting at
401—400("Bet limit reached") is not yet mapped to a business error. If your Casino sends400, verify the response isn't misclassified until this is added.
Authentication
It’s highly recommended to authenticate messages at the prod stage. x-signature header must be included in the HTTP message to sign a message.
x-signature is a hashed sha512 string = HTTP payload + ":" + password (given by Optiplay).
When a message with a signature is received it must be checked that the signature is valid.
If the message has an invalid signature, Casino must return an error message:
{
"status": 401,
"error": "Invalid Signature"
}
The following functions might be used to sign messages:
NodeJS
const crypto = require("crypto");
/**
* @param {string} payload
* @param {string} password
*/
const sign = (payload, password) =>
crypto.createHash("sha512").update(payload + ":" + password).digest("hex");
PHP
function sign(string $payload, string $password): string {
return hash('sha512', $payload . ':' . $password);
}
Games Api
GET /languages
Method: GET
URI: [optiplay_url]/languages
Description: Returns the list of languages available for the Casino
Response Type:
type Result = string[]
Response:
{
"status": 200,
"ts": 1234567890,
"result":[
"bg",
"en",
"cs",
"es",
"go",
"it",
...
]
}
GET /currencies
Method: GET
URI: [optiplay_url]/currencies
Description: Returns the list of currencies available for the Casino
Response Type:
type Result = string[]
Response:
{
"status": 200,
"ts": 1234567890,
"result":[
"EUR",
"LKR",
"MGA",
"UAH",
"USD",
"uBTC",
...
]
}
GET /games
Method: GET
URI: [optiplay_url]/games
Description: Returns the list of games available for the Casino
Response Type:
type Result = {
id: string;
name: string;
logo: string; //Link to game logo image
order: number;
tags?: string[];
};
Response:
{
"status": 200,
"ts": 1234567890,
"result": [
{
"id": 1045,
"name": "Sunny Coin 2",
"logo": "https://.../g1045.jpg",
"order": 2,
"tags": [
"fruits",
"snow"
]
},
{
"id": 2001,
"name": "Royal Hot v2",
"logo": ".https://.../g2001.jpg",
"order": 1
},
...
]
}
GET /freerounds/info
Method: GET
Params:
type Params = {
gameIds?: number[] // List of Optiplay Game IDs (optional)
currencies?: string[] // List of currencies (optional)
}
URI: [optiplay_url]/freerounds/info?gameIds=[ game id ]¤cies=[ currency ]
Descriptions: Returns information about Free Rounds settings available for the Casino
Response Type:
type Result = {
offers: {
currency: string,
game_id: string,
game_name: string,
bets: integer[] //list for free round bets available for the game and currency
}[]
}
Response:
{
"status": 200,
"ts": 1234567890,
"result": {
"offers": [
{
"currency": "UAH",
"game_id": "1045",
"game_name": "Sunny Coin 2",
"bets": [
200,
500,
1000
]
},
{
"currency": "USD",
"game_id": "2001",
"game_name": "Royal Hot v2",
"bets": [
100,
200,
1000
]
},
...
]
}
}
GET /init
Method: GET
Params:
type Params = {
gid: integer // Optiplay Game ID
pid: string // Casino Player ID
currency: string //Casino Player currency
home?: string // Button HOME moves the player to this URL
demo?: integer // Non zero value means the player is the demo
lang?: string // Casino Player language
client?: string // Html Client type. “desktop” or “mobile”
token?: string // Game launch token
countryCode?: string // Casino Player country code (KZ, TR, etc.)
}
URI: [optiplay_url]/init?gid=[ your gid ]&pid=[ your pid ]¤cy=[ your currency ]&home=/&demo=0&lang=en&client=desktop&token=[ your token ]
Description: Returns the URL of the chosen game.
The Casino must forward the Player into an iframe with the returned URL. Make sure the iframe has an "allowfullscreen" attribute.
Response Type:
type Result = string
Response:
{
"status": 200,
"ts": 1234567890,
"result": "https://cdn-v2.optiplay.com/3x3-hold-the-spin/v1.9.2?host=sapp.optiplay.com&port=443&lang=en&sid=avkdboqlz"
}
POST /opened
Method: POST
Body:
type Body = {
pid: string; // Casino Player ID
gid: string; // Optiplay Game ID
};
URI: [casino_url]/opened
Description: This request is sent when a player has opened the game.
Response:
{
"status": 200
}
* This request is not being sent by default. If the Casino has a necessity of getting this request, please contact the Optiplay integration team
POST /closed
Method: POST
Body:
type Body = {
pid: string; // Casino Player ID
gid: string; // Optiplay Game ID
};
URI: [casino_url]/closed
Description: This request is sent when a player has closed the game.
Response:
{
"status": 200
}
* This request is not being sent by default. If the Casino has a necessity of getting this request, please contact the Optiplay integration team
Wallet Api
The Casino is expected to implement the Wallet API for Optiplay calls. Each Wallet API response must contain a player’s current balance.
Wallet API POST requests have to be idempotent. Those requests contain a transaction_id field. The Casino has to ensure that requests with the same transaction_id are not processed twice while the duplicate responses have to contain a message "Already processed".
Already processed response example:
{
"status": 200,
"result": {
"balance": 8750,
"currency": "USD",
"message": "Already processed"
}
}
If a withdrawal exceeds the player’s balance, an “Insufficient funds” error response has to be returned. Insufficient funds response example:
{
"status": 402,
"error": "Insufficient funds",
"result": {
"balance": 8750
}
}
Every round has one withdrawal and one deposit request. There are no restrictions on the amount of rounds in the session. FreeRounds are presented as separate rounds.
The type parameter in the deposit and withdraw actions can have the following values:
- spin – an ordinary round
- freeRound – a free round provided by Casino
- prize – a round to send a tournament prize
- reward – an achievement payout
The type parameter in the cancel action will always have value "refund"
FreeRound type have the withdrawal amount equal to 0.
In case Casino cannot accept withdrawal amount 0, Optiplay can provide configuration that sends withdraw request for these rounds with
{
"amount": "min_bet"
}
where min_bet is the minimum bet amount configured for the current Casino, game and currency, and deposit request with
{
"amount": "min_bet + win_amount"
}
to compensate the withdrawal amount. However, it should be considered that in case player's balance is less than min_bet, player will get Insufficient funds error, though the round is technically free
Error processing
When a game session is interrupted during a game round (for example, a connection failure between the Optiplay client and the Optiplay server) the player can start the game from the lobby once again and continue the game from the same point.
Also a game session may be interrupted due to a transaction error between Optiplay and Casino.
The Optiplay server tries to resend the request automatically if Casino does not respond or the response HTTP status is not 200 or 201.
If all requests fail or some request has incorrect content, the game session will be blocked and the player will see an error message.
{
"status": 403,
"error": "User has unresolved transactions on this game"
}
| Code | Description | Refundable |
|---|---|---|
| 400 | Bet limit reached | false |
| 401 | Invalid Signature | false |
| 402 | Insufficient Funds | false |
| 403 | Game not allowed, Session expired | false |
| 404 | Page not found, Transaction not found | false |
| 405 | User is blocked | false |
| 406 | Withdraw operation already has a deposit action | false |
| 409 | Something went wrong | true |
| 422 | Unprocessable Entity (some parameter is invalid) | true |
| 429 | Too many requests | false |
| 430 | Freerounds not found | false |
| 500 | Server error, Transaction declined | true |
- In case an error with refundable=true occurs on withdraw(bet) transaction a cancel(rollback) transaction will be sent.
- In case an error with refundable=true occurs on deposit(win) transaction the win transaction will be retried.
GET /balance
Method: GET
Params:
type Params = {
pid: string; // Casino Player ID
token: string; // Game launch token (only if token was provided in init request)
}
URI: [casino_url]/balance
Description: Called when players balance is needed. Casino has to return the player's current balance.
Response Type:
type Result = {
balance: integer; // Casino Player balance
currency: string; // Casino Player currency
}
Response:
{
"status": 200,
"result": {
"balance":8750,
"currency":"USD"
}
}
POST /withdraw
Method: POST
Body:
type Body = {
type: string; // Round type (spin, prize, freeRound)
amount: integer; // Withdrawal amount
tid: string; // Optiplay Transaction ID
pid: string; // Casino Player ID
rid: string; // Optiplay Round ID
gid: string; // Optiplay Game ID
ts: integer; // Transaction timestamp (Unix time in milliseconds)
fr_id?: string; // Free Rounds campaign ID (only if round type=freeRound)
fr_finished?: boolean; //If freeround is last (only if round type=freeRound)
token?: string; // Game launch token (only if token was provided in init request)
}
URI: [casino_url]/withdraw
Description: Withdraws money from the player’s wallet. The Casino has to return the player’s current balance.
Response Type :
type Result = {
balance: integer; // Casino Player balance
transaction_id: string; // Casino Transaction ID
}
Response:
{
"status": 200,
"result": {
"balance": 8750,
"transaction_id": "t-1"
}
}
POST /deposit
Method: POST
Body:
type Body = {
type: string; // Round type (spin, prize, freeRound)
amount: integer; // Deposit amount
tid: string; // Optiplay Transaction ID
pid: string; // Casino Player ID
rid: string; // Optiplay Round ID
gid: string; // Optiplay Game ID
ts: integer; // Transaction timestamp (Unix time in milliseconds)
fr_id?: string; // Free Rounds campaign ID (only if round type=freeRound)
fr_finished?: boolean; //If freeround is last (only if round type=freeRound)
token?: string; // Game launch token (only if token was provided in init request)
}
URI: [casino_url]/deposit
Description: Deposits money to the player’s wallet. The Casino has to return the player’s current balance.
Response Type :
type Result = {
balance: integer; // Casino Player balance
transaction_id: string; // Casino Transaction ID
}
Response:
{
"status": 200,
"result": {
"balance": 8750,
"transaction_id": "t-1"
}
}
POST /cancel
Method: POST
Body:
type Body = {
type: string; // Round type (refund)
tid: string; // Optiplay Rollback Transaction ID
originalTid: string; // Optiplay Bet Transaction ID
pid: string; // Casino Player ID
rid: string; // Optiplay Round ID
gid: string; // Optiplay Game ID
ts: integer; // Transaction timestamp (Unix time in milliseconds)
bet: integer; // Bet amount (just for info)
win: integer; // Win amount (just for info)
token: string; // Game launch token (only if token was provided in init request)
}
URI: [casino_url]/cancel
Description: Rollbacks a bet transaction on Casino and closes the round in order to reverse the transaction and adjust the player’s balance. Casino has to return the money back when receives a Cancel request. Refunds must be made before the response to the request is sent.
Response Type :
type Result = {
balance: integer; // Casino Player balance
transaction_id: string; // Casino Rollback Transaction ID
}
Response:
{
"status": 200,
"result": {
"balance": 8750,
"transaction_id": "t-1"
}
}
Free Rounds Api
Free Rounds (FR) API is an optional API.
The Casino using the FR API is able to grant free bets to users. First-time-user bonuses are supported: FR feature functions even if a player has not played Optiplay games yet.
FR settings may have constraints set by Optiplay: games, currencies, bet values or time.
The Casino may have several FR settings with its constraints. To provide FR to some players, Casino has to specify which FR settings they are based on.
When players use FR their deposit/withdraw bet types are “freeRound”.
POST /freerounds/v2/create
Method: POST
Body:
type Body = {
fr_id: string; // Optiplay FR ID
started_at: datetime; // FR allowed from this time (optional)
finished_at: datetime; // FR allowed to this time (optional)
gid: string | integer []; // List of Optiplay Game IDs
bet_amount: integer; // Bet Amount
rounds: integer; // Amount of FR
pid: string; // Casino Player ID
currency?: string; // Casino Player currency (optional)
}
* As "bet_amount" you can set a value from the list of game bets for currency
URI: [optiplay_url]/freerounds/v2/create
Description: Creates or updates the freerounds settings if exists
Response Type:
type Result = {
fr_id: string // Optiplay FR ID
}
Response:
{
"status":200,
"ts":"1234567890",
"result": {
"fr_id":"13ec1944-4106-42ae-b410-c634a6a08f19"
}
}
POST /freerounds/create
⚠️ WARNING: This method is deprecated
Method: POST
Body:
type Body = {
fr_id: string; // Optiplay FR ID
started_at: datetime; // FR allowed from this time (optional)
finished_at: datetime; // FR allowed to this time (optional)
gid: string | integer []; // List of Optiplay Game IDs
bet_level: integer; // Bet Level
bet_coins: integer; //Bet Coins
rounds: integer; // Amount of FR
pid: string; // Casino Player ID
}
* The total bet is calculated as bet_lines * bet_level * bet_coins, where "bet_lines" is the maximum number of lines in the game.
If the “bet_level” parameter is not set, the default is 1.
If the “bet_coins” parameter is not set, the default is the FR bet is game min bet.
URI: [optiplay_url]/freerounds/create
Description: Creates or updates the freerounds settings if exists
Response Type:
type Result = {
fr_id: string // Optiplay FR ID
}
Response:
{
"status":200,
"result": {
"fr_id":"13ec1944-4106-42ae-b410-c634a6a08f19"
}
}
POST /freerounds/cancel
Method: POST
Body:
type Body = {
fr_id: string // Optiplay FR ID
}
URI: [optiplay_url]/freerounds/cancel
Description: Deletes the freerounds settings if exists.
Jackpots Api
Optiplay extension. This section is not part of the original Seamless Wallet protocol — it's an Optiplay-specific addition for games with a shared jackpot pool. Casinos that don't run jackpot-enabled games can ignore it.
GET /jackpots/balance
Method: GET
Params:
type Params = {
currency: string; // Currency code to convert the jackpot balance into (ISO-4217, 3 letters)
}
URI: [optiplay_url]/jackpots/balance?currency=[ currency ]
Description: Returns the current balance of every active jackpot tier for the Casino, converted into the requested currency.
Response Type:
type Result = {
status: number;
ts: number;
result: {
id: number;
name: string; // Jackpot tier name, e.g. "Minor", "Major", "Mega"
amount: number;
currency: string;
}[];
}
Response:
{
"status": 200,
"ts": 1234567890,
"result": [
{
"id": 23,
"name": "Major",
"amount": 35678,
"currency": "EUR"
},
{
"id": 23,
"name": "Mega",
"amount": 29600,
"currency": "EUR"
}
]
}
GET /jackpots/winners
Method: GET
Params:
type Params = {
limit: number; // Number of winners to return
currency: string; // Currency code to convert winnings into (ISO-4217, 3 letters)
}
URI: [optiplay_url]/jackpots/winners?limit=[ limit ]¤cy=[ currency ]
* The Casino is identified by [optiplay_url], not by a request parameter.
Description: Returns the most recent jackpot winners for the Casino.
Response Type:
type Result = {
status: number;
ts: number;
result: {
pid: string; // Casino Player ID
name: string; // Jackpot tier name
date: string; // ISO-8601 datetime
amount: number;
currency: string;
}[];
}
Response:
{
"status": 200,
"ts": 1234567890,
"result": [
{
"pid": "test-1",
"date": "2024-04-04T11:02:13.000Z",
"name": "Major",
"amount": 35678,
"currency": "EUR"
}
]
}
Rounds Report
POST /round/info
Method: POST
Body:
type Body = {
externalId: string // Optiplay round ID
}
URI: [optiplay_url]/round/info
Description: Returns information about specific round.
Note: unlike every other endpoint in this document, the response here is not wrapped in the
{status, ts, result}envelope — it uses{info, success}instead. This is intentional and matches our implementation; don't expect the standard envelope for this endpoint.
Response Type:
type Info = {
bet: integer; // Round bet amount
win: integer; // Round win amount
created_at: datetime; // Round created date
closed_at: datetime; // Round closed date
type: string, // Round type (spin, freeRound, prize)
currency: string // Round currency
}
Response:
{
"info": {
"bet": 10,
"win": 100,
"created_at": "2024-01-15T14:27:41.202000Z",
"closed_at": "2024-01-15T14:27:41.278499Z",
"type": "spin",
"currency": "EUR"
},
"success": true
}