API Docs

Table of contents

Glossary

Denomination - a positive integer number which is a denominator of a given amount of a balance transaction. It makes using floating-point numbers and precision errors avoidable. It is presented together with the value it corresponds to. For example, $30.73 would look like

{ "amount": 3073, "denomination": 100 }
{ "amount": 3073, "denomination": 100 }

Transaction ID - is used in balance-related operations to prevent double is used in balance-related operations to prevent double spend, when multiple consecutive requests are issued as a result of possible failures in request retry loop, i.e. the 1st request could be accepted by provider’s server, but for some reason, we didn’t receive a successfull response, after which, a 2nd request shall be issued with the same transaction ID.

Game history - when a user_id parameter is supplied at session initialization, it is then used to track, which machines are chosen by user and push them to the “Recently played” list.

Sequence Diagram

sequenceDiagram
    participant P as Provider
    participant S as Game Server
    participant C as Web Client

    P ->>+ S: Send Session Init request
    S ->>- P: URL to application
    P ->>  C: Open URL in tab/iframe
    C ->>  S: Connect
    loop
        C ->>  S: Choose Machine
        C ->>+ S: Choose Amount
        S ->>- P: Send Update Balance request (withdraw)

        opt
            S ->>  P: Send Log Action request
        end

        C ->>+ S: Exit to lobby / Close tab / Go offline
        S ->>- P: Send Balance Update request (deposit)
    end
    Note over S: Session is closed

API Endpoints

Requests made by Provider to Server

OpenAPI spec in json or yaml format.

Initialize a Session

Endpoint: POST /api/v1/session/init

Request payload:

{
	"casino_id": "<identifier>", // required
	"game_id": "<game identifier>", // required
	"session": "<session identifier>", // required
	"user_id": "<user identifier>", // optional
	"currency": "USD", // required
	"locale": "en", // optional
	"geo": "", // optional
	"denomination": 1000,
	"balance": 17020,
	"return_url": "https://example.com", // optional
	"cashier_url": "https://example.com", // optional
	"sub_id": "<id1>,<id2>,<id3>", // optional
	"buffer": "<encoded internal state>", // optional
	"sign": "<payload signature, see below>" // required
}
{
	"casino_id": "<identifier>", // required
	"game_id": "<game identifier>", // required
	"session": "<session identifier>", // required
	"user_id": "<user identifier>", // optional
	"currency": "USD", // required
	"locale": "en", // optional
	"geo": "", // optional
	"denomination": 1000,
	"balance": 17020,
	"return_url": "https://example.com", // optional
	"cashier_url": "https://example.com", // optional
	"sub_id": "<id1>,<id2>,<id3>", // optional
	"buffer": "<encoded internal state>", // optional
	"sign": "<payload signature, see below>" // required
}
Field Type Required Description
casino_id string A predetermined casino identifier
game_id string A Lobby identifier, either negotiated before or retrieved from the list-endpoint
session string A unique session identifier
user_id string A user identifier. If supplied, then history feature becomes available for the session
currency string ISO 4217 currency code
locale string ISO 639 language code
geo string ISO_3166-2 string representing user’s geo, i.e. CA, CA-ON
denomination integer Denomination of the balance
balance integer User’s balance
return_url string A URL, which would be used for redirects at the end of the session
cashier_url string A URL for redirecting to deposit page
sub_id string IDs of sub-clients, in the form of comma-separated list
buffer string Used for integration with stateless systems
sign string A Request signature

Responses:

List machines and lobbies

Endpoint: POST /api/v1/machine/list

Request payload:

{
	"casino_id": "<identifier>",
	"sign": "<payload signature, see below>"
}
{
	"casino_id": "<identifier>",
	"sign": "<payload signature, see below>"
}
Field Type Required Description
casino_id string A predetermined casino identifier
sign string A Request signature

Responses:

Endpoint: POST /api/v1/history/link

Request payload:

{
	"session": "<identifier>",
	"casino_id": "<identifier>",
	"sign": "<payload signature, see below>"
}
{
	"session": "<identifier>",
	"casino_id": "<identifier>",
	"sign": "<payload signature, see below>"
}
Field Type Required Description
session string Session ID used when initializing it
casino_id string A predetermined casino identifier
sign string A Request signature

