# What is Trueplay?

Trueplay provides its proprietary Loyalty Booster Suite to enable iGaming brands to build lasting customer relationships based on trust and mutual benefit.

The suite includes tools and services that ensure player interactions with iGaming platforms are exciting right from the start. The functionality of each solution is driven by its purpose at a particular marketing funnel stage.

<figure><img src="/files/bg5ar9uU4PNKIPv0cli3" alt=""><figcaption></figcaption></figure>

In the upcoming FAQ section, we’ll talk about each product and service and explain how they help improve critical casino performance metrics.


# FAQ

Find out everything you need to know before the start.

### **What products make up the Loyalty Booster Suite?**

[CopyStake](https://trueplay.io/copystake) enables you to host gameplay sessions on your website and simultaneously stream them on popular platforms like Kick and Twitch. That way, you will drive traffic and generate extra revenue by letting players copy streamers' bets.

The livestreaming tool is available in three modes: Bet Behind, Copy in Pool, and No Code. Modes differ in player engagement scenarios, supported game types, and integration approaches. Learn more about CopyStake and its modes in the video.

{% embed url="<https://youtu.be/65qFHzZgM_0?si=CZp1MjS74uDaPksS>" %}

[Funnels No Code](https://trueplay.io/funnels-no-code) is an acquisition tool that enables the creation of marketing campaign funnels to attract new customers and retain existing ones. It features gamification mechanics, Missions and the Tap to Earn game, which encourage prospects and customers to interact with a brand in exchange for guaranteed rewards.&#x20;

[Loyalty Program](https://trueplay.io/blog/how-trueplays-loyalty-programs-work) consists of two features — Play to Earn and Hold to Earn. Together, they help clients to motivate users to play more, deposit more, and keep funds within the casino ecosystem.

* Play to Earn: players receive rakeback tokens for making bets on the iGaming platform.
* Hold to Earn: users can freeze tokens they deposited and accrued through Play to Earn and get them back with an interest that depends on the platform's GGR generated over a token holding period.

#### How are loyalty rewards calculated?

* The Play to Earn reward is calculated as:

{% hint style="info" %}
*Bet Amount \* Bet Wager*
{% endhint %}

To check bet wagers, users should navigate to the Play to Earn settings.

* The Hold to Earn reward is based on the platform’s GGR generated over the program duration, which is 8 hours, 1 day, or 3 days. The reward is calculated as:

{% hint style="info" %}
*GGR during the Hold to Earn \* GGR share defined by the program \* User’s share in the holding pool \* Loyalty Token exchange rate*
{% endhint %}

*Web 3 loyalty programs* will help you grow players' engagement by making them interested in your economic success. Unlike traditional points-based programs, the Web3 ones use digital tokens that can be purchased, saved, and traded like other cryptocurrencies. The more customers hold and use these digital tokens, the greater their value. As a result, they build wealth when your revenue increases. &#x20;

We also provide [Trueplay Explorer](https://explorer.trueplay.io/), the tool that displays activity and transactional data to end-users. That way, players can ensure the casino allocates rewards accurately. This level of transparency will significantly enhance trust and confidence in your brand.

Additionally, to maximize the effectiveness of Trueplay loyalty programs, we offer *Marketing Campaigns* as a bonus to increase loyalty program awareness among platform users.

### How does Trueplay attract users?

* Customers visit a platform to spend time with a streamer they know or one whom the casino previously promoted. They may start copying streamers’ bets even if they initially wanted to watch broadcasts.&#x20;
* AI Streamers entertain the crowd when human streamers are unavailable. Therefore, online casinos keep customers engaged nonstop through CopyStake streams
* Players consider Hold to Earn a safe alternative to betting. It is risk-free for both players and platforms because if the GGR turns out to be negative, the platform doesn’t have to give out any rewards, but users get back the same amount of loyalty tokens they had frozen.
* When users get rewards, they can withdraw their loyalty tokens to the platform’s balance and continue playing games.
* To get more from Hold to Earn, players should engage in a gaming activity to receive rakeback tokens from Play to Earn.
* For new players, Trueplay provides the engaging Marketing Campaigns feature that rewards players for various activities and stokes their interest.

### What results can my platform reach with Trueplay?

Trueplay focuses on key business indicators to boost the platform’s profitability.

Our [behavioral research](https://cdn.trueplay.io/Behavioral_Research.pdf) demonstrates that Play to Earn and Hold to Earn improve player engagement and financial performance for iGaming brands.

<figure><img src="/files/CyOr7yN7HaRhxPlJ86yT" alt=""><figcaption></figcaption></figure>


# Specifications

This page lists the supported fiat and cryptocurrency options, as well as available languages and restricted countries.&#x20;

We use the exchangeratesapi (<https://exchangeratesapi.io/>) API to ensure accurate currency rates, with fiat currencies updated every 3 hours and cryptocurrencies every hour. The exchangeratesapi.io API provides real-time and historical data for a total of 168 world currencies.

If you need additional fiat or crypto currencies, please contact us to discuss these options before integration.

### Available currencies

{% tabs %}
{% tab title="fiat" %}

<table><thead><tr><th width="347">Code</th><th>Name</th></tr></thead><tbody><tr><td>AED</td><td>United Arab Emirates Dirham</td></tr><tr><td>AFN</td><td>Afghan Afghani</td></tr><tr><td>ALL</td><td>Albanian Lek</td></tr><tr><td>AMD</td><td>Armenian Dram</td></tr><tr><td>ANG</td><td>Netherlands Antillean Guilder</td></tr><tr><td>AOA</td><td>Angolan Kwanza</td></tr><tr><td>ARS</td><td>Argentine Peso</td></tr><tr><td>AUD</td><td>Australian Dollar</td></tr><tr><td>AWG</td><td>Aruban Florin</td></tr><tr><td>AZN</td><td>Azerbaijani Manat</td></tr><tr><td>BAM</td><td>Bosnia-Herzegovina Convertible Mark</td></tr><tr><td>BBD</td><td>Barbadian Dollar</td></tr><tr><td>BDT</td><td>Bangladeshi Taka</td></tr><tr><td>BGN</td><td>Bulgarian Lev</td></tr><tr><td>BHD</td><td>Bahraini Dinar</td></tr><tr><td>BIF</td><td>Burundian Franc</td></tr><tr><td>BMD</td><td>Bermudan Dollar</td></tr><tr><td>BND</td><td>Brunei Dollar</td></tr><tr><td>BOB</td><td>Bolivian Boliviano</td></tr><tr><td>BRL</td><td>Brazilian Real</td></tr><tr><td>BSD</td><td>Bahamian Dollar</td></tr><tr><td>BTC</td><td>Bitcoin</td></tr><tr><td>BTN</td><td>Bhutanese Ngultrum</td></tr><tr><td>BWP</td><td>Botswanan Pula</td></tr><tr><td>BYN</td><td>Belarusian Ruble</td></tr><tr><td>BYR</td><td>Belarusian Ruble</td></tr><tr><td>BZD</td><td>Belize Dollar</td></tr><tr><td>CAD</td><td>Canadian Dollar</td></tr><tr><td>CDF</td><td>Congolese Franc</td></tr><tr><td>CHF</td><td>Swiss Franc</td></tr><tr><td>CLF</td><td>Chilean Unit of Account (UF)</td></tr><tr><td>CLP</td><td>Chilean Peso</td></tr><tr><td>CNY</td><td>Chinese Yuan</td></tr><tr><td>COP</td><td>Colombian Peso</td></tr><tr><td>CRC</td><td>Costa Rican Colón</td></tr><tr><td>CUC</td><td>Cuban Convertible Peso</td></tr><tr><td>CUP</td><td>Cuban Peso</td></tr><tr><td>CVE</td><td>Cape Verdean Escudo</td></tr><tr><td>CZK</td><td>Czech Republic Koruna</td></tr><tr><td>DJF</td><td>Djiboutian Franc</td></tr><tr><td>DKK</td><td>Danish Krone</td></tr><tr><td>DOP</td><td>Dominican Peso</td></tr><tr><td>DZD</td><td>Algerian Dinar</td></tr><tr><td>EEK</td><td>Estonian Kroon</td></tr><tr><td>EGP</td><td>Egyptian Pound</td></tr><tr><td>ERN</td><td>Eritrean Nakfa</td></tr><tr><td>ETB</td><td>Ethiopian Birr</td></tr><tr><td>EUR</td><td>Euro</td></tr><tr><td>FJD</td><td>Fijian Dollar</td></tr><tr><td>FKP</td><td>Falkland Islands Pound</td></tr><tr><td>GBP</td><td>British Pound Sterling</td></tr><tr><td>GEL</td><td>Georgian Lari</td></tr><tr><td>GGP</td><td>Guernsey Pound</td></tr><tr><td>GHS</td><td>Ghanaian Cedi</td></tr><tr><td>GIP</td><td>Gibraltar Pound</td></tr><tr><td>GMD</td><td>Gambian Dalasi</td></tr><tr><td>GNF</td><td>Guinean Franc</td></tr><tr><td>GTQ</td><td>Guatemalan Quetzal</td></tr><tr><td>GYD</td><td>Guyanaese Dollar</td></tr><tr><td>HKD</td><td>Hong Kong Dollar</td></tr><tr><td>HNL</td><td>Honduran Lempira</td></tr><tr><td>HRK</td><td>Croatian Kuna</td></tr><tr><td>HTG</td><td>Haitian Gourde</td></tr><tr><td>HUF</td><td>Hungarian Forint</td></tr><tr><td>IDR</td><td>Indonesian Rupiah</td></tr><tr><td>ILS</td><td>Israeli New Sheqel</td></tr><tr><td>IMP</td><td>Manx pound</td></tr><tr><td>INR</td><td>Indian Rupee</td></tr><tr><td>IQD</td><td>Iraqi Dinar</td></tr><tr><td>IRR</td><td>Iranian Rial</td></tr><tr><td>ISK</td><td>Icelandic Króna</td></tr><tr><td>JEP</td><td>Jersey Pound</td></tr><tr><td>JMD</td><td>Jamaican Dollar</td></tr><tr><td>JOD</td><td>Jordanian Dinar</td></tr><tr><td>JPY</td><td>Japanese Yen</td></tr><tr><td>KES</td><td>Kenyan Shilling</td></tr><tr><td>KGS</td><td>Kyrgystani Som</td></tr><tr><td>KHR</td><td>Cambodian Riel</td></tr><tr><td>KMF</td><td>Comorian Franc</td></tr><tr><td>KPW</td><td>North Korean Won</td></tr><tr><td>KRW</td><td>South Korean Won</td></tr><tr><td>KWD</td><td>Kuwaiti Dinar</td></tr><tr><td>KYD</td><td>Cayman Islands Dollar</td></tr><tr><td>KZT</td><td>Kazakhstani Tenge</td></tr><tr><td>LAK</td><td>Laotian Kip</td></tr><tr><td>LBP</td><td>Lebanese Pound</td></tr><tr><td>LKR</td><td>Sri Lankan Rupee</td></tr><tr><td>LRD</td><td>Liberian Dollar</td></tr><tr><td>LSL</td><td>Lesotho Loti</td></tr><tr><td>LTL</td><td>Lithuanian Litas</td></tr><tr><td>LVL</td><td>Latvian Lats</td></tr><tr><td>LYD</td><td>Libyan Dinar</td></tr><tr><td>MAD</td><td>Moroccan Dirham</td></tr><tr><td>MDL</td><td>Moldovan Leu</td></tr><tr><td>MGA</td><td>Malagasy Ariary</td></tr><tr><td>MKD</td><td>Macedonian Denar</td></tr><tr><td>MMK</td><td>Myanma Kyat</td></tr><tr><td>MNT</td><td>Mongolian Tugrik</td></tr><tr><td>MOP</td><td>Macanese Pataca</td></tr><tr><td>MRO</td><td>Mauritanian Ouguiya</td></tr><tr><td>MUR</td><td>Mauritian Rupee</td></tr><tr><td>MVR</td><td>Maldivian Rufiyaa</td></tr><tr><td>MWK</td><td>Malawian Kwacha</td></tr><tr><td>MXN</td><td>Mexican Peso</td></tr><tr><td>MYR</td><td>Malaysian Ringgit</td></tr><tr><td>MZN</td><td>Mozambican Metical</td></tr><tr><td>NAD</td><td>Namibian Dollar</td></tr><tr><td>NGN</td><td>Nigerian Naira</td></tr><tr><td>NIO</td><td>Nicaraguan Córdoba</td></tr><tr><td>NOK</td><td>Norwegian Krone</td></tr><tr><td>NPR</td><td>Nepalese Rupee</td></tr><tr><td>NZD</td><td>New Zealand Dollar</td></tr><tr><td>OMR</td><td>Omani Rial</td></tr><tr><td>PAB</td><td>Panamanian Balboa</td></tr><tr><td>PEN</td><td>Peruvian Nuevo Sol</td></tr><tr><td>PGK</td><td>Papua New Guinean Kina</td></tr><tr><td>PHP</td><td>Philippine Peso</td></tr><tr><td>PKR</td><td>Pakistani Rupee</td></tr><tr><td>PLN</td><td>Polish Zloty</td></tr><tr><td>PYG</td><td>Paraguayan Guarani</td></tr><tr><td>QAR</td><td>Qatari Rial</td></tr><tr><td>RON</td><td>Romanian Leu</td></tr><tr><td>RSD</td><td>Serbian Dinar</td></tr><tr><td>RUB</td><td>Russian Ruble</td></tr><tr><td>RWF</td><td>Rwandan Franc</td></tr><tr><td>SAR</td><td>Saudi Riyal</td></tr><tr><td>SBD</td><td>Solomon Islands Dollar</td></tr><tr><td>SCR</td><td>Seychellois Rupee</td></tr><tr><td>SDG</td><td>Sudanese Pound</td></tr><tr><td>SEK</td><td>Swedish Krona</td></tr><tr><td>SGD</td><td>Singapore Dollar</td></tr><tr><td>SHP</td><td>Saint Helena Pound</td></tr><tr><td>SLL</td><td>Sierra Leonean Leone</td></tr><tr><td>SOS</td><td>Somali Shilling</td></tr><tr><td>SRD</td><td>Surinamese Dollar</td></tr><tr><td>STD</td><td>São Tomé and Príncipe Dobra</td></tr><tr><td>SVC</td><td>Salvadoran Colón</td></tr><tr><td>SYP</td><td>Syrian Pound</td></tr><tr><td>SZL</td><td>Swazi Lilangeni</td></tr><tr><td>THB</td><td>Thai Baht</td></tr><tr><td>TJS</td><td>Tajikistani Somoni</td></tr><tr><td>TMT</td><td>Turkmenistani Manat</td></tr><tr><td>TND</td><td>Tunisian Dinar</td></tr><tr><td>TOP</td><td>Tongan Paʻanga</td></tr><tr><td>TRY</td><td>Turkish Lira</td></tr><tr><td>TTD</td><td>Trinidad and Tobago Dollar</td></tr><tr><td>TWD</td><td>New Taiwan Dollar</td></tr><tr><td>TZS</td><td>Tanzanian Shilling</td></tr><tr><td>UAH</td><td>Ukrainian Hryvnia</td></tr><tr><td>UGX</td><td>Ugandan Shilling</td></tr><tr><td>USD</td><td>United States Dollar</td></tr><tr><td>UYU</td><td>Uruguayan Peso</td></tr><tr><td>UZS</td><td>Uzbekistan Som</td></tr><tr><td>VEF</td><td>Venezuelan Bolívar Fuerte</td></tr><tr><td>VND</td><td>Vietnamese Dong</td></tr><tr><td>VUV</td><td>Vanuatu Vatu</td></tr><tr><td>WST</td><td>Samoan Tala</td></tr><tr><td>XAF</td><td>CFA Franc BEAC</td></tr><tr><td>XAG</td><td>Silver (troy ounce)</td></tr><tr><td>XAU</td><td>Gold (troy ounce)</td></tr><tr><td>XCD</td><td>East Caribbean Dollar</td></tr><tr><td>XDR</td><td>Special Drawing Rights</td></tr><tr><td>XOF</td><td>CFA Franc BCEAO</td></tr><tr><td>XPF</td><td>CFP Franc</td></tr><tr><td>YER</td><td>Yemeni Rial</td></tr><tr><td>ZAR</td><td>South African Rand</td></tr><tr><td>ZMK</td><td>Zambian Kwacha (pre-2013)</td></tr><tr><td>ZMW</td><td>Zambian Kwacha</td></tr><tr><td>ZWL</td><td>Zimbabwean Dollar</td></tr></tbody></table>
{% endtab %}

{% tab title="crypto" %}

| Code          | Name         |
| ------------- | ------------ |
| BCH           | Bitcoin Cash |
| BNB           | Binance Coin |
| BTC           | Bitcoin      |
| BUSD          | Binance USD  |
| DASH          | Dash         |
| DOGE          | Dogecoin     |
| ETH           | Ethereum     |
| LTC           | Litecoin     |
| MATIC         | Polygon      |
| SUSHI         | SushiSwap    |
| TRX           | TRON         |
| USDC          | USD Coin     |
| USDT          | Tether       |
| XMR           | Monero       |
| XRP           | Ripple       |
| ZEC           | Zcash        |
| {% endtab %}  |              |
| {% endtabs %} |              |

### Available languages

If you need additional languages, please contact us to discuss these options before integration.

| Code | Name       |
| ---- | ---------- |
| BN   | Bengali    |
| HT   | Creole     |
| CS   | Czech      |
| EN   | English    |
| FR   | French     |
| DE   | German     |
| HU   | Hungarian  |
| ID   | Indonesian |
| JA   | Japanese   |
| KK   | Kazakh     |
| LT   | Lithuanian |
| PL   | Polish     |
| PT   | Portuguese |
| RU   | Russian    |
| SK   | Slovakian  |
| ES   | Spanish    |
| TR   | Turkish    |
| UK   | Ukrainian  |
| UZ   | Uzbek      |

### Restricted countries

Afghanistan, Belarus, Central African Republic, DR Congo, Eritrea, Guinea-Bissau, Iran, Iraq, Lebanon, Liberia, Libya, Myanmar, North Korea, Russia Federation, Somalia, South Sudan, Sudan, Syria, UK, USA, Yemen.


# Loyalty Integration

### Component diagram <a href="#components-diagram" id="components-diagram"></a>

<figure><img src="/files/B72NXlQAQt2CstWwP0Tz" alt=""><figcaption></figcaption></figure>

**Step 1:** To start Trueplay integration, the operator should provide access to game data through the Send Game Transaction endpoint.

**Step 2:** The Trueplay specialist receives data, sets up a user account in the database, and creates a Trueplay ID.

**Note:** The first time a user visits the Trueplay loyalty program page, they are immediately added to the Trueplay database.

**Step 3:** The operator integrates the Get Loyalty Page endpoint and receives a link to the loyalty program.

**Step 4:** To allow users to make deposits and withdrawals, the operator should set up the following endpoints:

* ***Get User Balance:*** to notify Trueplay about the user’s current balance.
* ***Token Exchange:*** for Trueplay to refresh the user’s balance when they make a withdrawal.

**Note:** Trueplay sends a payment notification when a user purchases tokens in the player’s account currency.

**Step 5:** The integration requires several endpoints to enable users to receive tokens for Marketing Campaigns:

* **Tokens for Registration:** This means that the user will receive tokens when placing the first bet or visiting the loyalty page.
  * If it is necessary to credit tokens before the user performs these actions, there is an optional Create User endpoint, which adds a user to the Trueplay database.
  * The user gets registration tokens right after Trueplay receives a request.
* **KYC Tokens:** The operator must notify Trueplay that the user has passed KYC.
  * Afterward, the operator should set up the Update User Account endpoint to change the status of passing the KYC verification from false to true.
* **Deposit Tokens:** In the admin panel, navigating to the Marketing Campaigns section, the operator should create a promo campaign and add users who made a deposit using the Deposit API method.

**IMPORTANT:**&#x20;

1. Operators need to whitelist the Trueplay IPs to receive callbacks about the status of transactions. Otherwise, Trueplay will return errors for deposit/withdrawal tokens requests.

<details>

<summary><strong>IPs for whitelisting</strong></summary>

18.193.249.95

18.184.86.250

18.196.113.251

</details>

2. All operator IP addresses must be whitelisted within the Trueplay system before traffic can be sent. You can add and manage your IPs through the Trueplay Admin Panel.

#### Important aspects **for cashback calculation**

If your platform offers sports betting, the operator should make the following updates:

* For WIN transactions on the Sportsbook game type, the operator must send transactions with losses as WIN = 0.
* In the reference ID parameter, for other WIN type transactions connected to the Sportsbook game type, the operator should send the BET identifier relevant to the reward.

**IMPORTANT!** WIN = 0 transactions require a unique transaction identifier.

## Trueplay endpoints <a href="#trueplay-endpoints" id="trueplay-endpoints"></a>

## Get Loyalty page&#x20;

### Authorized user

<mark style="color:blue;">`GET`</mark> `https://integration.trueplay.io/api/v2/user/{operatorUserId}/widget?language=EN`

**Method Description:** This method allows authorized users to retrieve a link to the loyalty page, suitable for embedding within an iframe on the casino platform.

In the request, you need to indicate:

* operatorUserId
* X-API key
* language

In response, you will receive a URL of the page that has to be displayed through an iframe on the casino side.

#### Path Parameters

| Name                                             | Type   | Description                 |
| ------------------------------------------------ | ------ | --------------------------- |
| operatorUserId<mark style="color:red;">\*</mark> | String | ID of user on Operator side |

#### Query Parameters

| Name                                       | Type   | Description                                                                                                                                                                 |
| ------------------------------------------ | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| language<mark style="color:red;">\*</mark> | String | <p>Localization of user loyalty page<br>Default language of loyalty page: EN</p><p>Available languages:  BN, CS, DE, EN, ES, FR, HU, ID, JA, LT, LV, PL, PT, RU, SK, TR</p> |
| view                                       | String | <p>Allows to open the required view of the loyalty page.<br>Available view: account, analytics, deposit, withdraw, token-sale, stream</p>                                   |

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

{% tabs %}
{% tab title="200: OK Request is succesful" %}
{% code overflow="wrap" %}

```json
{
"url": "https://widget.trueplay.io?token=eyJhbGciOiJIUzUxMiJ9.eyJpZF9vcGVyYXRvciI6MSwiaWRfdXNlciI6NzUxMSwicm9sZSI6IlJPTEVfVVNFUiIsImV4cCI6MTYzNDY0NjA5Mn0.umIbsJCJAQmATaVj50nS1uFAhWpLLf3Ztq953aomIS7Vl5Es-BlHuKdof_CYGBcAsimR3q1K1_3LmDZXB8iC8w” 
}
```

{% endcode %}
{% endtab %}

{% tab title="400: Bad Request Invalid request parameters provided" %}

{% endtab %}

{% tab title="401: Unauthorized Requester is unauthorized to perform an action" %}

```
{
  "message": "Authentication is required to access this resource"
}
```

{% endtab %}

{% tab title="403: Forbidden Requester is forbidden to perform an action" %}

{% endtab %}

{% tab title="404: Not Found Resource not found" %}

{% endtab %}
{% endtabs %}

### Anonymous user

<mark style="color:blue;">`GET`</mark>&#x20;

`https://integration.trueplay.io/api/v2/user/widget`

**Method Description:** This method allows anonymous users to retrieve a link to the loyalty page, suitable for embedding within an iframe on the casino platform.

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

**Example response**

{% tabs %}
{% tab title="200: OK Request is succesful" %}
{% code overflow="wrap" %}

```javascript
{
"url": "https://widget.trueplay.io?token=eyJhbGciOiJIUzUxMiJ9.eyJpZF9vcGVyYXRvciI6MSwiaWRfdXNlciI6NzUxMSwicm9sZSI6IlJPTEVfVVNFUiIsImV4cCI6MTYzNDY0NjA5Mn0.umIbsJCJAQmATaVj50nS1uFAhWpLLf3Ztq953aomIS7Vl5Es-BlHuKdof_CYGBcAsimR3q1K1_3LmDZXB8iC8w” 
}
```

{% endcode %}
{% endtab %}

{% tab title="400: Bad Request Invalid request parameters provided" %}

{% endtab %}

{% tab title="401: Unauthorized Requester is unauthorized to perform an action" %}

```
{
  "message": "Authentication is required to access this resource"
}
```

{% endtab %}

{% tab title="403: Forbidden Requester is forbidden to perform an action" %}

{% endtab %}

{% tab title="404: Not Found Resource not found" %}

{% endtab %}
{% endtabs %}

## Get transaction data

### **Get user loyalty balance**

<mark style="color:blue;">`GET`</mark> `https://integration.trueplay.io/api/v1/user/{operatorUserId}/balance`

**Method Description:** This method retrieves the user's balance on the loyalty page, allowing the operator to display this balance within the casino platform.

In the request, you need to indicate:

* operatorUserId
* X-API key

In response you will receive the user's token balance on the loyalty page.

#### Path Parameters

| Name                                             | Type   | Description                 |
| ------------------------------------------------ | ------ | --------------------------- |
| operatorUserId<mark style="color:red;">\*</mark> | String | ID of user on Operator side |

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

**Example:**

{% tabs %}
{% tab title="200: OK Request is sucessful" %}

```json
{
  "balance": 0.0001
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid request parameters provided" %}

{% endtab %}

{% tab title="Untitled" %}

{% endtab %}

{% tab title="401: Unauthorized Requester is unauthorized to perform an action" %}

{% endtab %}

{% tab title="403: Forbidden Requester is forbidden to perform an action" %}

{% endtab %}

{% tab title="404 Resource not found" %}

{% endtab %}
{% endtabs %}

### Send game transaction

<mark style="color:green;">`POST`</mark>&#x20;

`https://{operator-name}.proxy.trueplay.io/api/v1/accept`

**Method Description:** This method allows operators to send game transaction data to Trueplay. Each transaction should include essential details to support the core functionality of the Trueplay Loyalty system.

The data on game transactions is required for:

* the accrual of Play to Earn rewards to users for each bet
* the calculation GGR project for the accrual of rewards to participants of the Hold to Earn program
* Flexible mission evaluation based on transaction metadata

**IMPORTANT!**&#x20;

> Correct use of transaction types is required for accurate reward calculation:

* BET, WIN - core game actions
* ROLLBACK - cancels a previous BET or WIN

Particularities of data transmission:

* Cashout transactions for sports bets need to be passed as WIN.
* Sportbook initial transaction must be sent with parameter Type = Sportbook
* Sportbook outcomes must be sent with parameter Type = Win and reference TransactionId (initial transaction identifier). Transaction Amount depends on bet outcome type:
  * winning bet — Amount is equal to amount won
  * losing bet — Amount is 0
  * cashout done — Amount is equal to cashout amount

#### Headers

| Name                                        | Type   | Description                                       |
| ------------------------------------------- | ------ | ------------------------------------------------- |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by Trueplay to access the API |

#### Request Body

| Name                                                     | Type           | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| -------------------------------------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| operatorUserId<mark style="color:red;">\*</mark>         | String         | ID of the user on the operator’s side                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| transactionId<mark style="color:red;">\*</mark>          | String         | Unique identifier for the transaction (BET, WIN, ROLLBACK)                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| referenceTransactionId<mark style="color:red;">\*</mark> | String \| null | <p>Used to link related transactions.</p><p>• For BET transactions, this will be null as they are the starting point of the sequence.</p><p>• For WIN transactions, this field should reference the transactionId of the corresponding BET.</p><p>• For ROLLBACK transactions, this field should reference the transactionId of the original BET being rolled back. This also applies to rolling back WIN transactions; the referenceTransactionId should point to the transactionId of the WIN being rolled back.</p> |
| type<mark style="color:red;">\*</mark>                   | String         | Transaction type: BET, WIN, or ROLLBACK                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| gameProvider<mark style="color:red;">\*</mark>           | String         | Game provider name                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| gamePublisher<mark style="color:red;">\*</mark>          | String         | Game publisher name                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| gameCode<mark style="color:red;">\*</mark>               | String         | Game code                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| gameName<mark style="color:red;">\*</mark>               | String         | Game name                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| gameType<mark style="color:red;">\*</mark>               | String         | Type of game (e.g., Slots, Sportsbook)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| currency<mark style="color:red;">\*</mark>               | String         | ISO currency code (e.g., USDT, USD)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| amount<mark style="color:red;">\*</mark>                 | Integer        | <p>Transaction amount. </p><p>Up to 2 decimals for fiat, 8 for crypto</p>                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| customFields                                             | Object (Map)   | *Optional.* A key-value map of custom metadata fields for mission logic                                                                                                                                                                                                                                                                                                                                                                                                                                                |

**Important**: Ensure that referenceTransactionId correctly links to the associated BET or BONUS\_BET, or WIN or BONUS\_WIN as applicable. Setting it to 0 or leaving it blank when it should be populated will result in errors and incorrect transaction processing.

**Request example**

{% tabs %}
{% tab title="Request example (BET)" %}

```
Request
curl --location 'https://{operator-name}.proxy.trueplay.io/api/v1/accept' 
--header 'Content-Type: application/json' \
--header 'X-API-KEY: your-api-key-here' \
--data '{
    "userId": "1",
    "transactionId": "12345",
    "type": "WIN",
    "gameProvider": "NOLIMIT_CITY",
    "gamePublisher": "EVOLUTION",
    "gameCode": "Mental",
    "gameName": "Mental",
    "gameType": "Slots",
    "currency": "USDT",
    "amount": 25.00000000,
}
```

{% endtab %}

{% tab title="Request example (WIN)" %}

```
Request
curl --location 'https://{operator-name}.proxy.trueplay.io/api/v1/accept' 
--header 'Content-Type: application/json' \
--header 'X-API-KEY: your-api-key-here' \
--data '{
    "userId": "1",
    "transactionId": "5678",
    "type": "WIN",
    "gameProvider": "NOLIMIT_CITY",
    "gamePublisher": "EVOLUTION",
    "gameCode": "Mental",
    "gameName": "Mental",
    "gameType": "Slots",
    "currency": "USDT",
    "amount": 50.00000000,
}'
```

{% endtab %}

{% tab title="Request example (ROLLBACK BET)" %}

```
Request
curl --location 'https://{operator-name}.proxy.trueplay.io/api/v1/accept' 
--header 'Content-Type: application/json' \
--header 'X-API-KEY: your-api-key-here' \
--data '{
    "userId": "1",
    "transactionId": "54321",
    "type": "ROLLBACK",
    "gameProvider": "NOLIMIT_CITY",
    "gamePublisher": "EVOLUTION",
    "gameCode": "Mental",
    "gameName": "Mental",
    "gameType": "Slots",
    "currency": "USDT",
    "amount": 25.00000000,
    "referenceTransactionId": "12345"
}'
```

{% endtab %}

{% tab title="Request example (ROLLBACK WIN)" %}

```
Request
curl --location 'https://{operator-name}.proxy.trueplay.io/api/v1/accept' 
--header 'Content-Type: application/json' \
--header 'X-API-KEY: your-api-key-here' \
--data '{
    "userId": "1",
    "transactionId": "43210",
    "type": "ROLLBACK",
    "gameProvider": "NOLIMIT_CITY",
    "gamePublisher": "EVOLUTION",
    "gameCode": "Mental",
    "gameName": "Mental",
    "gameType": "Slots",
    "currency": "USDT",
    "amount": 50.00000000,
    "referenceTransactionId": "5678"
}'
```

{% endtab %}
{% endtabs %}

**Response example**

{% tabs %}
{% tab title="200: OK Request is successful" %}

```
200 OK
```

{% endtab %}

{% tab title="400: Bad Request " %}

```
400 Bad Request
```

{% endtab %}
{% endtabs %}

## Operator endpoints <a href="#operator-endpoints" id="operator-endpoints"></a>

### Get User Balance

<mark style="color:green;">`POST`</mark>&#x20;

`https://{operatorBaseUrl}/user-balance`

**Method Description:** This method allows retrieving the current balance of a user in a casino. Operators must provide the user's unique identifier on their side, and upon successful authentication, the method returns the user's balance along with the currency in which it is denominated.&#x20;

**This method is necessary to implement the token exchange endpoints.**

#### Headers

| Name                                                  | Type   | Description                                                                    |
| ----------------------------------------------------- | ------ | ------------------------------------------------------------------------------ |
| X-REQUEST-SIGNATURE<mark style="color:red;">\*</mark> | String | <p>Request signature, Base64(HmacSHA512(SecretKey, MD5(request body)))<br></p> |

#### Request Body

| Name                                             | Type   | Description                 |
| ------------------------------------------------ | ------ | --------------------------- |
| operatorUserId<mark style="color:red;">\*</mark> | String | ID of user on Operator side |

{% tabs %}
{% tab title="200: OK Request is sucessful" %}
{% code fullWidth="true" %}

```json
 {
 "balance": 100.12,
 "currency": "USD"
 }
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Token Exchange

<mark style="color:green;">`POST`</mark>&#x20;

`https://{operatorBaseUrl}/token-exchange`

**Method Description:** This method enables users to deposit tokens using funds from the casino balance or withdraw tokens to the casino balance. It supports two actions: CREDIT and DEBIT.

* **CREDIT:** Withdraws tokens from the loyalty page balance and converts them into money, adding them to the casino balance.
* **DEBIT:** Deposits money from the casino balance and converts it into tokens, adding them to the loyalty page balance.

To integrate Token Exchange endpoints successfully, operators must specify the Callback URL from which deposit/withdrawal requests will be executed and generate transaction signatures using the Secret Key, which should be included in the request header. Correct transaction types (CREDIT or DEBIT) must be provided in the request body for the method to function accurately.

#### Headers

<table><thead><tr><th width="250">Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>X-REQUEST-SIGNATURE<mark style="color:red;">*</mark></td><td>String</td><td>Request signature, Base64(HmacSHA512(SecretKey, MD5(request body)))</td></tr></tbody></table>

#### Request Body

| Name                                             | Type    | Description                                                                                                                                                                                               |
| ------------------------------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id<mark style="color:red;">\*</mark>             | String  | operation ID                                                                                                                                                                                              |
| action<mark style="color:red;">\*</mark>         | String  | Specifies the action to be performed. Accepted values are CREDIT (transfer from token balance to operator account balance) and DEBIT (transfer from operator account balance to token balance)            |
| amount<mark style="color:red;">\*</mark>         | Integer | <p></p><ul><li>Fiat: Although fiat currencies typically allow up to two decimal places (e.g., USD: 10.25)</li><li>Cryptocurrency: The amount parameter adheres to a maximum of 8 decimal places</li></ul> |
| currency                                         | String  | Currency code used in the transaction                                                                                                                                                                     |
| tokenAmount<mark style="color:red;">\*</mark>    | Integer | Token amount involved in the transaction                                                                                                                                                                  |
| operatorId<mark style="color:red;">\*</mark>     | String  | ID of Operator                                                                                                                                                                                            |
| operatorUserId<mark style="color:red;">\*</mark> | String  | ID of user on Operator side                                                                                                                                                                               |

{% tabs %}
{% tab title="200: OK Request is succesful" %}

```json
{
"balance": 100.12,
"currency": "USD"
}
```

{% endtab %}

{% tab title="400: Deposit is failed" %}

{% endtab %}

{% tab title="403: User has a bonus balance" %}

{% endtab %}
{% endtabs %}

## Request signature

Requests from TruePlay include `X-REQUEST-SIGNATURE` header.

Example of how to generate a signature for SecretKey = `secret`

> node \
> \
> Welcome to Node.js v16.13.0. Type ".help" for more information.\
> \
> var crypto = require('crypto'); \
> undefined \
> \
> var hasher = crypto.createHash('md5'); \
> undefined \
> \
> var hashed = hasher.update('{"id":"103193","action":"CREDIT","amount":4.123,"currency":"USD","exchangeRate":0.00203250655485,"tokenAmount":2500,"operatorId":123,"operatorUserId":"333"}') \
> undefined\
> \
> var hash = hashed.digest('hex'); \
> undefined \
> \
> var hmac = crypto.createHmac('sha512', 'secret'); \
> undefined \
> \
> hmac.update(hash); \
> Hmac { \_options: undefined, \[Symbol(kHandle)]: Hmac {}, \[Symbol(kState)]: { \[Symbol(kFinalized)]: false } } \
> \
> var sign = hmac.digest('base64'); \
> undefined \
> \
> console.log('signature: ' + sign); \
> signature: IifPVbfXptagZ6qSXH9vYrQiqSP4sKIC+hV+39z2K+FlLzRoEboPGTTymjmeuAhN1i0ICDyyrrufYspgAJmxHQ==

## Marketing Campaigns

### Create user account

<mark style="color:green;">`POST`</mark>&#x20;

`https://integration.trueplay.io/api/v1/user`

Create user on Trueplay side to get promo reward.  &#x20;

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

#### Request Body

<table><thead><tr><th width="283">Name</th><th width="212">Type</th><th>Description</th></tr></thead><tbody><tr><td>kyc</td><td>String</td><td>Indicates whether the user has passed the KYC verification process. When <strong>true</strong>, the user has successfully completed the KYC process; when <strong>false</strong>, the user has not yet completed KYC.</td></tr><tr><td>operatorUserId<mark style="color:red;">*</mark></td><td>String</td><td>ID of user on Operator side</td></tr></tbody></table>

{% tabs %}
{% tab title="200: OK Request is successful" %}

```
"operatorUserId": "john12345"
```

{% endtab %}
{% endtabs %}

### Update user account

<mark style="color:orange;">`PUT`</mark>&#x20;

`https://integration.trueplay.io/api/v1/user`

The method to update user's "Kyc" parameter to get promo reward.

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

#### Request Body

<table><thead><tr><th width="283">Name</th><th width="212">Type</th><th>Description</th></tr></thead><tbody><tr><td>kyc</td><td>String</td><td>Indicates whether the user has passed the KYC verification process. When <strong>true</strong>, the user has successfully completed the KYC process; when <strong>false</strong>, the user has not yet completed KYC.</td></tr><tr><td>operatorUserId<mark style="color:red;">*</mark></td><td>String</td><td>ID of user on Operator side</td></tr></tbody></table>

{% tabs %}
{% tab title="200: OK Request is successful" %}

```json
{
"kyc": true,
"operatorUserId": "22334455"
}
```

{% endtab %}
{% endtabs %}

### Send user deposit&#x20;

<mark style="color:green;">`POST`</mark>&#x20;

`https://integration.trueplay.io/api/v1/promo/deposit`

This API method is used to process and register a user’s deposit within the casino platform. It ensures that the deposit is acknowledged within the Trueplay system and applies any promotional rewards associated with the deposit.

#### Request Body

| Name                                             | Type    | Description                                                                                                         |
| ------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------- |
| transactionId<mark style="color:red;">\*</mark>  | String  | A unique transaction identifier used for tracking the operation.                                                    |
| operatorUserId<mark style="color:red;">\*</mark> | String  | The user’s identifier in the operator’s system.                                                                     |
| amount<mark style="color:red;">\*</mark>         | Integer | The deposit amount in the currency specified in the currency parameter.                                             |
| currency<mark style="color:red;">\*</mark>       | String  | Currency code following the [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) standard (e.g., EUR, USD). |
| amountUsd<mark style="color:red;">\*</mark>      | Integer | The equivalent deposit amount in US dollars (USD), based on the current exchange rate.                              |
| createdAt<mark style="color:red;">\*</mark>      | String  | The transaction creation date and time in ISO 8601 format (YYYY-MM-DDTHH:MM:SS.SSS).                                |

{% tabs %}
{% tab title="Request example" %}

```
Request
curl --location 'https://integration.trueplay.io/api/v1/promo/deposit' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: your-api-key-here' \
--data '{
    "transactionId": "230821765",
    "operatorUserId": "331438",
    "amount": "28.00",
    "currency": "EUR",
    "amountUsd": 29.008000000000003,
    "createdAt": "2025-02-12T21:36:47.000"
}'
```

{% endtab %}

{% tab title="Response example" %}
200: OK Request is successful
{% endtab %}
{% endtabs %}

The operator can also define a user segment to add to the campaign using API.  The Marketing Campaigns API supports the following methods

### Get all Active marketing campaigns

<mark style="color:blue;">`GET`</mark>&#x20;

`https://integration.trueplay.io/api/v1/promo-campaign/active`

The method returns a list of active marketing campaigns. This must be performed before adding a user to the campaign, so as to avoid adding a user to a campaign with the Draft/Expired/Deactivated status by accident.

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-Api-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

{% tabs %}
{% tab title="200: OK Request is successful" %}

```json
 {
      "accrualCondition": "string",
      "allUsers": true,
      "betVolumeRule": 0,
      "cashbackTime": 0,
      "conditionMax": 0,
      "conditionMin": 0,
      "createdAt": "2023-09-22T15:50:22.909",
      "dailyCashbackReward": 0,
      "dailyCashbackRewardAmount": 0,
      "dayOfWeek": "string",
      "duration": 0,
      "expirationDate": "2023-09-22",
      "fixedAmountReward": 0,
      "id": 0,
      "kycRule": true,
      "maxUserCount": 0,
      "name": "string",
      "p2eMultiplierReward": 0,
      "participants": 0,
      "percentAmountReward": 0,
      "registeredAfter": "2023-09-22",
      "signUpRule": true,
      "stakingLimitCoefficientReward": 0,
      "status": "string",
      "sumFixedAmountReward": 0,
      "weeklyCashbackReward": 0,
      "weeklyCashbackTime": 0
    }
    
    
```

{% endtab %}
{% endtabs %}

### Get marketing campaign participants by campaign ID

<mark style="color:blue;">`GET`</mark>&#x20;

`https://integration.trueplay.io/api/v1/promo-campaign/{campaign_id}/participants`

Returns a list of marketing campaign participants

#### Path Parameters

| Name                                 | Type    | Description              |
| ------------------------------------ | ------- | ------------------------ |
| id<mark style="color:red;">\*</mark> | Integer | ID of marketing campaign |

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

{% tabs %}
{% tab title="200: OK Request is succesful" %}

```json
{ 
  "content": [ 
    { 
      "campingId": 10, 
      "createdAt": "2023-04-20T09:15:40.545", 
      "method": "API", 
      "operatorUserId": "23423", 
    },
  ]
    { 
      "campingId": 15, 
      "createdAt": "2023-04-20T09:15:40.545", 
      "method": "Manual", 
      "operatorUserId": "97500", 
    },            
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid request parameters provided" %}

{% endtab %}

{% tab title="401: Unauthorized Requester is unauthorized to perform an action" %}

{% endtab %}

{% tab title="403: Forbidden Requester is forbidden to perform an action" %}

{% endtab %}

{% tab title="404: Not Found Resource not found" %}

{% endtab %}
{% endtabs %}

### Assign user to the marketing campaign

<mark style="color:green;">`POST`</mark>&#x20;

`https://integration.trueplay.io/api/v1/promo-campaign/{campaignId}/user/{operatorUserId}`

The method add a user to the marketing campaign

#### Path Parameters

| Name                                             | Type    | Description                 |
| ------------------------------------------------ | ------- | --------------------------- |
| operatorUserId<mark style="color:red;">\*</mark> | Integer | ID of user on Operator side |
| campaignId<mark style="color:red;">\*</mark>     | Integer | ID of marketing campaign    |

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-Api-Key<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

{% tabs %}
{% tab title="201: Created Request is succesful" %}

```json
{
  "campingId": 0,
  "createdAt": "2023-09-22T16:11:42.371",
  "method": "string",
  "operatorUserId": "string",
  "transaction": "string"
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid request parameters provided" %}

{% endtab %}

{% tab title="401 Requester is unauthorized to perform an action" %}

{% endtab %}

{% tab title="403: Forbidden Requester is forbidden to perform an action" %}

{% endtab %}

{% tab title="404: Not Found Resource not found" %}

{% endtab %}
{% endtabs %}

### Delete user from marketing campaign

<mark style="color:red;">`DELETE`</mark>&#x20;

`https://integration.trueplay.io/api/v1/promo-campaign/{campaignId}/user/{operatorUserId}`

The method delete users from marketing campaign

#### Path Parameters

| Name                                             | Type    | Description                 |
| ------------------------------------------------ | ------- | --------------------------- |
| campaignId<mark style="color:red;">\*</mark>     | Integer | ID of marketing campaign    |
| operatorUserId<mark style="color:red;">\*</mark> | Integer | ID of user on Operator side |

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

{% tabs %}
{% tab title="200: OK Request is succesful" %}

{% endtab %}
{% endtabs %}

## Users Rewards

### Get the total amount of rewards for all users

<mark style="color:blue;">`GET`</mark>&#x20;

`https://integration.trueplay.io/api/v1/operator/rewards`

The method returns a list of all types of rewards by all users.  It is possible to set a time interval for receiving a list of rewards

#### Query Parameters

| Name                                        | Type   | Description |
| ------------------------------------------- | ------ | ----------- |
| startDate<mark style="color:red;">\*</mark> | String |             |
| endDate<mark style="color:red;">\*</mark>   | String |             |

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

#### Response

{% tabs %}
{% tab title="200: OK Request is succesfull" %}

```json
 {
  "playToEarn": 0,
  "holdToEarn": 0,
  "promo": 0,
  "dailyCashback": 0,
  "weeklyCashback": 0,
  "referralPlayToEarn": 0,
  "referralHoldToEarn": 0,
  "playToEarnRollback": 0,
  "burn": 0
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid request parameters provided" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="401: Unauthorized Requester is unauthorized to perform an action" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="403: Forbidden Requester is forbidden to perform an action" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="404: Not Found Resource not found" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}

### Get the amount of rewards separately for each user

<mark style="color:blue;">`GET`</mark>&#x20;

`https://integration.trueplay.io/api/v1/users/rewards`

The method returns a list of users and their awards for a certain period of time. \
Maximum time period - 24 hours. \
The request must indicate the from (date and time) - to (date and time).   \
\
For example, a request for a period 2024-03-24 13:00:00.000 - 2024-03-24 14:00:00.000 will return a list of users and their rewards for the specified period.

#### Query Parameters

| Name                                   | Type   | Example                 |
| -------------------------------------- | ------ | ----------------------- |
| from<mark style="color:red;">\*</mark> | String | 2024-04-01 00:00:00.000 |
| to<mark style="color:red;">\*</mark>   | String | 2024-04-02 00:00:00.000 |

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

#### Response

{% tabs %}
{% tab title="200: OK Request is succesfull" %}

```json
[
  {
    "playToEarnRollback": null,
    "casinoReward": null,
    "promo": null,
    "dailyCashback": null,
    "weeklyCashback": null,
    "burn": null,
    "playToEarn": 10.35,
    "holdToEarn": null,
    "operatorUserId": "0026337c1-9d39-43a7-a734-d60dd94z1bf2"
  },
  {
    "playToEarnRollback": null,
    "casinoReward": null,
    "promo": null,
    "dailyCashback": null,
    "weeklyCashback": null,
    "burn": null,
    "playToEarn": null,
    "holdToEarn": 0.7060225419336147,
    "operatorUserId": "0vb6376b5-6ddc-4156-8bba-b81df693d8dc"
  }
 ] 
```

{% endtab %}

{% tab title="400: Bad Request Invalid request parameters provided" %}
`{`&#x20;

`}`
{% endtab %}

{% tab title="401: Unauthorized Requester is unauthorized to perform an action" %}

{% endtab %}

{% tab title="403: Forbidden Requester is forbidden to perform an actiontitled" %}

{% endtab %}

{% tab title="404: Not Found Resource not found" %}

{% endtab %}
{% endtabs %}

### Get a reward by a user

<mark style="color:blue;">`GET`</mark> `https://integration.trueplay.io/api/v1/user/${operatorUserId}/rewards`

The method returns a list of all types of rewards by a specific user.  It is possible to set a time interval for receiving a list of rewards

#### Path Parameters

| Name                                             | Type   | Description                 |
| ------------------------------------------------ | ------ | --------------------------- |
| operatorUserId<mark style="color:red;">\*</mark> | String | ID of user on Operator side |

#### Query Parameters

| Name      | Type   | Description |
| --------- | ------ | ----------- |
| startDate | String |             |
| endDate   | String |             |

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

#### Response

{% tabs %}
{% tab title="200: OK Request is succesful" %}

```json
 {
  "playToEarn": 0,
  "holdToEarn": 0,
  "promo": 0,
  "dailyCashback": 0,
  "weeklyCashback": 0,
  "referralPlayToEarn": 0,
  "referralHoldToEarn": 0,
  "playToEarnRollback": 0,
  "burn": 0
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid request parameters provided" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="401: Unauthorized Requester is unauthorized to perform an action" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="403: Forbidden Requester is forbidden to perform an action" %}

```javascript
{
    // Response
}
```

{% endtab %}

{% tab title="404: Not Found Resource not found" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}

### Check user balance

<mark style="color:blue;">`GET`</mark> `https://integration.trueplay.io/api/v1/user/{operatorUserId}/check-balance`

The method returns 2 values by selected user :&#x20;

* The total amount of tokens on the user's wallet ;
* The total amount of tokens in Hold To Earn programs .

The rate limit is 60 requests per minute.

#### Path Parameters

| Name                                             | Type   | Description                 |
| ------------------------------------------------ | ------ | --------------------------- |
| operatorUserId<mark style="color:red;">\*</mark> | String | ID of user on Operator side |

#### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

#### Response

{% tabs %}
{% tab title="200: OK Request is succesful" %}

```
{ 
"balance": 100.5, 
"balanceH2e": 20000.5 
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid request parameters provided" %}

```
{
    // Response
}
```

{% endtab %}
{% endtabs %}

### Accrual of rewards for activity in the casino

<mark style="color:green;">`POST`</mark>&#x20;

`https://integration.trueplay.io/api/v1/casino/reward`

This method is used when a user on the casino side reaches a specific level that triggers a token reward.\
The operator can award tokens to users once they complete the following actions:

* When the user reaches a certain level of play ;
* For tournament participation ;
* When the user opens loot boxes ;
* Other triggers.

**Headers**

<table><thead><tr><th width="234">Name</th><th width="224">Type</th><th>Description</th></tr></thead><tbody><tr><td>X-API-KEY<mark style="color:red;">*</mark></td><td>String</td><td>Operator key issued by TruePlay to access TruePlay API</td></tr></tbody></table>

**Body**

<table><thead><tr><th width="230">Name</th><th width="245">Type</th><th>Description</th></tr></thead><tbody><tr><td>operatorUserId</td><td>string</td><td>ID of user on Operator side<br></td></tr><tr><td>amount</td><td>Integer</td><td>The number of tokens that must be credited to the user's loyalty page balance</td></tr><tr><td>requestId</td><td>string</td><td></td></tr></tbody></table>

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
  "operatorUserId": "john12345",
  "amount": 3.56,
  "requestId": "string"
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

### Swap loyalty balance to the bonus balance in the casino

<mark style="color:green;">`POST`</mark>&#x20;

`https://integration.trueplay.io/api/v1/casino/loyalty-swap`

This method is used when the operator allow the user to withdraw tokens from the loyalty page and receive a bonus balance, freespins or freebets. The operator should add a pop-up, button, etc where the user see the ratio of the number of tokens to the number of freespins (freebets)

**Headers**

<table><thead><tr><th width="234">Name</th><th width="224">Type</th><th>Description</th></tr></thead><tbody><tr><td>X-API-KEY<mark style="color:red;">*</mark></td><td>String</td><td>Operator key issued by TruePlay to access TruePlay API</td></tr></tbody></table>

**Body**

<table><thead><tr><th width="230">Name</th><th width="232">Type</th><th>Description</th></tr></thead><tbody><tr><td>operatorUserId</td><td>string</td><td>ID of user on Operator side<br></td></tr><tr><td>amount</td><td>Integer</td><td>The number of tokens that must be withdrawn from user's loyalty page balance</td></tr><tr><td>requestId</td><td>string</td><td></td></tr></tbody></table>

**Response**

{% tabs %}
{% tab title="200: OK Request is successful" %}

{% endtab %}

{% tab title="400" %}

{% endtab %}
{% endtabs %}


# Integration for the Game Aggregator

## Trueplay endpoint <a href="#trueplay-endpoints" id="trueplay-endpoints"></a>

### Send game transactions

<mark style="color:green;">`POST`</mark> `https://{operator-name}.proxy.trueplay.io/api/v1/accept`

The method to send game traffic from operator to Trueplay.

### Headers

| Name                                        | Type   | Description                                            |
| ------------------------------------------- | ------ | ------------------------------------------------------ |
| X-API-KEY<mark style="color:red;">\*</mark> | String | Operator key issued by TruePlay to access TruePlay API |

### Request Body

<table><thead><tr><th width="205">Name</th><th width="93">Type</th><th>Description</th><th>Example</th></tr></thead><tbody><tr><td>operatorUserId<mark style="color:red;">*</mark></td><td>String</td><td>Id of user on Operator side</td><td>"121242"</td></tr><tr><td>transactionId<mark style="color:red;">*</mark></td><td>String</td><td>Id of user transaction</td><td>"fa732e77-db74-44b8-b6723-be9d37a13b40"</td></tr><tr><td>referenceTransactionId<mark style="color:red;">*</mark></td><td>String</td><td>Id of game transactions (BET | WIN) .  <br>This is required to be sent for such types of game transactions as ( REFUND | ROLLBACK )</td><td>null</td></tr><tr><td>type<mark style="color:red;">*</mark></td><td>String</td><td>Type of game transaction (BET | WIN | ROLLBACK | BONUS_BET | BONUS_WIN)</td><td>"BET"</td></tr><tr><td>gameProvider<mark style="color:red;">*</mark></td><td>String</td><td>-</td><td>"PRAGMATIC"</td></tr><tr><td>gameCode<mark style="color:red;">*</mark></td><td>String</td><td>-</td><td>"165"</td></tr><tr><td>gameName<mark style="color:red;">*</mark></td><td>String</td><td>-</td><td>"Pharaohs Gold 20"</td></tr><tr><td>gameType<mark style="color:red;">*</mark></td><td>String</td><td>-</td><td>"Slot"</td></tr><tr><td>currency<mark style="color:red;">*</mark></td><td>String</td><td>currency of game transaction</td><td>"USD"</td></tr><tr><td>amount<mark style="color:red;">*</mark></td><td>Integer</td><td>amount of game transaction</td><td>2</td></tr></tbody></table>

## Game Aggregator endpoint <a href="#trueplay-endpoints" id="trueplay-endpoints"></a>

### Send Copy Stake transactions&#x20;

<mark style="color:green;">`POST`</mark> `https://{operatorbaseurl}/player-event`

The method to send game transactions in functionality "Copy Stake" from Trueplay side to Game Aggregator

### Headers

| Name                                                  | Type   | Description                                                                                                               |
| ----------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------- |
| X-REQUEST-SIGNATURE<mark style="color:red;">\*</mark> | String | <p>Request signature, Base64(HmacSHA512(SecretKey, MD5(request body)))<br>Event "data" is individual for each request</p> |

### Request Body

<table><thead><tr><th width="172">Name</th><th width="124">Type</th><th width="183">Description</th><th>Example</th></tr></thead><tbody><tr><td>operatorUserId<mark style="color:red;">*</mark></td><td>String</td><td>Id of user on Operator side</td><td>"john12345"</td></tr><tr><td>requestId<mark style="color:red;">*</mark></td><td>String</td><td>Id of request</td><td>"uuid"</td></tr><tr><td>createdAt<mark style="color:red;">*</mark></td><td>String</td><td>Date of game transactions</td><td>"2022-08-18 06:42:45"</td></tr><tr><td>type<mark style="color:red;">*</mark></td><td>String</td><td>Type of Event (COPY_BET | COPY_WIN | COPY_ROLLBACK )</td><td>COPY_BET</td></tr><tr><td>data<mark style="color:red;">*</mark></td><td>String</td><td>-</td><td>{<br>"eventParam":"eventValue"<br>}</td></tr></tbody></table>

### Type of "Copy Stake" events

<table data-full-width="true"><thead><tr><th width="299">Event type</th><th>Event data</th></tr></thead><tbody><tr><td>COPY_BET</td><td><p>{ </p><p>"type": "COPY_BET", </p><p>"data": {<br>  "gameProvider": Pragmatic,<br>  "gameCode": 123,<br>  "gameName":  Banana,<br>  "gameType": Slot,<br>  "currency": Usd,<br>  "amount": 10 <br>  } <br>}</p></td></tr><tr><td>COPY_WIN</td><td><p>{ </p><p>"type": "COPY_WIN", </p><p>"data": {<br>  "gameProvider": Pragmatic,<br>  "gameCode": 123,<br>  "gameName":  Banana,<br>  "gameType": Slot,<br>  "currency": Usd,<br>  "amount": 10 <br>  } <br>}</p></td></tr><tr><td>COPY_ROLLBACK</td><td><p>{ </p><p>"type": "COPY_ROLLBACK", </p><p>"data": {<br>  "gameProvider": Pragmatic,<br>  "gameCode": 123,<br>  "gameName":  Banana,<br>  "gameType": Slot,<br>  "currency": Usd,<br>  "amount": 10 <br>  } <br>}</p></td></tr></tbody></table>


# Copystake Integration

## **CopyStake overview**

CopyStake consists of two parts:

* **Lobby**. The page of active streamers (with video streams) and regular users actively playing allowed games.
* **Broadcast**. The page of the selected streamer, where the live stream is displayed (or, if it's a regular user, an animation will be shown), and where users can watch the stream, monitor the streamer's bets, and start copying them.

CopyStake admin configuration:

* **Operator settings**. To integrate CopyStake, the operator needs to implement the API contract (provided below) and specify the following information on the Admin CopyStake page:
  * **X-API-KEY**. CopyStake will make requests to the operator with this value in the request’s header.
  * **Session TTL**. It’s needed to synchronize the session duration between the operator and CopyStake.
  * **Callback URL**. It’s required for sending requests from CopyStake.
* **CopyStake settings**. A section necessary for configuring games to be added to the whitelist, creating streamers, scheduling video streams, and more.

API Access:

* All requests from Copystake to the operator contain X-API-KEY with a value issued by the operator.
* All requests from the operator to Copystake contain X-API-KEY with a value issued by Copystake.

Signature:

* All requests from Copystake must be signed by Copystake and verified by the operator.
* All requests from the operator must be signed by the operator and verified by CopyStake.
* The SecretKey for signing the payload in both cases is issued by CopyStake.
* The signature will be placed in the X-REQUEST-SIGNATURE header of each request and uses Base64(HmacSHA512(SecretKey, MD5(request body))).
* Dealing with X-REQUEST-SIGNATURE.

<details>

<summary>Example of how to generate a signature for SecretKey = <code>secret</code></summary>

node \
\
Welcome to Node.js v16.13.0. Type ".help" for more information.\
\
var crypto = require('crypto'); \
undefined \
\
var hasher = crypto.createHash('md5'); \
undefined \
\
var hashed = hasher.update('{"id":"103193","action":"CREDIT","amount":4.123,"currency":"USD","exchangeRate":0.00203250655485,"tokenAmount":2500,"operatorId":123,"operatorUserId":"333"}') \
undefined\
\
var hash = hashed.digest('hex'); \
undefined \
\
var hmac = crypto.createHmac('sha512', 'secret'); \
undefined \
\
hmac.update(hash); \
Hmac { \_options: undefined, \[Symbol(kHandle)]: Hmac {}, \[Symbol(kState)]: { \[Symbol(kFinalized)]: false } } \
\
var sign = hmac.digest('base64'); \
undefined \
\
console.log('signature: ' + sign); \
signature: IifPVbfXptagZ6qSXH9vYrQiqSP4sKIC+hV+39z2K+FlLzRoEboPGTTymjmeuAhN1i0ICDyyrrufYspgAJmxHQ==

</details>

Callback URL:

* `callback_url` - provided by the operator, e.g. `callback_url=https://integration.operator.com/api/v1/copystake`

**IMPORTANT:**&#x20;

Operators need to whitelist the Trueplay IPs to receive transaction status callbacks. Otherwise, Trueplay will return errors for deposit/withdrawal tokens requests.

<details>

<summary><strong>IPs for whitelisting</strong></summary>

18.193.249.95

18.184.86.250

18.196.113.251

</details>

## **Original and Copied transactions**

<figure><img src="/files/5Hv1v8duBG155gj25hNX" alt=""><figcaption></figcaption></figure>

## Get CopyStake page&#x20;

This API method allows operators to obtain a link to the CopyStake page, which can be embedded as an iframe into the operator's website.

*If a user accesses CopyStake, the system loads the lobby as the default entry point. However, when generating a Stream URL, it allows to bypass the CopyStake Lobby and be redirected directly to a broadcast page when a stream is active.*

<mark style="color:green;">`POST`</mark>

`https://integration.trueplay.io/api/v1/copystake/init`

**Headers**

{% code overflow="wrap" %}

```
Content-Type: application/json
X-API-KEY: value issued by CopyStake
X-REQUEST-SIGNATURE: value generated based on the request payload (secret key issued by CopyStake)
```

{% endcode %}

**Request**

<table data-header-hidden><thead><tr><th width="168"></th><th width="92"></th><th width="129"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>userId</td><td>String</td><td>mandatory</td><td>User identifier in the operator system</td></tr><tr><td>sessionId</td><td>String</td><td>optional</td><td>Unique session identifier in the operator system. If not provided, it will be generated by CopyStake</td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>User's active currency (ISO 4217)</td></tr><tr><td>balance</td><td>Double</td><td>mandatory</td><td>User's current balance in the operator system, rounded to 8 decimal places</td></tr><tr><td>language</td><td>String</td><td>optional</td><td>User's UI language code from the permitted set in the backoffice (ISO 639)</td></tr><tr><td>streamId</td><td>String</td><td>optional</td><td>If this parameter is included in the request, Trueplay system will recognize it and automatically direct the user to the Broadcast page instead of the Lobby.</td></tr></tbody></table>

**Response success**

<table data-header-hidden><thead><tr><th width="158"></th><th width="118"></th><th width="158"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>url</td><td>String</td><td>mandatory</td><td>CopyStake URL with an authentication token</td></tr><tr><td>sessionId</td><td>String</td><td>mandatory</td><td>Unique session identifier in the operator system. If not provided, it will be generated by CopyStake</td></tr></tbody></table>

**Response error**

HTTP 400 Bad Request

<table data-header-hidden><thead><tr><th width="150"></th><th width="86"></th><th width="118"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>errorCode</td><td>String</td><td>mandatory</td><td><p>ERR_UNKNOWN<br>General error status, for cases without a special error code.</p><p>ERR_COPYSTAKE_OFF<br>CopyStake is disabled</p></td></tr><tr><td>errorMessage</td><td>String</td><td>optional</td><td>more detailed description of the error</td></tr></tbody></table>

<details>

<summary><strong>Request example</strong></summary>

{% code overflow="wrap" %}

```
Request
curl --location 'https://integration.trueplay.io/api/v1/copystake/init' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: d922bd1c-e7ac-4c98-9b1a-baa724440b0e' \
--header 'X-REQUEST-SIGNATURE: XhNkfy6WCTdiewUu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x+77DvqCGRw==' \
--data '{
    "userId": "1",
    "sessionId": "10XFTW12",
    "currency": "USDT",
    "balance": 820.00000000,
    "language": "en",
    "streamId": "7b699688-f4ad-407d-baf5-c006ba8d50e2"
}'
```

{% endcode %}

</details>

**Response example**

{% tabs %}
{% tab title="200: OK Request is succesful" %}
{% code overflow="wrap" %}

```
200 OK
{
    "url": "https://copystake.trueplay.io?token=eyJhbGciOiJIUzUxMiJ9.eyJpZF9vcGVyYXRvciI6”,
    "sessionId": "10XFTW12"
}
```

{% endcode %}
{% endtab %}

{% tab title="400: Bad Request " %}

```
400 Bad Request
{
    "errorCode": "ERR_COPYSTAKE_OFF",
    "errorMessage": "CopyStake is disabled"
}
```

{% endtab %}
{% endtabs %}

### **Get CopyStake page DEMO** <a href="#get-copystake-page-demo" id="get-copystake-page-demo"></a>

This API method allows operators to obtain a link to the CopyStake page, which can be opened in demo mode within an iframe on the operator’s website.

<mark style="color:green;">`POST`</mark>

`https://integration.trueplay.io/api/v1/copystake/init-demo`

**Headers**

{% code overflow="wrap" %}

```
Content-Type: application/json
X-API-KEY: value issued by CopyStake
```

{% endcode %}

**Request**

<table data-header-hidden><thead><tr><th width="168"></th><th width="92"></th><th width="129"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>language</td><td>String</td><td>optional</td><td>User's UI language code from the permitted set in the backoffice (ISO 639)</td></tr><tr><td>streamId</td><td>String</td><td>optional</td><td>User identifier for active stream. If present, followers are directed to the Broadcast page, skipping the Lobby</td></tr></tbody></table>

Response success

<table data-header-hidden><thead><tr><th width="183"></th><th width="132"></th><th width="141"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>url</td><td>String</td><td>mandatory</td><td>CopyStake url with auth token</td></tr></tbody></table>

Response error HTTP&#x20;

400 Bad Request

<table data-header-hidden><thead><tr><th width="156"></th><th width="126"></th><th width="161"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>errorCode</td><td>String</td><td>mandatory</td><td><p>ERR_UNKNOWN<br>General error status, for cases without a special error code.</p><p>ERR_COPYSTAKE_OFF<br>CopyStake is disabled</p></td></tr><tr><td>errorMessage</td><td>String</td><td>optional</td><td>more detailed description of the error</td></tr></tbody></table>

<details>

<summary><strong>Request example</strong></summary>

{% code overflow="wrap" %}

```
Request
curl --location 'https://integration.trueplay.io/api/v1/copystake/init-demo' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: d922bd1c-e7ac-4c98-9b1a-baa724440b0e' \
--header 'X-REQUEST-SIGNATURE: XhNkfy6WCTdiewUu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x+77DvqCGRw==' \
--data '{
    "language": "en",
    "streamId": "7b699688-f4ad-407d-baf5-c006ba8d50e2"
}'
```

{% endcode %}

</details>

**Response example**

{% tabs %}
{% tab title="200: OK Request is succesful" %}
{% code overflow="wrap" %}

```
200 OK
{
    "url": "https://copystake.trueplay.io?token=eyJhbGciOiJIUzUxMiJ9.eyJpZF9vcGVyYXRvciI6”
}
```

{% endcode %}
{% endtab %}

{% tab title="400: Bad Request " %}

```
400 Bad Request
{
    "errorCode": "ERR_COPYSTAKE_OFF",
    "errorMessage": "CopyStake is disabled"
}
```

{% endtab %}
{% endtabs %}

## Send game transaction

This method allows operators to send transaction data to Trueplay. Operators must provide the relevant details of each transaction.

<mark style="color:green;">`POST`</mark>&#x20;

`https://{operator-name}.proxy.trueplay.io/api/v1/accept`

**Headers**

```
Content-Type: application/json
X-API-KEY: value issued by CopyStake
```

<table data-header-hidden><thead><tr><th width="217"></th><th width="102"></th><th width="115"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>userId</td><td>String</td><td>mandatory</td><td>User identifier in the operator system</td></tr><tr><td>transactionId</td><td>String</td><td>mandatory</td><td>A unique identifier for each transaction type (BET, WIN, ROLLBACK). For every new action (BET, WIN, ROLLBACK) a distinct transactionId is generated to track that specific action.</td></tr><tr><td>referenceTransactionId</td><td>String</td><td>optional</td><td><p>Used to link related transactions.</p><p>• For BET transactions, this will be null as they are the starting point of the sequence.</p><p>• For WIN transactions, this field should reference the transactionId of the corresponding BET.</p><p>• For ROLLBACK transactions, this field should reference the transactionId of the original BET being rolled back. This also applies to rolling back WIN transactions; the referenceTransactionId should point to the transactionId of the WIN being rolled back.</p></td></tr><tr><td>type</td><td>String</td><td>mandatory</td><td>Type of game transaction (BET | WIN | ROLLBACK)</td></tr><tr><td>gameProvider</td><td>String</td><td>mandatory</td><td>Indicates the provider of the game or platform associated with the transaction </td></tr><tr><td>gamePublisher</td><td>String</td><td>mandatory</td><td>Specifies the game’s publisher</td></tr><tr><td>gameCode</td><td>String</td><td>mandatory</td><td>Unique game code</td></tr><tr><td>gameName</td><td>String</td><td>mandatory</td><td>An identifier for the specific game associated with the transaction</td></tr><tr><td>gameType</td><td>String</td><td>mandatory</td><td>The type of game</td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>User's active currency (ISO 4217)</td></tr><tr><td>amount</td><td>Double</td><td>mandatory</td><td><ul><li>Fiat: Although fiat currencies typically allow up to two decimal places (e.g., USD: 10.25)</li><li>Cryptocurrency: The amount parameter adheres to a maximum of 8 decimal places</li></ul></td></tr></tbody></table>

<details>

<summary><strong>Request example</strong></summary>

{% code overflow="wrap" %}

```
Request
curl --location 'https://integration.trueplay.io/api/v1/copystake/init' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: d922bd1c-e7ac-4c98-9b1a-baa724440b0e' \
--header 'X-REQUEST-SIGNATURE: XhNkfy6WCTdiewUu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x+77DvqCGRw==' \
--data '{
    "userId": "1",
    "transactionId": "111",
    "type": "WIN",
    "gameProvider": "NOLIMIT_CITY"
    "gameProvider": "EVOLUTION",
    "gameCode": "Mental",
    "gameName": "Mental",
    "gameType": "Slots",
    "currency": "USDT",
    "amount": 25.00000000,
}
```

{% endcode %}

</details>

{% tabs %}
{% tab title="200: OK Request is successful" %}
{% code overflow="wrap" %}

```
200 OK
```

{% endcode %}
{% endtab %}

{% tab title="400: Bad Request " %}
{% code overflow="wrap" %}

```
400 Bad Request
{
    "errorCode": "ERR_COPYSTAKE_OFF",
    "errorMessage": "CopyStake is disabled"
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## **Get user balance**

This method retrieves the current available balance of a user during the opening of the broadcast page and before starting the copy round.

<mark style="color:green;">`POST`</mark>&#x20;

```
{callback_url}/user-balance
```

**Headers**

{% code overflow="wrap" %}

```
Content-Type: application/json
X-API-KEY: value issued by Operator
X-REQUEST-SIGNATURE: value generated based on the request payload (secret key issued by CopyStake)
```

{% endcode %}

**Request**

<table data-header-hidden><thead><tr><th width="154"></th><th width="110"></th><th width="144"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>sessionId</td><td>String</td><td>mandatory</td><td>unique session identifier</td></tr></tbody></table>

**Response**

<table data-header-hidden><thead><tr><th width="135"></th><th width="112"></th><th width="143"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>balance</td><td>Double</td><td>mandatory</td><td><ul><li>rounding to 8 decimal places</li><li>current available user's balance</li></ul></td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>user's active currency ISO 4217</td></tr></tbody></table>

<details>

<summary><strong>Request example</strong></summary>

{% code overflow="wrap" %}

```
curl --location '{callback_url}/user-balance' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: e58d1990-31b9-41f5-aa39-fd150643a8fe' \
--header 'X-REQUEST-SIGNATURE: FbS2341Uu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x234FD==' \
--data '{
    "sessionId": "10XFTW12"

```

{% endcode %}

</details>

{% tabs %}
{% tab title="Response example" %}

```
200 OK
{
    "balance": 830.00000000,
    "currency": "USDT",
}
```

{% endtab %}
{% endtabs %}

## **Send copied transactions (BET/WIN/ROLLBACK)**

### **Send BET copied transaction**

This API method sends a BET copied transaction to the operator immediately after receiving the transaction from the streamer during an active game round.

<mark style="color:green;">`POST`</mark>&#x20;

```
{callback_url}/bet
```

**Headers**

{% code overflow="wrap" %}

```
Content-Type: application/json
X-API-KEY: value issued by Operator
X-REQUEST-SIGNATURE: value generated based on the request payload (secret key issued by CopyStake)
```

{% endcode %}

**Request**

<table data-header-hidden><thead><tr><th width="222"></th><th width="98"></th><th width="119"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>sessionId</td><td>String</td><td>mandatory</td><td>Unique session identifier</td></tr><tr><td>roundId</td><td>String</td><td>mandatory</td><td>Unique round identifier representing one copy cycle (some number of game actions)</td></tr><tr><td>transactionId</td><td>String</td><td>mandatory</td><td>Unique CopyStake transaction identifier</td></tr><tr><td>transactionIdOriginal</td><td>String</td><td>mandatory</td><td>Original transaction identifier (the streamer's transaction)</td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>User's active currency (ISO 4217)</td></tr><tr><td>amount</td><td>Double</td><td>mandatory</td><td><p></p><ul><li>Fiat: Although fiat currencies typically allow up to two decimal places (e.g., USD: 10.25)</li><li>Cryptocurrency: The amount parameter adheres to a maximum of 8 decimal places</li></ul></td></tr></tbody></table>

**Response**

<table data-header-hidden><thead><tr><th width="157"></th><th width="100"></th><th width="122"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>balance</td><td>Double</td><td>mandatory</td><td>Current available user's balance, rounded to 8 decimal places</td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>User's active currency (ISO 4217)</td></tr></tbody></table>

**Response error**\
HTTP 400 Bad Request

<table data-header-hidden><thead><tr><th width="158"></th><th width="88"></th><th width="117"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>errorCode</td><td>String</td><td>mandatory</td><td>ERR_UNKNOWN<br>General error status, for cases without a special error code.</td></tr><tr><td>errorMessage</td><td>String</td><td>optional</td><td>More detailed description of the error</td></tr></tbody></table>

<details>

<summary><strong>Request example</strong></summary>

{% code overflow="wrap" %}

```
curl --location'https://{operator_base_url}/integration/copystake/bet'\
--header 'Content-Type: application/json' \
--header 'X-API-KEY: e58d1990-31b9-41f5-aa39-fd150643a8fe' \
--header 'X-REQUEST-SIGNATURE: FbS2341Uu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x234FD==' \
--data '{
    "sessionId": "10XFTW12",
    "roundId": "1",
    "transactionId": "1",
    "transactionIdOriginal": "111",
    "currency": "USDT",
    "amount": 25.00000000
}'
```

{% endcode %}

</details>

**Response example**

{% tabs %}
{% tab title="200: OK Request is successful" %}

```
200 OK
{
    "balance": 795.00000000,
    "currency": "USDT",
}
```

{% endtab %}

{% tab title="400: Bad Request " %}

```
400 Bad Request
{
    "errorCode": "ERR_COPYSTAKE_OFF",
    "errorMessage": "CopyStake is disabled"
}
```

{% endtab %}
{% endtabs %}

### **Send WIN copied transaction**

This API method sends a WIN copied transaction to the operator immediately after receiving the transaction from the streamer during an active game round.

<mark style="color:green;">`POST`</mark>&#x20;

```
{callback_url}/win
```

**Headers**

{% code overflow="wrap" %}

```
Content-Type: application/json
X-API-KEY: value issued by Operator
X-REQUEST-SIGNATURE: value generated based on the request payload (secret key issued by CopyStake)
```

{% endcode %}

**Request**

<table data-header-hidden><thead><tr><th width="229"></th><th width="100"></th><th width="120"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>sessionId</td><td>String</td><td>mandatory</td><td>Unique session identifier</td></tr><tr><td>roundId</td><td>String</td><td>mandatory</td><td>Unique round identifier representing one copy cycle (some number of game actions)</td></tr><tr><td>transactionId</td><td>String</td><td>mandatory</td><td>Unique CopyStake transaction identifier</td></tr><tr><td>transactionIdOriginal</td><td>String</td><td>mandatory</td><td>Original transaction identifier (the streamer's transaction)</td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>User's active currency (ISO 4217)</td></tr><tr><td>amount</td><td>Double</td><td>mandatory</td><td><p></p><ul><li>Fiat: Although fiat currencies typically allow up to two decimal places (e.g., USD: 10.25)</li><li>Cryptocurrency: The amount parameter adheres to a maximum of 8 decimal places</li></ul></td></tr></tbody></table>

**Response**

<table data-header-hidden><thead><tr><th width="143"></th><th width="112"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>balance</td><td>Double</td><td>mandatory</td><td>Current available user's balance, rounded to 8 decimal places</td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>User's active currency (ISO 4217)</td></tr></tbody></table>

<details>

<summary><strong>Request example</strong></summary>

{% code overflow="wrap" %}

```
curl --location https://{operator_base_url}/integration/copystake/win \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: e58d1990-31b9-41f5-aa39-fd150643a8fe' \
--header 'X-REQUEST-SIGNATURE: FbS2341Uu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x234FD==' \
--data '{
    "sessionId": "10XFTW12",
    "roundId": "1",
    "transactionId": "1",
    "transactionIdOriginal": "111",
    "currency": "USDT",
    "amount": 25.00000000
}'
```

{% endcode %}

</details>

**Response example**

{% tabs %}
{% tab title="200: OK Request is successful" %}

```
200 OK
{
    "balance": 805.00000000,
    "currency": "USDT",
}
```

{% endtab %}

{% tab title="400: Bad Request " %}

```
400 Bad Request
{
    "errorCode": "ERR_COPYSTAKE_OFF",
    "errorMessage": "CopyStake is disabled"
}
```

{% endtab %}
{% endtabs %}

### **Send ROLLBACK BET copied transaction**

This API method sends a ROLLBACK BET copied transaction to the operator immediately after receiving the transaction from the streamer during an active game round.

<mark style="color:green;">`POST`</mark>&#x20;

```
{callback_url}/rollback-bet
```

**Headers**

{% code overflow="wrap" %}

```
Content-Type: application/json
X-API-KEY: value issued by Operator
X-REQUEST-SIGNATURE: value generated based on the request payload (secret key issued by CopyStake)
```

{% endcode %}

**Request**

<table data-header-hidden><thead><tr><th width="295"></th><th width="86"></th><th width="120"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>sessionId</td><td>String</td><td>mandatory</td><td>Unique session identifier</td></tr><tr><td>roundId</td><td>String</td><td>mandatory</td><td>Unique round identifier representing one copy cycle (some number of game actions)</td></tr><tr><td>transactionId</td><td>String</td><td>mandatory</td><td>Unique CopyStake transaction identifier</td></tr><tr><td>referenceTransactionId</td><td>String</td><td>mandatory</td><td>Reference to BET CopyStake transaction identifier</td></tr><tr><td>transactionIdOriginal</td><td>String</td><td>mandatory</td><td>Original transaction identifier (the streamer's transaction)</td></tr><tr><td>referenceTransactionIdOriginal</td><td>String</td><td>mandatory</td><td>Reference to original BET transaction identifier</td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>User's active currency (ISO 4217)</td></tr><tr><td>amount</td><td>Double</td><td>mandatory</td><td><p></p><ul><li>Fiat: Although fiat currencies typically allow up to two decimal places (e.g., USD: 10.25)</li><li>Cryptocurrency: The amount parameter adheres to a maximum of 8 decimal places</li></ul></td></tr></tbody></table>

**Response**

<table data-header-hidden><thead><tr><th width="137"></th><th width="133"></th><th width="143"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>balance</td><td>Double</td><td>mandatory</td><td>Current available user's balance, rounded to 8 decimal places</td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>User's active currency (ISO 4217)</td></tr></tbody></table>

<details>

<summary><strong>Request example</strong></summary>

{% code overflow="wrap" %}

```
curl --location 'https://{operator_base_url}/integration/copystake/rollback-bet' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: e58d1990-31b9-41f5-aa39-fd150643a8fe' \
--header 'X-REQUEST-SIGNATURE: FAE3S2341Uu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x23d23d==' \
--data '{
    "sessionId": "10XFTW12",                   
    "roundId": "1",                            
    "transactionId": "3",                      
    "referenceTransactionId": "1",              
    "transactionIdOriginal": "333",             
    "referenceTransactionIdOriginal": "111",
    "currency": "USDT",                        
    "amount": 25.00000000                        
}'
```

{% endcode %}

</details>

**Response example**

{% tabs %}
{% tab title="200: OK Request is successful" %}

```
200 OK
{
    "balance": 830.00000000,
    "currency": "USDT"
}
```

{% endtab %}

{% tab title="400: Bad Request " %}

```
400 Bad Request
{
    "errorCode": "ERR_COPYSTAKE_OFF",
    "errorMessage": "CopyStake is disabled"
}
```

{% endtab %}
{% endtabs %}

### **Send ROLLBACK WIN copied transaction**

This API method sends a ROLLBACK WIN copied transaction to the operator immediately after receiving the transaction from the streamer during an active game round.

<mark style="color:green;">`POST`</mark>&#x20;

```
{callback_url}/rollback-win
```

**Headers**

{% code overflow="wrap" %}

```
Content-Type: application/json
X-API-KEY: value issued by Operator
X-REQUEST-SIGNATURE: value generated based on the request payload (secret key issued by CopyStake)
```

{% endcode %}

**Request**

<table data-header-hidden><thead><tr><th width="276"></th><th width="92"></th><th width="117"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>sessionId</td><td>String</td><td>mandatory</td><td>Unique session identifier</td></tr><tr><td>roundId</td><td>String</td><td>mandatory</td><td>Unique round identifier representing one copy cycle (some number of game actions)</td></tr><tr><td>transactionId</td><td>String</td><td>mandatory</td><td>Unique CopyStake transaction identifier</td></tr><tr><td>referenceTransactionId</td><td>String</td><td>mandatory</td><td>Reference to WIN CopyStake transaction identifier</td></tr><tr><td>transactionIdOriginal</td><td>String</td><td>mandatory</td><td>Original transaction identifier (the streamer's transaction)</td></tr><tr><td>referenceTransactionIdOriginal</td><td>String</td><td>mandatory</td><td>Reference to original BET transaction identifier</td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>User's active currency (ISO 4217)</td></tr><tr><td>amount</td><td>Double</td><td>mandatory</td><td><p></p><ul><li>Fiat: Although fiat currencies typically allow up to two decimal places (e.g., USD: 10.25)</li><li>Cryptocurrency: The amount parameter adheres to a maximum of 8 decimal places</li></ul></td></tr></tbody></table>

**Response**

<table data-header-hidden><thead><tr><th width="137"></th><th width="133"></th><th width="143"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>balance</td><td>Double</td><td>mandatory</td><td>Current available user's balance, rounded to 8 decimal places</td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>User's active currency (ISO 4217)</td></tr></tbody></table>

<details>

<summary><strong>Request example</strong></summary>

<pre data-overflow="wrap"><code><strong>curl --location 'https://{operator_base_url}/integration/copystake/rollback-win' \
</strong>--header 'Content-Type: application/json' \
--header 'X-API-KEY: e58d1990-31b9-41f5-aa39-fd150643a8fe' \
--header 'X-REQUEST-SIGNATURE: FAE3S2341Uu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x23d23d==' \
--data '{
    "sessionId": "10XFTW12",                   
    "roundId": "1",                            
    "transactionId": "4",                      
    "referenceTransactionId": "2",              
    "transactionIdOriginal": "444",             
    "referenceTransactionIdOriginal": "222",
    "currency": "USDT",                        
    "amount": 10.00000000                        
}'
</code></pre>

</details>

**Response example**

{% tabs %}
{% tab title="200: OK Request is successful" %}

```
200 OK
{
    "balance": 830.00,
    "currency": "USDT"
}
```

{% endtab %}

{% tab title="400: Bad Request " %}

```
400 Bad Request
{
    "errorCode": "ERR_COPYSTAKE_OFF",
    "errorMessage": "CopyStake is disabled"
}
```

{% endtab %}
{% endtabs %}

## Update User account type

This API method allows you to update the user account type to either TEST or REGULAR. It is commonly used to mark a user as a test user.

<mark style="color:red;">`PUT`</mark>&#x20;

```
https://integration.trueplay.io/api/v1/copystake/user
```

**Headers**

{% code overflow="wrap" %}

```
Content-Type: application/json
X-API-KEY: value issued by CopyStake
```

{% endcode %}

**Request**

| **Field** | **Type** | **Require** | **Description**  |
| --------- | -------- | ----------- | ---------------- |
| userId    | String   | mandatory   | operator user id |
| userType  | String   | mandatory   | TEST REGULAR     |

**Response success**

```
204 OK
```

<details>

<summary><strong>Request example</strong></summary>

{% code overflow="wrap" %}

```
curl -X 'PUT' \
  'https://integration.trueplay.io/api/v1/copystake/user' \
  -H 'accept: */*' \
  -H 'X-API-KEY: d922bd1c-e7ac-4c98-9b1a-baa724440b0e' \
  -H 'Content-Type: application/json' \
  -d '{
  "userId": "local_user",
  "userType": "TEST"
}'
```

{% endcode %}

</details>

**Response example**

{% tabs %}
{% tab title="204: OK Request is successful" %}

```
204 OK
```

{% endtab %}

{% tab title="404: Not Found " %}

```
404 Not Found
{
    "message": "User [operatorUserId] not found"
}
```

{% endtab %}
{% endtabs %}

## Copystake Reward URL

The reward endpoint allows CopyStake to notify the operator’s bonus engine about a reward granted to a user as part of gamified features like Jackpot, Wheel of Fortune, or Sign-up Reward.

<mark style="color:green;">`POST`</mark>&#x20;

```
https://{callback_url}/reward
```

**Headers**

{% code overflow="wrap" %}

```
Content-Type: application/json
X-API-KEY: value issued by Operator
X-REQUEST-SIGNATURE: value generated based on the request payload (secret key issued by CopyStake)
```

{% endcode %}

<table data-header-hidden><thead><tr><th width="135.86328125"></th><th width="100.93359375"></th><th width="146.078125"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>userId</td><td>String</td><td>mandatory</td><td>user identifier in the operator system</td></tr><tr><td>transactionId</td><td>String</td><td>mandatory</td><td>unique CopyStake transaction identifier</td></tr><tr><td>rewardType</td><td>String</td><td>mandatory</td><td>COPYSTAKE_REWARD<br>the reward type sent by CopyStake</td></tr><tr><td>eventType</td><td>String</td><td>mandatory</td><td>JACKPOT, WHEEL_OF_FORTUNE, SIGN_UP_REWARD<br>the event type sent by CopyStake</td></tr><tr><td>bonusType</td><td>String</td><td>mandatory</td><td>CASINO, SPORT<br>the bonus type sent by CopyStake to identify Operator’s bonus engine</td></tr><tr><td>wager</td><td>Integer</td><td>mandatory</td><td><p>0: the charge is made to the main user’s account</p><p>1 and greater: coefficient used to calculate the amount a user must wager to transfer winnings from the bonus user’s account to the main user’s account (e.g. wager=5 and amount=100, then after wagering the amount of 5*100, the user will receive a bonus of 100 to to the main user’s account)</p></td></tr><tr><td>bonusTtlDays</td><td>Integer</td><td>mandatory</td><td><p>0: in case the wager=0</p><p>1 and greater: number of days during which the user can wager the bonus</p></td></tr><tr><td>currency</td><td>String</td><td>mandatory</td><td>user's active currency ISO 4217</td></tr><tr><td>amount</td><td>Double</td><td>mandatory</td><td><ul><li>fiat: two decimal places (e.g., USD: 10.25)</li><li>cryptocurrency: the amount parameter adheres to a maximum of 8 decimal places</li></ul></td></tr></tbody></table>

<details>

<summary>Request example</summary>

```
curl --location '{callback_url}/reward' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: e58d1990-31b9-41f5-aa39-fd150643a8fe' \
--header 'X-REQUEST-SIGNATURE: FbS2341Uu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x234FD==' \
--data '{
    "userId": "29e946a1-e801-4e27-952d-1d6ebbd19525",
    "transactionId": "01944be7-a260-7209-b16f-0d2d953e8c9f",
    "rewardType": "COPYSTAKE_REWARD",
    "eventType": "WHEEL_OF_FORTUNE",
    "bonusType": "CASINO",
    "wager": 0,
    "currency": "USD",
    "amount": 5.00
}'
```

</details>

{% tabs %}
{% tab title="200: OK Request is successful" %}

{% endtab %}

{% tab title="400 Bad Request" %}

```
{
    "errorCode": "ERR_REWARD_FORBIDDEN",
    "errorMessage": "user fraud detected"
}
```

{% endtab %}
{% endtabs %}

## **Error handling and retry mechanism**

CopyStake is very sensitive to the stability and speed of the operator's response and cannot allow long delays in response or a classic retry mechanism with several attempts. In the case of prolonged latency, CopyStack will **interrupt the game round** but keep the session active. If an error differs from those below, there will be **one retry attempt**.

**Response**

<table data-header-hidden><thead><tr><th width="150"></th><th width="96"></th><th width="116"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>errorCode</td><td>String</td><td>mandatory</td><td><p>ERR_UNKNOWN<br>General error status, for cases without a special error code.</p><p>ERR_INSUFFICIENT_FUNDS<br>Not enough money on the user's balance to process a transaction</p><p>ERR_DUPLICATE_TRANSACTION<br>A transaction with the same identifier was sent</p><p>ERR_USER_DISABLED<br>User is disabled/locked (cannot interact with user's balance)</p><p>ERR_INVALID_SIGNATURE<br>Operator couldn't verify the signature on request from</p></td></tr><tr><td>errorMessage</td><td>String</td><td>optional</td><td>more detailed description of the error</td></tr></tbody></table>

**Response example**

{% tabs %}
{% tab title="400: Bad Request " %}

```
400 Bad Request
{
    "errorCode": "ERR_INSUFFICIENT_FUNDS",
    "errorMessage": "Insufficient balance"
}
```

{% endtab %}
{% endtabs %}


# Copy in Pool

### Overview

The **Copy In Pool** mode is an extension of the CopyStake product. In this mode, users copy the streamer's bets by contributing funds to a shared pool. The size of their win or loss is proportional to their share of the pool. All actions are processed via the streamer's balance on the operator's side.

This document defines the API contract required for operators to integrate the Copy In Pool functionality.

API Access:

* all requests from CopyStake to Operator contain `X-API-KEY` with value issued by Operator;
* all requests from Operator to CopyStake contain `X-API-KEY` with value issued by CopyStake;

Signature:

* all requests from CopyStake must be signed by CopyStake and verified by Operator;
* all requests from Operator must be signed by Operator and verified by CopyStake;
* **secretKey** for signing the payload in both cases is issued by CopyStake
* the signature will be placed in the `X-REQUEST-SIGNATURE` header of each request and uses **Base64(HmacSHA512(SecretKey, MD5(request body)))**
* dealing with `X-REQUEST-SIGNATURE`&#x20;

<details>

<summary>Example of how to generate a signature for SecretKey = <code>secret</code></summary>

node \
\
Welcome to Node.js v16.13.0. Type ".help" for more information.\
\
var crypto = require('crypto'); \
undefined \
\
var hasher = crypto.createHash('md5'); \
undefined \
\
var hashed = hasher.update('{"id":"103193","action":"CREDIT","amount":4.123,"currency":"USD","exchangeRate":0.00203250655485,"tokenAmount":2500,"operatorId":123,"operatorUserId":"333"}') \
undefined\
\
var hash = hashed.digest('hex'); \
undefined \
\
var hmac = crypto.createHmac('sha512', 'secret'); \
undefined \
\
hmac.update(hash); \
Hmac { \_options: undefined, \[Symbol(kHandle)]: Hmac {}, \[Symbol(kState)]: { \[Symbol(kFinalized)]: false } } \
\
var sign = hmac.digest('base64'); \
undefined \
\
console.log('signature: ' + sign); \
signature: IifPVbfXptagZ6qSXH9vYrQiqSP4sKIC+hV+39z2K+FlLzRoEboPGTTymjmeuAhN1i0ICDyyrrufYspgAJmxHQ==

</details>

Callback URL:

* `callback_url` - provided by Operator, e.g. `callback_url=https://integration.operator.com/api/v1/copystake`

**IMPORTANT:**&#x20;

Operators need to whitelist the Trueplay IPs to receive callbacks about the status of transactions. Otherwise, Trueplay will return errors for deposit/withdrawal tokens requests.

<details>

<summary><strong>IPs for whitelisting</strong></summary>

18.193.249.95

18.184.86.250

18.196.113.251

</details>

**Validation rules**:

**Operator side**:

* to prevent fraud and loss of funds by the follower, Operator should ensure control over the withdrawal of funds from the streamer’s balance on the operator’s site to streamer’s personal account (out of operator’s site);

**CopyStake side**:

* to ensure the correct execution of operations, CopyStake should perform transfer operations only for users identified in the CopyStake system as streamers

### **Transfer operation** <a href="#transfer-operation" id="transfer-operation"></a>

OPERATOR

* **type = DEPOSIT** only under the condition of a successfully executed BET transaction on the follower’s account, i.e., the action when the follower joined the pool;
* **type = WITHDRAWAL** under the condition that the follower decided to leave the pool (or the stream ended, or other scenarios). This operation must be completed with a WIN transaction on the follower’s account.

Performing deposit/withdraw operations concerning the streamer’s balance. This method can be invoked:

\ <mark style="color:green;">`POST`</mark>

`{callback_url}/transfer`

**Headers**

{% code overflow="wrap" %}

```
Content-Type: application/json
X-API-KEY: value issued by Operator
X-REQUEST-SIGNATURE: value generated based on the request payload (secret key issued by CopyStake)
```

{% endcode %}

**Request**

<table data-header-hidden><thead><tr><th width="99.27734375"></th><th width="116.703125"></th><th width="141.4765625"></th><th width="292.74609375"></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>userId</td><td>String</td><td>mandatory</td><td>user identifier in the operator system</td></tr><tr><td>currency</td><td>String</td><td>optional</td><td><p>currency ISO 4217</p><ul><li>field is present, return the account balance information in the specified currency</li><li>field is absent, return the account balance information with which the game was launched (not a balance inside the game)</li><li><strong>field is absent and there is no active game session - throw</strong> ERR_OPEN_SESSION_NOT_FOUND</li></ul></td></tr></tbody></table>

**Response success**

| **Field** | **Type** | **Require** | **Description**                                                                         |
| --------- | -------- | ----------- | --------------------------------------------------------------------------------------- |
| balance   | Double   | mandatory   | <ul><li>rounding to 8 decimal places</li><li>current available user’s balance</li></ul> |
| currency  | String   | mandatory   | currency ISO 4217                                                                       |

**Response error**

HTTP 400 Bad Request

<table data-header-hidden><thead><tr><th width="150"></th><th width="86"></th><th width="118"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>errorCode</td><td>String</td><td>mandatory</td><td><p><code>ERR_UNKNOWN</code><br>General error status, for cases without a special error code</p><p><code>ERR_TRANSFER_FORBIDDEN</code><br>Any conditions under which the user is prohibited for deposit/withdraw operations</p><p><code>ERR_INSUFFICIENT_BALANCE</code><br>Insufficient streamer balance</p><p><code>ERR_INVALID_USER</code><br>User does not exist</p><p><code>ERR_OPEN_SESSION_NOT_FOUND</code><br>User session not found</p></td></tr><tr><td>errorMessage</td><td>String</td><td>optional</td><td>more detailed description of the errorRequest example</td></tr></tbody></table>

<details>

<summary><strong>Request example</strong></summary>

{% code overflow="wrap" %}

```
curl --location ’{callback_url}/streamer-balance’ \
--header ’Content-Type: application/json’ \
--header ’X-API-KEY: e58d1990-31b9-41f5-aa39-fd150643a8fe’ \
--header ’X-REQUEST-SIGNATURE: FbS2341Uu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x234FD==’ \
--data ’{
    "userId": "29e946a1-e801-4e27-952d-1d6ebbd19525"
}’
```

{% endcode %}

</details>

**Response example**

{% tabs %}
{% tab title="200: OK Request is succesful" %}
{% code overflow="wrap" %}

```
200 OK
{
    "balance": 805.00000000,
    "currency": "USD",
}
```

{% endcode %}
{% endtab %}

{% tab title="400: Bad Request " %}

```
400 Bad Request
{
    "errorCode": "ERR_BALANCE_FORBIDDEN",
    "errorMessage": "user's balance is prohibited to display"
}
```

{% endtab %}
{% endtabs %}

### **Get balance (Copy In Pool mode)** <a href="#get-balance-copy-in-pool-mode" id="get-balance-copy-in-pool-mode"></a>

This API method allows operators to retrieve the current balance of the streamer before join the pool.

<mark style="color:green;">`POST`</mark>

`{callback_url}/streamer-balance`

**Headers**

{% code overflow="wrap" %}

```
Content-Type: application/json
X-API-KEY: value issued by CopyStake
```

{% endcode %}

**Request**

<table data-header-hidden><thead><tr><th width="168"></th><th width="92"></th><th width="129"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>language</td><td>String</td><td>optional</td><td>User's UI language code from the permitted set in the backoffice (ISO 639)</td></tr><tr><td>streamId</td><td>String</td><td>optional</td><td>User identifier for active stream. If present, followers are directed to the Broadcast page, skipping the Lobby</td></tr></tbody></table>

Response success

<table data-header-hidden><thead><tr><th width="183"></th><th width="132"></th><th width="141"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>url</td><td>String</td><td>mandatory</td><td>CopyStake url with auth token</td></tr></tbody></table>

Response error HTTP&#x20;

400 Bad Request

<table data-header-hidden><thead><tr><th width="156"></th><th width="126"></th><th width="161"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>errorCode</td><td>String</td><td>mandatory</td><td><p>ERR_UNKNOWN<br>General error status, for cases without a special error code.</p><p>ERR_COPYSTAKE_OFF<br>CopyStake is disabled</p></td></tr><tr><td>errorMessage</td><td>String</td><td>optional</td><td>more detailed description of the error</td></tr></tbody></table>

<details>

<summary><strong>Request example</strong></summary>

{% code overflow="wrap" %}

```
Request
curl --location 'https://integration.trueplay.io/api/v1/copystake/init-demo' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: d922bd1c-e7ac-4c98-9b1a-baa724440b0e' \
--header 'X-REQUEST-SIGNATURE: XhNkfy6WCTdiewUu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x+77DvqCGRw==' \
--data '{
    "language": "en",
    "streamId": "7b699688-f4ad-407d-baf5-c006ba8d50e2"
}'
```

{% endcode %}

</details>

**Response example**

{% tabs %}
{% tab title="200: OK Request is succesful" %}
{% code overflow="wrap" %}

```
200 OK
{
    "url": "https://copystake.trueplay.io?token=eyJhbGciOiJIUzUxMiJ9.eyJpZF9vcGVyYXRvciI6”
}
```

{% endcode %}
{% endtab %}

{% tab title="400: Bad Request " %}

```
400 Bad Request
{
    "errorCode": "ERR_COPYSTAKE_OFF",
    "errorMessage": "CopyStake is disabled"
}
```

{% endtab %}
{% endtabs %}

### **Game Pool state**

Send information to the Operator that the streamer's balance is the Game Pool.&#x20;

It could be OPEN before the first follower decides to join the pool or CLOSED when the last follower leaves the pool. **Based on the information about state, Operator able to create internal rules to forbidden some operator actions (withdrawal of funds from the streamer’s balance on the operator’s site to streamer’s personal account, token exchanges and other that can impact on streamer’s balance)**

<mark style="color:green;">`POST`</mark>&#x20;

`{callback_url}/game-pool`

**Headers**

```
Content-Type: application/json
X-API-KEY: value issued by CopyStake

Request
```

<table data-header-hidden><thead><tr><th width="217"></th><th width="102"></th><th width="115"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Type</strong></td><td><strong>Require</strong></td><td><strong>Description</strong></td></tr><tr><td>userId</td><td>String</td><td>mandatory</td><td>User identifier in the operator system</td></tr><tr><td>state</td><td>String</td><td>mandatory</td><td><p>OPEN - first follower decides to join the pool</p><p>CLOSE - last follower leaves the pool</p></td></tr></tbody></table>

<details>

<summary><strong>Request example</strong></summary>

{% code overflow="wrap" %}

```
curl --location ’{callback_url}/game-pool’ \
--header ’Content-Type: application/json’ \
--header ’X-API-KEY: e58d1990-31b9-41f5-aa39-fd150643a8fe’ \
--header ’X-REQUEST-SIGNATURE: FbS2341Uu0mSUAGw4LwF7GVBa7GT7drJXCvHkI+ORHJQ07uxVKAi3pA/0vB8/shlzX16x234FD==’ \
--data ’{
    "userId": "29e946a1-e801-4e27-952d-1d6ebbd19525",
    "state": "OPEN"
}’
```

{% endcode %}

</details>

{% tabs %}
{% tab title="200: OK Request is successful" %}
{% code overflow="wrap" %}

```
200 OK
```

{% endcode %}
{% endtab %}

{% tab title="400: Bad Request " %}
{% code overflow="wrap" %}

```
400 Bad Request
{
    "errorCode": "ERR_INVALID_USER",
    "errorMessage": "user does not exist"
}
```

{% endcode %}
{% endtab %}
{% endtabs %}


# FNC Integration

### FNC overview

Our Funnels No Code loyalty widget is created to boost user engagement. Its integration is quick and requires little to no effort from an operator.&#x20;

It features Offline Missions and the Tap to Earn game for attracting and retaining customers. Trueplay handles the content and moderation, ensuring a seamless experience The result? Additional gamification leads to increased player activity.

### How to Add Widget?

Add this iframe in place where widget must be placed:

```
<iframe id="trueplay-widget" frameborder="0" allow="clipboard-write;web-share"></iframe>
```

Add a script just above the closing body tag and widget will load and launch automatically.

```
<script async     
src="https://cdn.trueplay.io/global/trueplay-widget.js?id={operatorId}&userId={userId}&autorun=true">
</script>
```

where `userId` – user identifier in the operator system. The operator needs to send this parameter to authenticate the user on the widget.

`operatorId` - id of operator on the Trueplay side. ID will be added automatically to the script which you should copy from the admin panel.

Or you can set query parameter:

```
autorun=false
```

and run widget programmatically after the script is loaded by running:

```
window.trueplay.init();
```

1. Unauthorised Users:
   * When a user is not authorised, an anonymous widget will be displayed.
   * User progress will be preserved using local storage.
2. User Authorisation:
   * Once the user is authorised, the operator should send the userId to the script to complete the integration.

These steps ensure a smooth experience for users, allowing them to continue where they left off even if they are not logged in.


# Onboarding

Make advertising materials to let people know about your loyalty program.

The main thing to keep in mind is that players who actively use **Trueplay generate an additional 5.6% of NGR**. A marketing campaign will support the launch by attracting new users and increasing the activity of existing ones.

Here is what you can do to make the most of Trueplay.

<br>


# Welcome Newsletter

Create an email campaign to notify your users about the loyalty page launch.

In the first email, inform your users about the reward opportunities available through Play to Earn and Hold to Earn — how to earn rewards, increase them, and deposit or withdraw loyalty tokens.

Give users a treat by mentioning that they already have something on their loyalty balance as a registration bonus, allowing them to try Hold to Earn with a short-term welcome token freeze.

<br>

<figure><img src="/files/fqq1Utmm9RRwRyhHU03p" alt=""><figcaption></figcaption></figure>

## Welcome newsletter template

Discover all the benefits of Loyalty Token! Welcome to the Loyalty Token widget!

Boosting your rewards has never been so easy!

Discover how to acquire our Loyalty Tokens and use them to multiply your rewards.

**How to get Loyalty Tokens on \[brand name]?**

Get your rakeback in Loyalty Tokens for each bet in games as part of the Play to Earn program. Regardless of game outcome, you will get a percentage of your bet back in Loyalty Tokens, allowing you to maximize your rewards with every play. Join \[brand name] now and start collecting Loyalty Tokens today!

**How to increase rewards?**

Play and multiply the acquired tokens with Hold to Earn. Freeze Loyalty Tokens for 8 hours, 1 day, or 3 days and get a fraction of the total platform profits. The average annual income of our holders is 535%! For instance, if you hold tokens equivalent to $100 daily, you can effortlessly get up to $535 after a year.

**What else can you do with Loyalty Tokens?**

You can convert tokens into the currency of your account and continue playing or withdraw tokens to your wallet. Moreover, our tokens are already being traded on decentralized exchanges, meaning you can trade them, too!<br>

<figure><img src="/files/189vi8uu0kyhoOSkd1RS" alt=""><figcaption></figcaption></figure>

<br>

<br>


# Social Media

Social media will help you build a community around your loyalty. It is a great strategy to reach a new audience and establish more value and trust. Giveaways and other engaging activities will make some noise around your loyalty programs.

**You may want to consider:**

* Twitter for short posts and memes
* Discord for tech discussions and chats
* Telegram for major updates and communication with users
* YouTube for educational videos and updates
* Medium or Blog for news updates and longreads


# Registration Bonuses

When users register, give them their first no-deposit bonus so they can try Trueplay and become more involved from the start. When users receive loyalty tokens for registration, they can freeze them in the Hold to Earn program and get more tokens this way. These tokens will incentivize users to return for more excitement and make their next bets.

In your email campaign, include information on how to earn more loyalty with Play to Earn and Hold to Earn, as well as what the player can do with their multiplied rewards.

<figure><img src="/files/vAK7iUnyANs8lng0TiLT" alt=""><figcaption><p>Email Campaign</p></figcaption></figure>

For better results, you can also mention the registration bonus in other promo campaigns or registration windows, main page promo banners, etc.


# Welcome Staking

Show your users how to multiply rewards with the Hold to Earn program.

<figure><img src="/files/Dnwx5C9KX588NaIwPxb6" alt=""><figcaption><p>Hold to Earn</p></figcaption></figure>

Tokens received as a Registration bonus can be utilized in the 30-second Welcome Staking program with a 2% yield. This will demonstrate the Welcome Staking features and encourage users to join other loyalty programs.

<figure><img src="/files/fFb2KLXPRtdXNwGhVaoA" alt=""><figcaption><p>Loyalty Page</p></figcaption></figure>

Inform users about Welcome Staking during promotional activities, for example, through website banners and the registration screen.

<br>


# Website Navigation

Professionally designed advertising on websites goes a long way toward attracting and retaining customers. The visual components increase customer awareness of the platform’s loyalty program.<br>

## Navigation Menu

Add your loyalty program to the navigation menu to make it easily accessible for customers. This will allow them to quickly find information about the program and track their rewards.

<figure><img src="/files/v1rR9Cn46yXyIQ5PSkDk" alt=""><figcaption><p>Navigation Menu</p></figcaption></figure>

## Promo Banner

Place a promo banner on your website’s main page and watch the Loyalty page visits increase.

<figure><img src="/files/WpnB7iZajtsJ1YzLQ6xR" alt=""><figcaption><p>Promo Banner</p></figcaption></figure>

## Scroll-triggered Popup

Add a pop-up window with information about Trueplay to make the number of Loyalty page visits grow. For example, a welcome pop-up (+ CTA button) can be shown every time users log in.

<figure><img src="/files/aF4s0kYiUJOEovTzzDpk" alt=""><figcaption><p>Popup</p></figcaption></figure>


# Event Types

Trueplay events are notifications that the operator receives when users make changes to their loyalty balance. For example, when the holding period expires, Trueplay notifies the operator and the user’s loyalty page.

To notify users about their rewards and other activities with notification emails, you need to set up automatic mailing customized for specific events.

### Event Types <a href="#event-types" id="event-types"></a>

* Play to Earn: A user receives a Play to Earn reward. This can be set as the initial reward event for a user. Send them an invitation to visit the Loyalty page to earn additional rewards.
* Hold to Earn: A user receives a Hold to Earn reward. Notify the user and encourage them to hold more tokens to increase their bonus.
* Balance change: The user’s balance has changed, excluding the Play to Earn and Hold to Earn events.

  Transaction types that included in the "Balance Change" event:

  * `CASINO_REWARD` - For rewards given by the casino.
  * `WITHDRAW / CRYPTO_WITHDRAW` - For withdrawals from the widget made by the user.
  * `DEPOSIT / CRYPTO_DEPOSIT` - For deposits made by the user.
  * `TRANSFER_IN / TRANSFER_OUT` - For transfers that increase or decrease the user’s balance.
  * `PROMO (PROMO_CAMPAIGN_REWARD / DAILY_CASHBACK / WEEKLY_CASHBACK,  PROMO_DEPOSIT_REWARD) -` For promotional rewards credited to the user’s balance.
  * `STAKE / UNSTAKE -`For the start and finish of a staking program (“hold to earn”).
  * `BURN` - For any balance deductions specified as burning points or tokens.

### Events data for developers <a href="#events-data-for-developers" id="events-data-for-developers"></a>

This functionality sends an event with the necessary data to the operator.

**Request body structure:**

<table data-full-width="true"><thead><tr><th width="322">METHOD</th><th>POST</th></tr></thead><tbody><tr><td>URL</td><td>https://{operatorbaseurl}/player-event</td></tr><tr><td>BODY</td><td><p><code>{</code></p><p> <code>"requestId":"uuid",</code></p><p> <code>"operatorUserId":"john12345",</code></p><p> <code>"createdAt":"2022-08-18 06:42:45",</code></p><p> <code>"type":"EVENT_TYPE",</code></p><p> <code>"data": {</code> </p><p>   <code>"eventParam":"eventValue"</code> </p><p>  <code>}</code> </p><p><code>}</code></p></td></tr><tr><td>HEADERS</td><td>X-REQUEST-SIGNATURE:SIccPXmsq6XdaCd9t82ghl1bny54yVnwpjXNo0t0vLkPgtkUIQtt+1OoXp8FQfak0JyjK6FhayLHrO6RPAIIDg== Content-Type: application/json</td></tr><tr><td>DETAILS</td><td>X-REQUEST-SIGNATURE - Request signature, Base64(HmacSHA512(SecretKey, MD5(request body))) Event "data" is individual for each request</td></tr></tbody></table>

**Supported Events:**

<table data-full-width="true"><thead><tr><th width="243">Event type</th><th width="172.59765625">Description</th><th>Event data</th></tr></thead><tbody><tr><td>PLAY_TO_EARN</td><td>Once a user receives a Play To Earn Reward</td><td><p><code>{</code> </p><p><code>"type": "PLAY_TO_EARN",</code> </p><p><code>"data": {</code></p><p>  <code>"amount": 10</code></p><p>  <code>"balance": 10,</code> <br>   <code>"tokenPriceUsdt": 0.005,</code> </p><p>  <code>"gameType": SLOT // Any game type sent by operator</code></p><p> <code>}</code></p><p><code>}</code><br>List of current game types:  VIDEO_POKER, LIVE_ROULETTE, ROULETTE, BINGO, BLACK_JACK, CASUAL_GAMES, HI_LO, INSTANT_WIN_GAMES, KENO, LIVE_BLACK_JACK, LIVE_DEALER, LIVE_DICE, LIVE_GAMES, LOTTERY, OTHER, POKER, SCRATCH_CARDS, SIC_BO, SPORTS_BOOK, TABLE_GAMES, VIDEO_BINGO, V_SPORT, WHEEL_OF_FORTUNE, BACCARAT, CARD, CRAPS, CRASH, LIVE_BACCARAT, LIVE_LOTTERY</p></td></tr><tr><td>HOLD_TO_EARN</td><td>When a user receives a Hold to Earn reward</td><td><p><code>{</code> </p><p><code>"type": "HOLD_TO_EARN",</code> </p><p><code>"data": {</code></p><p>  <code>"amount": 10, //h2e reward</code></p><p>  <code>"reward": 10, //h2e reward</code></p><p>  <code>"balance": 10,</code></p><p>  <code>"tokenPriceUsdt": 0.005</code> </p><p> <code>}</code> </p><p><code>}</code></p></td></tr><tr><td>BALANCE_CHANGE</td><td>Once the user balance has been changed. Except P2E and H2E events. </td><td><p><code>{</code> </p><p><code>"type": "BALANCE_CHANGE",</code></p><p> <code>"transactionType: "BURN"</code> </p><p><code>"data": {</code></p><p>  <code>"amount": 5 ,</code></p><p>  <code>"balance": 10 ,</code></p><p>  <code>"tokenPriceUsdt": 0.005</code> </p><p> <code>}</code> </p><p><code>}</code></p></td></tr><tr><td>CRYPTO_DEPOSIT_SUCCESS</td><td>When tokens are successfully deposited from user crypto wallet</td><td><p><code>{</code> </p><p><code>"type":"CRYPTO_DEPOSIT_SUCCESS",</code></p><p><code>"data": {</code> </p><p>  <code>"amount": 10.023</code> </p><p> <code>}</code> </p><p><code>}</code></p></td></tr><tr><td>CRYPTO_WITHDRAWAL_SUCCESS</td><td>When tokens are successfully withdrawn to user crypto wallet</td><td><p><code>{</code> </p><p><code>"type":"CRYPTO_WITHDRAWAL_SUCCESS",</code></p><p><code>"data": {</code> </p><p>  <code>"amount": 10.023</code> </p><p> <code>}</code> </p><p><code>}</code></p></td></tr><tr><td>PROMO_REWARD</td><td>When a user receives reward for registration/kyc or for a custom marketing campaigns.</td><td><p><code>{</code> </p><p><code>"type": "PROMO_REWARD",</code> </p><p><code>"data": {</code> </p><p>  <code>"amount": 10,</code> </p><p>  <code>"p2eMultiplier": 10.023,</code></p><p>  <code>"stakingLimitCoefficient": 10.2,</code></p><p>  <code>"balance": 10,</code></p><p>  <code>"tokenPriceUsdt": 0.005</code> </p><p> <code>}</code> </p><p><code>}</code></p></td></tr><tr><td>DAILY_CASHBACK</td><td>When a user receives token reward in the form of daily cashback</td><td><p><code>{</code> </p><p><code>"type": "DAILY_CASHBACK",</code> </p><p><code>"data": {</code> </p><p>  <code>"amount": 10, //daily_cashback</code></p><p>  <code>"balance": 10,</code></p><p>  <code>"tokenPriceUsdt": 0.005</code> </p><p> <code>}</code> </p><p><code>}</code></p></td></tr><tr><td>WEEKLY_CASHBACK</td><td>When a user receives token reward in the form of weekly cashback </td><td><p><code>{</code> </p><p><code>"type": "WEEKLY_CASHBACK",</code> </p><p><code>"data": {</code> </p><p>  <code>"amount": 10, //weekly_cashback</code></p><p>  <code>"balance": 10,</code> </p><p>  <code>"tokenPriceUsdt": 0.005</code> </p><p> <code>}</code> </p><p><code>}</code></p></td></tr><tr><td>DEPOSIT_VOLUME</td><td>When user receives reward with tokens for replenishing your deposit at the casino.</td><td><p><code>{</code> </p><p><code>"type": "DEPOSIT_VOLUME",</code> </p><p><code>"data": {</code> </p><p>  <code>"amount": 10, //deposit_volume</code></p><p>  <code>"balance": 10,</code></p><p>  <code>"tokenPriceUsdt": 0.005</code> </p><p> <code>}</code> </p><p><code>}</code></p></td></tr></tbody></table>

###


# CopyStake

CopyStake is a streaming tool for customer acquisition and engagement. It allows running gameplay sessions on an iGaming platform and simultaneously streaming them on popular platforms like Kick and Twitch to drive traffic and generate extra revenue. How? During these streams, users can automatically mirror streamers’ bets, sharing the wins and losses.&#x20;

### CopyStake modes

You can choose among three modes, selecting the option that best fits your user engagement and integration preferences: **Bet Behind**, **Copy in Pool**, and **No Code**.&#x20;

With **Bet Behind**, players automatically make the same bets as a steamer. To join the fun, they only need to set the size of their bets and click Play. The mode is compatible with slot games and allows hosting Wheel of Fortune and Jackpot draws.

<figure><img src="/files/0Zhrl8DBIfE8LkFykkWW" alt=""><figcaption></figcaption></figure>

<p align="center"><sub>Broadcast page in CopyStake Bet Behind</sub></p>

During **Copy in Pool** streams, players put funds into a shared pool managed by an online casino streamer who is playing live. Users get a portion of each win and participate in every bet based on their contribution share. Copy in Pool supports all game types and Wheel of Fortune and Jackpot draws.

<figure><img src="/files/ucJN4hnkgZeWbAZ30Wfa" alt=""><figcaption></figcaption></figure>

<p align="center"><sub>Broadcast page in CopyStake Copy in Pool</sub></p>

Both modes require backend integration.&#x20;

**No Code** allows hosting sessions where users сan join Wheel of Fortune giveaways and watch streamers play. One can integrate this mode quickly and easily, as the setup primarily involves the frontend.

The streaming tool has several gamification features: Wheel of Fortune, Jackpot, and a leaderboard. It also includes Become a Streamer, which lets you expand your streaming schedule and promote the platform through user-generated content (UGC) for free. Additionally, AI Streamers enables 24/7 player engagement.&#x20;

More detailed information about CopyStake and its features can be found in the dedicated [article](https://trueplay.io/blog/copystake-turn-livestreams-into-user-acquisition-engines).

#### First stream conversion

Expand the number of active users by inviting popular streamers to perform on your iGaming platform. A share of streamers’ fans would follow them to a casino website to watch gameplay and end up copying bets.&#x20;

In November 2024, the team tested CopyStake’s user acquisition capabilities on a client’s platform. They discovered that 13% of Twitch stream viewers visited a casino website and copied bets.

<figure><img src="/files/eeacZ19EW1Jm2KSqoYdy" alt=""><figcaption></figcaption></figure>


# AI Streamers

[AI Streamers](https://trueplay.io/ai-streamers) is the CopyStake feature that allows you to introduce iGaming streams and keep the lobby buzzing with minimal effort and investment. With it, you can create virtual hosts that run interactive streams on any schedule, even nonstop.

#### Streamer capabilities

The AI streamer can start a broadcast, open a game, understand in-game events, and react to them. It comments on the gameplay and interacts with the viewers, responding to their messages from the live chat. Besides showcasing a game, the AI streamer can encourage users to copy their bets in real time, increasing revenue opportunities.

You can choose and modify your streamers' personality traits, voice, appearance, and game skills.&#x20;

Find more information about AI Streamers in the [blog post](https://trueplay.io/blog/ai-streamers-making-24-7-user-engagement-reality), and feel free to [contact the team](https://trueplay.io/book-a-meeting) if you have any questions.


# Play to Earn

Learn how Play to Earn can boost your players’ loyalty.

### Win-win becomes a reality

A diverse selection of games, exciting tournaments, and nice bonuses draw many people to iGaming platforms. However, analysis of player behavior reveals that their main priority is always to win.

Betting and playing involve some risk, as winnings are not guaranteed. But offering rewards simply for playing provides customers with a sense of security.

Since winning fosters player loyalty, a platform’s success depends on its ability to leverage incentives for driving player engagement and satisfaction. This way, users are motivated to choose the casino for more than just a single game.

### What is Play to Earn

Over the past decade, iGaming platforms have offered a free-to-play model where users can play some games without paying. Today, with our loyalty gamification, you can change this rule.

Trueplay offers a play-to-earn model that benefits both players and the business.&#x20;

Play to Earn is a Loyalty Program feature that enables giving users loyalty rakeback for every bet. That way, you can motivate users and introduce internal loyalty tokens as a basic platform asset. In addition, the feature will help you grow a user base and increase loyalty to your business.

Metrics you can improve with Play to Earn:

* Website visit frequency
* Game session duration
* First-time deposit rate&#x20;
* Re-deposit rate
* Average revenue per user

Moreover, crediting in Play to Earn is automatic, and users can always be sure their balance will grow.

Setting up Play to Earn is easy and can be done in a few clicks. Mark the games and set the percentage of the bets users will receive in loyalty tokens. You can read more about setting up the feature in the admin panel.&#x20;

<figure><img src="/files/dLzpHgxsIqKvlUQfaIly" alt=""><figcaption><p>Play to Earn History on Loyalty page</p></figcaption></figure>


# Hold to Earn

Learn more about how to increase user retention by building a loyalty system on your platform.

While Play to Earn, described in the previous section, allows players to receive tokens for each bet, the Hold to Earn feature gives them the opportunity to increase their rewards. How? By freezing tokens for a specific period.

<figure><img src="/files/A5AQotOu8ZojifYhR41Q" alt=""><figcaption><p>Hold to Earn Program on the Loyalty page</p></figcaption></figure>

Each period differs in profitability: yearly profit and the share of casino income one can receive. The longer the holding period, the bigger the potential returns. To start, players need to choose a holding period and the number of tokens, then press Hold.&#x20;

The key advantage is that users risk nothing. Rewards are credited from a pool that is a set percentage of the platform’s GGR.

When your platform generates revenue during a holding period, Hold to Earn participants receive tokens as rewards. If there is no revenue during that time, players will receive back the same number of tokens they initially froze once the holding period ends.

Ongoing and past holds are displayed in the Hold to Earn History.

<figure><img src="/files/Esh9ydxGzFr6XjjAFMmQ" alt=""><figcaption><p>Hold to Earn History on the Loyalty page</p></figcaption></figure>

Players can withdraw rewards to the casino balance to play their favorite games.

You can customize all the parameters, choose the most suitable holding periods for you, and set the reward percentage for your users.


# Marketing Campaigns

On the Marketing Campaigns page, you can set up rewards for activities for certain user groups.

#### The Marketing Campaigns feature supports the following types of rewards:

* **Registration reward**: users receives a specified amount of tokens after registration.
* **KYC reward**: users receive a specific amount of tokens for completing Know\
  Your Customer (KYC) tasks.
* **Cashback reward**: users receive tokens as a percentage of the platform’s GGR.
* **Deposit reward**: users are rewarded after depositing a specific amount to their platform\
  account.
* **Token purchase**: users are allowed to purchase the desired amount of tokens.
* **Custom reward**.

#### The following restrictions may be applied to reward distribution:

* Campaign date
* Campaign duration
* The number of users that can participate
* A user segment that can be defined by an API&#x20;

## Marketing Campaigns life cycle

<figure><img src="/files/MuDb46yDsWHB9EiP7tor" alt=""><figcaption><p>Marketing Campaigns Life Cycle</p></figcaption></figure>

**Campaign status:**

* **Draft**: This status is assigned by default and indicates that the campaign’s\
  settings can be edited
* **Active**: Once activated, users can be added to the campaign to earn rewards
* **Deactivated**: The campaign is deactivated, and users can no longer be added
* **Expired**: The campaign has passed its deadline or the maximum number of users\
  has been reached

## Creating a campaign

To create a campaign, click on the Create Campaign (Fig. 2) button and configure campaign settings.

<figure><img src="/files/S1MlIn10AHySj5Jswx5r" alt=""><figcaption><p>Marketing Campaigns Page Interface</p></figcaption></figure>

To create a campaign, enter its name and configure the reward. The campaign will be added to the list and assigned a Draft status. When the campaign has an Active status, users will be added to the campaign (according to automatic rules or using an API).

<figure><img src="/files/2gc6kgQw6P8uWBEHfeVK" alt=""><figcaption><p>Marketing Campaigns Popup</p></figcaption></figure>

## Campaign management

You can filter campaigns by status and date.

On the Marketing Campaigns page, you can perform the following actions with the campaign (Fig. 4):

* Change its status
* Add users to the campaign
* Check the list of users added to the campaign
* View campaign configuration
* Edit the created campaign (if assigned the Draft, Deactivated, or Expired status)
* Delete the campaign (if assigned the Draft, Deactivated, or Expired status)

<figure><img src="/files/MFUtGTfUaj2MOnDmty10" alt=""><figcaption><p>Campaign Management Options</p></figcaption></figure>

## API

The Marketing Campaigns API supports the following methods:

* **Get all Active Marketing Campaigns.** Returning a list of active marketing campaigns. It must be run before adding a user to the campaign to avoid accidentally adding a user to a campaign with a Draft/Expired/Deactivated status.
* **Get Marketing Campaigns participants by ID.** Returning a list of Marketing Campaigns participants.
* **Assign User to Marketing Campaigns**. Adding a user to the campaign.
* **Delete User from Marketing Campaigns**. Deleting a user from the campaign.

### Get all Active Marketing Campaigns

| METHOD       | GET                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| URL          | <https://integration.trueplay.io/api/v1/promo-campaign/active>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| HEADER       | X-API-KEY (see value at Integration Settings)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| PARAMETERS   | -                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| RESPONSE     | <p>\[ </p><p>{ </p><p>  "betVolumeRule": 0,</p><p>  "createdAt": "2023-04-20T09:13:51.735Z", </p><p>  "dailyCashbackReward": 0, </p><p>  "duration": 0,</p><p>  "expirationDate": "2023-04-20", </p><p>  "fixedAmountReward": 500, </p><p>  "id": 0, </p><p>  "kycRule": true, </p><p>  "maxUserCount": 0, </p><p>  "name": "Campaing\_1", </p><p>  "p2eMultiplierReward": 1.5, </p><p>  "signUpRule": true, </p><p>  "stakingLimitCoefficientReward": 10000, </p><p>  "status": "Active" </p><p>},</p><p>{ </p><p>  "betVolumeRule": 0,</p><p>  "createdAt": "2023-04-20T09:13:51.735Z", </p><p>  "dailyCashbackReward": 0, </p><p>  "duration": 0,</p><p>  "expirationDate": "2023-04-20", </p><p>  "fixedAmountReward": 50, </p><p>  "id": 0, </p><p>  "kycRule": false, </p><p>  "maxUserCount": 0, </p><p>  "name": "string", </p><p>  "p2eMultiplierReward": 0, </p><p>  "signUpRule": true, </p><p>  "stakingLimitCoefficientReward": 15000, </p><p>  "status": "Active" </p><p>}</p><p>]</p> |
| STATUS CODES | <p>200 OK - The request is successful</p><p>400 Bad Request - Invalid request parameters provided</p><p>401 Unauthorized - Requester is unauthorized to perform an action</p><p>403 Forbidden - Requester is forbidden to perform an action</p><p>404 Not Found - Resource not found</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |

<br>

### Get Marketing Campaigns participants by campaign ID

| METHOD       | GET                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| URL          | <https://integration.trueplay.io/api/v1/promo-campaign/{campaign\\_id}/participants>                                                                                                                                                                                                                                                                                                                                |
| HEADER       | X-API-KEY (see value at Integration Settings)                                                                                                                                                                                                                                                                                                                                                                       |
| PARAMETERS   | - id - Operator ID                                                                                                                                                                                                                                                                                                                                                                                                  |
| RESPONSE     | <p>{ </p><p>  "content": \[ </p><p>    { </p><p>      "campingId": 10, </p><p>      "createdAt": "2023-04-20T09:15:40.545Z", </p><p>      "method": "API", </p><p>      "operatorUserId": "23423", </p><p>    },</p><p>    { </p><p>      "campingId": 15, </p><p>      "createdAt": "2023-04-20T09:15:40.545Z", </p><p>      "method": "Manual", </p><p>      "operatorUserId": "97500", </p><p>    },</p><p>]</p> |
| STATUS CODES | <p>200 OK - The request is successful</p><p>400 Bad Request - Invalid request parameters provided</p><p>401 Unauthorized - Requester is unauthorized to perform an action</p><p>403 Forbidden - Requester is forbidden to perform an action</p><p>404 Not Found - Resource not found</p>                                                                                                                            |

<br>

### Assign User to the Marketing Campaigns

| METHOD       | POST                                                                                                                                                                                                                                                                                     |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| URL          | <https://integration.trueplay.io/api/v1/promo-campaign/{campaignId}/user/{operatorUserId}>                                                                                                                                                                                               |
| HEADER       | X-API-KEY (see value at Integration Settings)                                                                                                                                                                                                                                            |
| PARAMETERS   | <p>- Campaign ID</p><p>- Operator user ID</p>                                                                                                                                                                                                                                            |
| RESPONSE     | <p>{ </p><p>  "campingId": 0, </p><p>  "createdAt": "2023-04-20T09:17:49.302Z", </p><p>  "method": "API", </p><p>  "operatorUserId": "65464", </p><p>  "transaction": "API" </p><p>}</p>                                                                                                 |
| STATUS CODES | <p>200 OK - The request is successful</p><p>400 Bad Request - Invalid request parameters provided</p><p>401 Unauthorized - Requester is unauthorized to perform an action</p><p>403 Forbidden - Requester is forbidden to perform an action</p><p>404 Not Found - Resource not found</p> |

<br>

### Delete User from the Marketing Campaigns

| METHOD       | DELETE                                                                                                                                                                                                                                                                                   |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| URL          | <https://integration.trueplay.io/api/v1/promo-campaign/{campaignId}/user/{operatorUserId}>                                                                                                                                                                                               |
| HEADER       | X-API-KEY (see value at Integration Settings)                                                                                                                                                                                                                                            |
| PARAMETERS   | <p>- Campaign ID</p><p>- Operator user ID</p>                                                                                                                                                                                                                                            |
| STATUS CODES | <p>200 OK - The request is successful</p><p>400 Bad Request - Invalid request parameters provided</p><p>401 Unauthorized - Requester is unauthorized to perform an action</p><p>403 Forbidden - Requester is forbidden to perform an action</p><p>404 Not Found - Resource not found</p> |

<br>


# Funnels No Code

[Funnels No Code](https://trueplay.io/funnels-no-code) is an acquisition tool that lets you create and launch funnels for marketing campaigns to bring in new players and retain existing ones. Its gamification mechanics — **Missions** and **Tap to Earn** — provide added value to prospects and customers by allowing them to participate in activities that yield rewards.&#x20;

<figure><img src="/files/gzVsyzLgqOq6VCKNwr0B" alt=""><figcaption></figcaption></figure>

Missions are point-earning tasks, such as posting a platform review, following a casino on Instagram, or referring a friend. You can use preset missions or create your own.

In the Tap to Earn game, users press on an image in the center of the screen to accumulate points. Zero learning curve and instant reward accrual make the game captivating right from the start. Moreover, a daily earning limit encourages customers to play the game seven days a week.

Accumulated points can be exchanged for gifts and bonuses in the Reward Shop.

Funnels No Code can be embedded on a website using an iFrame.&#x20;

Find more information about the tool in the [newsletter](https://www.linkedin.com/pulse/keep-player-interest-burning-trueplays-gamification-solutions-pkurf/?trackingId=B9ESWmE8Q8CeDoIxdSiqxA%3D%3D).


# Loyalty program // 12.02.2026

February 12, 2026

### Light & Dark modes for mobile and desktop

**Two themes, two moods:**  let players make the experience their own.

<div align="left"><figure><img src="/files/hIyWO5cHseFZewvRnczf" alt="" width="375"><figcaption></figcaption></figure></div>

### Home

#### Start screen

<div align="left"><figure><img src="/files/jrBm7I6EhNvvbSkbZEq3" alt=""><figcaption></figcaption></figure></div>

#### In progress

<figure><img src="/files/UL6NhLZPZegRLdoR0Rvy" alt=""><figcaption></figcaption></figure>

### Hold to Earn

#### Hold to Earn events:

1. Selected program
2. Hold duration
3. Percentage of return
4. Casino shared percentage
5. Limited/Unlimited program
6. Tokens amount input field
7. Hold button

<figure><img src="/files/C8jWwFKKyu2xOqAuZgiS" alt=""><figcaption></figcaption></figure>

1. Active holds
2. Hold deposit
3. Earned tokens
4. Holding timer
5. Hold duration
6. Total earnings

<div align="left"><figure><img src="/files/sGO72nyJlGmsvP3s0Bmj" alt="" width="563"><figcaption></figcaption></figure></div>

#### Hold to Earn history

What players see:

1. Total tokens earned
2. Date & hold ID
3. Hold duration
4. Gain percentage
5. Reward amount
6. Status & action history

<div align="left"><figure><img src="/files/eNTQiTyi95sfQe6zAKHd" alt="" width="563"><figcaption></figcaption></figure></div>

### Play to Earn

#### Play to Earn history

1. Total tokens earned
2. Game type
3. Bet amount
4. Reward received
5. Date & session details

<div align="left"><figure><img src="/files/pl8pmN7iLmDw3Mq1Oq5V" alt="" width="563"><figcaption></figcaption></figure></div>

#### Play to Earn history

<div align="left"><figure><img src="/files/QyDq3iUXp9qjQjWokd1O" alt="" width="563"><figcaption></figcaption></figure></div>

### Balance

#### Deposit

<div align="left"><figure><img src="/files/KwLzsbawdl5FccHMmEcA" alt="" width="563"><figcaption></figcaption></figure></div>

#### Deposit

<div align="left"><figure><img src="/files/LIgsxH1tt9XsFADVP3S5" alt="" width="563"><figcaption></figcaption></figure></div>

### Profile

### Info/ Profile page

Old: Account tab → Settings

New: User icon in the header

<div align="left"><figure><img src="/files/IA1mRObS0Qx4zybKngfn" alt="" width="563"><figcaption></figcaption></figure></div>

* Language & Security buttons added.
* User ID remains copyable.
* Notifications moved into a visible list (no separate window).

<div align="left"><figure><img src="/files/nCK7aVlKWnVNtYu6DxSV" alt="" width="563"><figcaption></figcaption></figure></div>

Language selection and display remain unchanged.

<div align="left"><figure><img src="/files/GGnXNup7TXuw8BAEY5sV" alt="" width="563"><figcaption></figcaption></figure></div>

No changes to 2FA functionality. Enable/disable options are located under the Security button.

<div align="left"><figure><img src="/files/uQwoZq4dSsPjcSUKdo1f" alt="" width="563"><figcaption></figcaption></figure></div>

Notification mechanics remain the same — message counter on the icon, unread indicators, and full delete options.

<div align="left"><figure><img src="/files/92547jH9jJZV2SmhKcZA" alt="" width="563"><figcaption></figcaption></figure></div>

### How it works

“How It Works” is now contextual — available directly inside the Hold to Earn block via the question mark icon.

<div align="left"><figure><img src="/files/dbX7Z8fYig7MgZrGDimm" alt="" width="563"><figcaption></figcaption></figure></div>

The “How It Works” logic remains the same — only its placement was updated.

<div align="left"><figure><img src="/files/rm8JSyxsa6DuWInkATan" alt="" width="563"><figcaption></figcaption></figure></div>

### Elements

#### Simplified in the new design

* Token info panel
* Casino income chart

<div align="left"><figure><img src="/files/e2kJb0cwcTZI9fhZtqCL" alt="" width="563"><figcaption></figcaption></figure></div>

#### New in this release

Structured accordion block with 4 elements

<div align="left"><figure><img src="/files/avno2ouubWSMOljEM4yG" alt="" width="563"><figcaption></figcaption></figure></div>

#### Play to Earn only

The Play to Earn-only widget does not include the “How It Works,” “Follow Us,” or token price display buttons. All other blocks in the new design remain consistent with the previous version.

<div align="left"><figure><img src="/files/xEYMRARBjqRuYMzC2BHP" alt="" width="563"><figcaption></figcaption></figure></div>