Responses:

Requests made by Server to Provider

OpenAPI spec in json or yaml format.

The endpoints can be tweaked per each provider, but the defaults are provided below:

Update Balance

Endpoint: POST /action

Request Payload:

{
	"session": "<identifier>",
	"currency": "USD",
	"amount": 1332,
	"denomination": 100,
	"type": "win", // "win", "bet" or "refund"
	"transaction": "<tx identifier>",
	"betTransactionId": "<bet tx identifier>",
	"roundId": "<round number>",
	"sign": "string", // See Request signing
	"timestamp": 1644231487,
	"machine": "FFFF456789ABCDEF",
	"buffer": "<encoded internal state>" // optional
}
{
	"session": "<identifier>",
	"currency": "USD",
	"amount": 1332,
	"denomination": 100,
	"type": "win", // "win", "bet" or "refund"
	"transaction": "<tx identifier>",
	"betTransactionId": "<bet tx identifier>",
	"roundId": "<round number>",
	"sign": "string", // See Request signing
	"timestamp": 1644231487,
	"machine": "FFFF456789ABCDEF",
	"buffer": "<encoded internal state>" // optional
}
Field Type Required Description
session string Session identifier, specified in Initialize a Session endpoint
currency string ISO 4217 currency code
amount integer Amount to withdraw/deposit
denomination integer Denomination of the amount
type string "win", "bet" or "refund"
transaction string A unique transaction ID
betTransactionId string Bet transaction ID, transaction from previous bet request for win/refund, same as transaction for bet
roundId integer Non-negative number, binding pairs of bet and win/refund requests
sign string A Request signature
timestamp integer UNIX Epoch timestamp in milliseconds
machine string Machine identifier, on which the game was played
buffer string Used for integration with stateless systems

Response Payload:

{
	"balance": 1332,
	"denomination": 100,
	"transaction": "<tx identifier>",
	"buffer": "<encoded internal state>" // optional
}
{
	"balance": 1332,
	"denomination": 100,
	"transaction": "<tx identifier>",
	"buffer": "<encoded internal state>" // optional
}
Field Type Required Description
balance integer Resulting balance
denomination integer Denomination of the amount
transaction string A unique transaction ID
buffer string Used for integration with stateless systems

Log Action

This endpoint can be optinally supported by provider, to receive events that happen in-between the withdraw and deposit requests (i.e. through Update Balance endpoint).

Request Payload:

{
	"session": "<identifier>", // The identifier, sent by provider in init request
	"currency": "USD",
	"amount": 132,
	"denomination": 100,
	"type": "win", // "win", "bet" or "refund"
	"transaction": "<tx identifier>",
	"sign": "string", // See Request signing
	"timestamp": 1644231487,
	"buffer": "<encoded internal state>" // optional
}
{
	"session": "<identifier>", // The identifier, sent by provider in init request
	"currency": "USD",
	"amount": 132,
	"denomination": 100,
	"type": "win", // "win", "bet" or "refund"
	"transaction": "<tx identifier>",
	"sign": "string", // See Request signing
	"timestamp": 1644231487,
	"buffer": "<encoded internal state>" // optional
}
Field Type Required Description
session string Session identifier, specified in Initialize a Session endpoint
currency string ISO 4217 currency code
amount integer Amount to withdraw/deposit
denomination integer Denomination of the amount
type string "win", "bet" or "refund"
transaction string A unique transaction ID
sign string A Request signature
timestamp integer UNIX Epoch timestamp in milliseconds
buffer string Used for integration with stateless systems

Response Payload:

Any non-errorneous status code with arbitrary payload which is ignored.

Wallet

Endpoint: POST /wallet

Request Payload:

{
	"session": "<identifier>", // The identifier, sent by provider in init request
	"currency": "USD",
	"denomination": 100,
	"transaction": "<tx identifier>",
	"sign": "string", // See Request signing
	"timestamp": 1644231487,
	"buffer": "<encoded internal state>" // optional
}
{
	"session": "<identifier>", // The identifier, sent by provider in init request
	"currency": "USD",
	"denomination": 100,
	"transaction": "<tx identifier>",
	"sign": "string", // See Request signing
	"timestamp": 1644231487,
	"buffer": "<encoded internal state>" // optional
}
Field Type Required Description
session string Session identifier, specified in Initialize a Session endpoint
currency string ISO 4217 currency code
denomination integer Denomination of the amount
transaction string A unique transaction ID
sign string A Request signature
timestamp integer UNIX Epoch timestamp in milliseconds
buffer string Used for integration with stateless systems

Response Payload:

{
	"balance": 1332,
	"denomination": 100,
	"transaction": "<tx identifier>",
	"buffer": "<encoded internal state>" // optional
}
{
	"balance": 1332,
	"denomination": 100,
	"transaction": "<tx identifier>",
	"buffer": "<encoded internal state>" // optional
}
Field Type Required Description
balance integer Resulting balance
denomination integer Denomination of the amount
transaction string A unique transaction ID
buffer string Used for integration with stateless systems

Request signing

Endpoints that contain top level sign field are subject to payload signing. The sign is calculated in the following way:

  1. Encode the payload into JSON. To avoid inconsistency regarding object key ordering, all object values in the payload must have their keys sorted alphabetically. Some languages have this behaviour out-of-the-box (i.e. Pythons’s json.dumps with sort_keys=True)
  2. Append a key to the encoded JSON string
  3. Compute a hash from the resulting string using provided algorithm
  4. Encode the output of the hashing function into hex string

When performing a request, take the constructed object, compute the sign using the steps above and assign the hex string to the sign property before encoding and sending the payload.

When checking the signature of an incoming request, decode the payload, take the sign property from the object, compute the sign of the object with removed sign key using the steps above and compare the incoming and computed signatures. If they are equal, the request is trusted.

Below are the code snippets for some languages which implement functions for computing the sign, applying it the the payload and checking the incoming request payload:

import { createHash } from 'node:crypto';

function encodeValueSorted(value) {
	if (value === null || typeof value !== 'object') {
		return JSON.stringify(value);
	}
	if (Array.isArray(value)) {
		return `[${value.map(encodeValueSorted).join(',')}]`;
	}
	const entries = Object.entries(value)
		.filter(([, val]) => val !== undefined)
		.sort(([key1], [key2]) => (key1 > key2 ? 1 : -1))
		.map(([key, val]) => `${JSON.stringify(key)}:${encodeValueSorted(val)}`);
	return `{${entries.join(',')}}`;
}

function getSignature(payload, key, algorithm) {
	const hashInput = `${encodeValueSorted(payload)}${key}`;
	const hash = createHash(algorithm);
	return hash.update(hashInput).digest('hex');
}

const key = '0d50d9b3-7d80-422a-a20d-ab4ca017737f';
const algorithm = 'sha256';

function signPayload(payload) {
	const sign = getSignature(payload, key, algorithm);

	return { ...payload, sign };
}

function checkPayload(payload) {
	const { sign, ...rest } = payload;
	return sign === getSignature(rest, key, algorithm);
}
import { createHash } from 'node:crypto';

function encodeValueSorted(value) {
	if (value === null || typeof value !== 'object') {
		return JSON.stringify(value);
	}
	if (Array.isArray(value)) {
		return `[${value.map(encodeValueSorted).join(',')}]`;
	}
	const entries = Object.entries(value)
		.filter(([, val]) => val !== undefined)
		.sort(([key1], [key2]) => (key1 > key2 ? 1 : -1))
		.map(([key, val]) => `${JSON.stringify(key)}:${encodeValueSorted(val)}`);
	return `{${entries.join(',')}}`;
}

function getSignature(payload, key, algorithm) {
	const hashInput = `${encodeValueSorted(payload)}${key}`;
	const hash = createHash(algorithm);
	return hash.update(hashInput).digest('hex');
}

const key = '0d50d9b3-7d80-422a-a20d-ab4ca017737f';
const algorithm = 'sha256';

function signPayload(payload) {
	const sign = getSignature(payload, key, algorithm);

	return { ...payload, sign };
}

function checkPayload(payload) {
	const { sign, ...rest } = payload;
	return sign === getSignature(rest, key, algorithm);
}
import json
import hashlib


def get_signature(payload, key, algorighm):
    hash_input = json.dumps(payload, sort_keys=True, separators=(",", ":"))
    hash_input += key
    hash = hashlib.new(algorighm, hash_input.encode())
    return hash.hexdigest()


key = "0d50d9b3-7d80-422a-a20d-ab4ca017737f"
algorithm = "sha256"


def sign_payload(payload):
    sign = get_signature(payload, key, algorithm)
    return {**payload, "sign": sign}


def check_payload(payload):
    payload = {**payload}
    expected = payload.pop("sign")
    actual = get_signature(payload, key, algorithm)
    return expected == actual
import json
import hashlib


def get_signature(payload, key, algorighm):
    hash_input = json.dumps(payload, sort_keys=True, separators=(",", ":"))
    hash_input += key
    hash = hashlib.new(algorighm, hash_input.encode())
    return hash.hexdigest()


key = "0d50d9b3-7d80-422a-a20d-ab4ca017737f"
algorithm = "sha256"


def sign_payload(payload):
    sign = get_signature(payload, key, algorithm)
    return {**payload, "sign": sign}


def check_payload(payload):
    payload = {**payload}
    expected = payload.pop("sign")
    actual = get_signature(payload, key, algorithm)
    return expected == actual
package signing

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"hash"
)

type Signable interface {
	SetSign(sign string)
	ExtractSign() string
}

var hashCtors = map[string]func() hash.Hash{
	"sha256": sha256.New,
}

func getSignature(payload any, key string, algorithm string) (string, error) {
	createHash, ok := hashCtors[algorithm]
	if !ok {
		return "", errors.New("Unsupported hash algorithm")
	}
	var enc []byte
	var err error
	if enc, err = json.Marshal(payload); err != nil {
		return "", err
	}
	// Sort keys alphabetically by unmarshaling back into map and then marshallng the result from it
	pMap := make(map[string]any)
	if err = json.Unmarshal(enc, &pMap); err != nil {
		return "", err
	}
	if enc, err = json.Marshal(pMap); err != nil {
		return "", err
	}
	hash := createHash()
	if _, err = hash.Write(enc); err != nil {
		return "", err
	}
	if _, err = hash.Write([]byte(key)); err != nil {
		return "", err
	}
	sum := hash.Sum(nil)
	return hex.EncodeToString(sum), nil
}

var key = "0d50d9b3-7d80-422a-a20d-ab4ca017737f"
var algorithm = "sha256"

func SignPayload[T Signable](payload T) error {
	sign, err := getSignature(payload, key, algorithm)
	if err != nil {
		return err
	}
	payload.SetSign(sign)
	return nil
}

func CheckPayload[T Signable](payload T) (bool, error) {
	expected := payload.ExtractSign()
	actual, err := getSignature(payload, key, "sha256")
	if err != nil {
		return false, err
	}
	return expected == actual, nil
}
package signing

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"hash"
)

type Signable interface {
	SetSign(sign string)
	ExtractSign() string
}

var hashCtors = map[string]func() hash.Hash{
	"sha256": sha256.New,
}

func getSignature(payload any, key string, algorithm string) (string, error) {
	createHash, ok := hashCtors[algorithm]
	if !ok {
		return "", errors.New("Unsupported hash algorithm")
	}
	var enc []byte
	var err error
	if enc, err = json.Marshal(payload); err != nil {
		return "", err
	}
	// Sort keys alphabetically by unmarshaling back into map and then marshallng the result from it
	pMap := make(map[string]any)
	if err = json.Unmarshal(enc, &pMap); err != nil {
		return "", err
	}
	if enc, err = json.Marshal(pMap); err != nil {
		return "", err
	}
	hash := createHash()
	if _, err = hash.Write(enc); err != nil {
		return "", err
	}
	if _, err = hash.Write([]byte(key)); err != nil {
		return "", err
	}
	sum := hash.Sum(nil)
	return hex.EncodeToString(sum), nil
}

var key = "0d50d9b3-7d80-422a-a20d-ab4ca017737f"
var algorithm = "sha256"

func SignPayload[T Signable](payload T) error {
	sign, err := getSignature(payload, key, algorithm)
	if err != nil {
		return err
	}
	payload.SetSign(sign)
	return nil
}

func CheckPayload[T Signable](payload T) (bool, error) {
	expected := payload.ExtractSign()
	actual, err := getSignature(payload, key, "sha256")
	if err != nil {
		return false, err
	}
	return expected == actual, nil
}
<?php
function is_json_array(array $arr): bool {
	if ($arr === []) {
		return true;
	}
	return array_keys($arr) === range(0, count($arr) - 1);
}

function encodeValueSorted($value): string {
	if (!is_array($value) && !is_object($value)) {
		return json_encode($value);
	}

	if (is_object($value)) {
		$value = (array)$value;
	}

	if (is_json_array($value)) {
		$encoded_elements = array_map('encodeValueSorted', $value);
		return '[' . implode(',', $encoded_elements) . ']';
	}

	$entries = [];
	foreach ($value as $key => $val) {
		$entries[(string)$key] = $val;
	}

	ksort($entries);

	$encoded_entries = [];
	foreach ($entries as $key => $val) {
		$encoded_key = json_encode((string)$key);
		$encoded_value = encodeValueSorted($val);
		$encoded_entries[] = $encoded_key . ':' . $encoded_value;
	}

	return '{' . implode(',', $encoded_entries) . '}';
}

function getSignature($payload, string $key, string $algorithm): string {
	$hashInput = encodeValueSorted($payload) . $key;

	return hash($algorithm, $hashInput);
}

const key = '0d50d9b3-7d80-422a-a20d-ab4ca017737f';
const algorithm = 'sha256';

function signPayload(array $payload): array {
	$sign = getSignature($payload, key, algorithm);

	return array_merge($payload, ['sign' => $sign]);
}

function checkPayload(array $payload): bool {
	$sign = $payload['sign'] ?? null;
	$rest = $payload;
	unset($rest['sign']);

	return $sign !== null && $sign === getSignature($rest, key, algorithm);
}
?>
<?php
function is_json_array(array $arr): bool {
	if ($arr === []) {
		return true;
	}
	return array_keys($arr) === range(0, count($arr) - 1);
}

function encodeValueSorted($value): string {
	if (!is_array($value) && !is_object($value)) {
		return json_encode($value);
	}

	if (is_object($value)) {
		$value = (array)$value;
	}

	if (is_json_array($value)) {
		$encoded_elements = array_map('encodeValueSorted', $value);
		return '[' . implode(',', $encoded_elements) . ']';
	}

	$entries = [];
	foreach ($value as $key => $val) {
		$entries[(string)$key] = $val;
	}

	ksort($entries);

	$encoded_entries = [];
	foreach ($entries as $key => $val) {
		$encoded_key = json_encode((string)$key);
		$encoded_value = encodeValueSorted($val);
		$encoded_entries[] = $encoded_key . ':' . $encoded_value;
	}

	return '{' . implode(',', $encoded_entries) . '}';
}

function getSignature($payload, string $key, string $algorithm): string {
	$hashInput = encodeValueSorted($payload) . $key;

	return hash($algorithm, $hashInput);
}

const key = '0d50d9b3-7d80-422a-a20d-ab4ca017737f';
const algorithm = 'sha256';

function signPayload(array $payload): array {
	$sign = getSignature($payload, key, algorithm);

	return array_merge($payload, ['sign' => $sign]);
}

function checkPayload(array $payload): bool {
	$sign = $payload['sign'] ?? null;
	$rest = $payload;
	unset($rest['sign']);

	return $sign !== null && $sign === getSignature($rest, key, algorithm);
}
?>

Thumbnails

Archive with all thumbnails

Name Previw
RealLiveSlots-190x190.png RealLiveSlots-190x190.png
RealLiveSlots-236x110.png RealLiveSlots-236x110.png
RealLiveSlots-290x196.png RealLiveSlots-290x196.png
RealLiveSlots-337x181.png RealLiveSlots-337x181.png
RealLiveSlots-380x380.png RealLiveSlots-380x380.png
RealLiveSlots-thumb-224x264.png RealLiveSlots-thumb-224x264.png
RealLiveSlots-thumb-448x528.png RealLiveSlots-thumb-448x528.png

Brand Assets

Archive with all brand assets

Name Previw
RealLiveSlots-logo.svg RealLiveSlots-logo.svg
RealLiveSlots-logo-310x310.png RealLiveSlots-logo-310x310.png