Introduction
Welcome to ThrillTech's technology and integration documentation!
This document is structured as a searchable online book and aims to provide you, our partner, with all the technical information you need to build successful integrations, understand our platform and most importantly, have a readily available reference in the future.
To search from anywhere within the documentation, please s
and enter your search term in the search box
ThrillPots Overview
Welcome to the ThrillPots Integration Guide.
ThrillPots is an advanced standalone Jackpot Platform that allows casinos to offer their players jackpots over "everything". Be it offering a sitewide jackpot across games from various providers, to a seasonal Raffle jackpot for the 12 days of Christmas or even a Bad Beat jackpot for your poker players, ThrillPots can do it all (and more).
The goal of this guide is to make integrating with ThrillPots as painless as possible by providing you, the technical reader, with all the information you need and taking you step by step through a standard integration process.
Release Notes - October 2024
General
- Added new documentation for Contribution Sources
New Features
ThrillPots
-
Multi-strategy Community Payouts
- Up until now, community payouts were limited to a single payout strategy (Active Players, Highest Lifetime Contributor, or the new Highest Contribution Per Win). With this release, it is now possible to define multiple community payout strategies for a single community win.
For example, if you allocate 50% of the pot to be paid out to the community, you are now able to create sophisticated community payout strategies such as:
- Pay 20% to X random players that were active contributors to the jackpot in the last n hours
- Pay 20% to the top Y highest contributors to the pot
- Pay the remaining 10% to the top Z highest contributors of the jackpots lifetime
NOTE: Community payout strategies are defined as part of the jackpot mathematical model. If you would like to migrate your model to take advantage of multi-strategy community payouts in the future, please contact your Customer Success manager or technical point of contact to discuss further.
-
New Community Payout Strategy: Highest Contributor Per Win
- In previous versions, the Highest Contributor strategy would track and reward the highest contributors for all time against a jackpot instance.
- This new strategy provides the following capabilities:
- Contributions are tracked per player, per pot (jackpot tier)
- When this strategy is used to select community winners for a pot that has been won, the contribution values per pot are used for the selection.
- When a specific pot is won by a player, all players have their contribution counters for that pot reset
- This strategy provides a fair way to introduce new brands to a multi-brand community jackpot by eliminating any advantage players from longer-participating brands may have had.
-
Raffle Ticket Accumulation Mode
- As of this release, Raffle Tickets can be awarded based on accumulated contributions or base wager costs.
- What this means is that you can set the "price" of a raffle ticket to be X (eg €2.00), and as players contribute or wager, the system will accumulate the selected metric until the cost of the ticket has been reached, at which point a ticket will be awarded.
- For example:
- A ticket's cost is set to €2.00 of base wager
- A player is playing a slot game for €0.10 spins at a time.
- After 20 spins at €0.10 per spin, the player will be awarded a raffle ticket.
-
Winners Feeds from ThrillPots Gateway
-
Implemented functionality to retrieve latest winners per pot, as well as over all pots.
- jackpot_latest_winners_for_instance_pot
- Returns a HashMap where the keys are the pot identifiers, and the values are arrays containing the latest winners for the pot
- jackpot_latest_winners_for_instance
- Returns an array containing the latest winners over all pots
- jackpot_latest_winners_for_instance_pot
-
APIs are served from ThrillPots Gateway at the following routes:
GET /jackpots/instances/jackpot/:instance_id/pot_winners
GET /jackpots/instances/jackpot/:instance_id/latest_winners
-
Both APIs accept the following query parameters:
brand_id
(Optional) - filters the winners by brand_id. If not provided, winners across all brands will be returned.limit
(Optional, default: 10) - limits the number of winners returned. In the case of pot_winners_for_instance, limit is considered per pot
-
Changes/Improvements
ThrillPots
- Events sent from ThrillPots Gateway now carry a unique
event_id
identifier for each event.- This can be used to detect already-processed events in your downstream listeners (if you have more than one listener subscribed to events)
Bug Fixes
ThrillConnect
Service
connections to ThrillConnect did not receive events that they were subscribed for. This has now been fixed and anyService
based event subscribers listening to ThrillConnect events will once again start receiving events.
SaaS Integrations
Welcome to the SaaS integration guide for the ThrillPots Platform! Please read through the guide carefully as we have done our best to ensure that we explain each step of the integration as clearly as possible to ensure that you're efforts are as straighforward as possible.
How do SaaS integrations work?
When integration with the SaaS version of ThrillPots, you will be integrating your services with those of ThrillTech which are hosted in ThrillTech's hosting environment. There are 3 steps to the integration (as visualised in the diagram below):
1. Event Processor -> ThrillPots integration
This part of the integration connects enables your system to react to events occurring within your platform (such as bet events) and make jackpot contributions on behalf of players.
2. ThrillGate -> Wallet integration
This part of the integration enables the Thrillpots to communicate with your wallet system in order to be able to authenticate players and perform transactions for player jackpot bets and wins.
3. ThrillConnect -> Frontend integration
This part of the integration connects your player facing frontend(s) with the ThrillPots system and provides you with real time jackpot events and specific client-facing functionality (such as opting players in and out of jackpots)
We will discuss each of these steps in detail in the coming chapters.
ThrillPots Terminology
Before you start integrating, it would helpful to understand the terminology that is used in the context of ThrillPots.
Term | Definition |
---|---|
Source | A 'source' refers to any user interaction that can occur on your site. For example, a 'source' may be a game, a sports bet, a successful deposit and so forth. It is common to think of sources as games (and more specifically, their corresponding game codes) but there is no reason that the definition needs to be limited to games. |
Bearer Token | A Bearer token is a security token that is sent using the Authorization header of an HTTP request. Typically, a Bearer token looks as follows: Authorization: Bearer token_goes_here |
Jackpot Template | A 'jackpot template' contains the ruleset that is used to create one or more Jackpot Instances |
Jackpot Instance | A 'jackpot instance' refers to a live jackpot that can be in one of many Jackpot States |
Jackpot State | A jackpot instance can be in one of the following Jackpot States: Pending A pending jackpot is a scheduled jackpot that has not started to accept contributions or opt-ins from players Active An active jackpot is a jackpot that is accepting contributions and opt-ins, and can be won Paused A paused jackpot does not accept contributions but can be "unpaused" by setting its state back to Active Terminated A terminated jackpot is one that has ended due to either operator decision and manual intervention, or a scheduled jackpot that has reached the end of its lifetime. Terminated jackpots do not accept contributions or opt-ins and can not be re-activated. |
Contribution | A jackpot bet made on behalf of a player |
Owner ID | An owner_id specifies the organisation or organisational unit that created and owns the resource. The structure of an owner ID is: operator_id :brand_id , where the brand_id portion is optional. For example, it is valid to have an owner id only be the operator_id on its own, which means that the resource is owned by the organisation, and not a specific brand. |
Operator ID | An operator ID defines the identifier for a specific operator within the system. An operator can be considered an 'organisation' which has one or more brands |
Brand ID | A brand ID defines the identifier for a specific brand that an operator owns |
Event Processor Integration
In this section, we will discuss the Event Processor integration component that is required in order to enable the ability to make contributions to jackpots.
In general, this integration component needs to be able to receive the events that will drive jackpot contributions on behalf of users/players.
In a standard ThrillPots-powered system, it is usually gameplay that causes jackpot contributions to be made on behalf of players, but you are not limited to just this single use case.
From a simplistic perspective, the general logic should look something like this:
Authenticate your integration service with ThrillPots Gateway
Subscribe to gameplay/bet events from your event stream
When an event is received from your event stream:
- Read the properties of the event for game code, player ID and bet amount
- Make a contribution call to ThrillPots using these (and other values)
From here, it is relatively easy to see how you could expand the use case to create a Deposit jackpot. Lets imagine that the deposit flow was identified by source
DEPOSIT. Lets also assume that when a successful deposit has been made by a player, that an event is published by the operator's platform. For argument's sake, lets call this event DEPOSIT_SUCCESS
.
If we wanted to create a deposit jackpot, the logic could look as follows:
Subscribe to DEPOSIT_SUCCESS event
When an event is received:
- Read the properties of the event for the player ID and deposit amount
- Make a contribution call to ThrillPots using the DEPOSIT source_id and other properties
Sequence Diagram for the Event Processor integration
Authenticating via ThrillPots Gateway
The ThrillPots Gateway service exposes a REST endpoint which your event stream process can authenticate itself with Thrill-ID.
The endpoint is POST /authenticate/service
and accepts a payload which contains the connecting service's username
and password
.
If authentication is successful, you will receive a response which contains token
which must be used as a Bearer
token in subsequent API requests to the ThrillPots Gateway service. Service
tokens do not expire and therefore you do not need to be concerned with refreshing your token once it has been received.
NOTE: As part of your SaaS integration info pack, you will have received the details of the
Service
account that you must use for your Event Processor authentication.
Additional Information
If your event processor service is processing gameplay bet events, you should remember to filter out any and all events related to Jackpot Contributions as this could create loop of contributions on behalf of players
Contributing to Jackpots
Now that you are processing events from your platform, you want to be able to make Contributions on behalf of players to the jackpot. The process of contributing is quite straight forward and does not require your service to be aware of player opt-in status. You will however need to decide which jackpot to contribute to and this can be done in one of two ways:
- Contribute by source
- Contribute direct to jackpot
Sources
A Source
can be thought of as an operator-defined identifier for a user journey, a group of games, or even a single game. You can read more about Sources here,
Example: Sitewide Jackpot
If you wanted to create a site-wide jackpot for your casino vertical, you could create a Source
named casino-sitewide
, map a jackpot to the source and then send all contributions to that specific Source
.
{
"token": "token_00001",
"brand_id": "thrilltech:brand1",
"player_id": "player_00001",
"player_country": "UK",
"source_id": "casino-sitewide",
"gameround_id": "1",
"currency": "EUR",
"base_wager": 1
}
Example: Deposit Jackpot
If you wanted to create a deposit jackpot, you can create a source called deposit
, map the relevant jackpot to the source and then send all deposit-based contributions ot that source
{
"token": "token_00001",
"brand_id": "thrilltech:brand1",
"player_id": "player_00001",
"player_country": "UK",
"source_id": "deposit",
"gameround_id": "DEPOSIT_TX_ID",
"currency": "EUR",
"base_wager": 1
}
Example: Game Group Jackpot
If you wanted to create a jackpot for a specific set of games, for example, a jackpot for all egyptian themed games, you can create a source called egyptian-games
and use that for contributions each time a player bets into a game that is egyption themed. This would naturally require your integration service to know which games are matched to which Game Group
source.
{
"token": "token_00001",
"brand_id": "thrilltech:brand1",
"player_id": "player_00001",
"player_country": "UK",
"source_id": "egyptian-games",
"gameround_id": "1",
"currency": "EUR",
"base_wager": 1
}
Example: Game Specific Jackpots
If you want to split your liquidity by game title, you can create sources that correspond to the game codes of games in your system. Each source would need a jackpot mapped to it, but once that is done, you are able to make contributions to the source based on the game code of the base game bet.
{
"token": "token_00001",
"brand_id": "thrilltech:brand1",
"player_id": "player_00001",
"player_country": "UK",
"source_id": "provider-game-code",
"gameround_id": "1",
"currency": "EUR",
"base_wager": 1
}
Direct to Jackpot Contribution
An alternative to using sources is to make contributions directly to Jackpot Instances by their ID. For example, if you have created a Jackpot instance, you will have its ID available to you. This ID will not change over the lifetime of the jackpot. Making contributions directly to a Jackpot ID incurs less processing cost, but may also reduce the flexibility you may have in changing which jackpot players contribute to based on the content or user flows.
The only difference in the contribution payload is that the source_id
is replaced with an instance_id
field as seen below:
{
"instance_id": "0a1cfeea-5b07-4f2b-b2f1-2e4cd2aa991d",
"token": "token_00001",
"brand_id": "thrilltech:brand1",
"player_id": "player_00001",
"player_country": "MT",
"gameround_id": "1000",
"base_wager": 2,
"currency": "EUR"
}
Synchronous vs Asynchronous contribution
The default contribution mechanism is synchronous. However, depending on your system architecture (and system load), you may prefer to make use of asynchronous contribution mechanics. In order to make asynchronous contributions, you need to provide a webhook that the ThrillPots system can call once the result of a contribution has been determined.
In order to make a contribution asynchronously, you simple need to add a callback
property to either of the contribution payloads above to specify the webhook to call and which results you are interested in receiving.
The structure of the callback
property is as follows:
{
"web_hook": "https://your.host/webhook",
"win_result_only": false
}
The web_hook
field indicates the fully qualified HTTP path to your webhook and the win_result_only
property indicates whether the webhook should only receive win results or all contribution results.
Therefore, an asynchronous contribution for a sitewide casino jackpot would look like this:
{
"token": "token_00001",
"brand_id": "thrilltech:brand1",
"player_id": "player_00001",
"player_country": "UK",
"source_id": "casino-sitewide",
"gameround_id": "1",
"currency": "EUR",
"base_wager": 1,
"callback": {
"web_hook": "https://your.host/webhook",
"win_result_only": false
}
}
When making an asynchronous contribution, the ThrillPots system will either return 200 OK
with a JSON payload that contains a trace_id
for the request when it has successfully accepted the contribution request for processing, or you will receive an error due to the request being malformed.
Any contribution request errors will be send to the webhook. The structure of the webhook payload is defined as follows:
Successful contribution result
{
"type": "data",
"contribution_amount": Number,
"contribution_currency": String,
"gameround_id": String,
"instance_id": String,
"metadata": null | Object,
"tickets_awarded": null | Number,
"timestamp": Number,
"win_amount": Number,
"win_pot_id": null | String,
"win_withheld": Boolean
}
Error result
{
"type": "error",
"status_code": Number,
"code": String,
"message": String,
}
The data
portion will either be a ContributionResult
structure or an Error
structure. You can find more information on these structures in the API documentation.
Examples of payloads sent to the web hook
Contribution Result
{
"type": "data",
"contribution_amount": 0.1,
"contribution_currency": "EUR",
"gameround_id": "cc83c1cc-6260-44fc-822b-d3c03acf2d89",
"instance_id": "a49ff35f-6ecd-491f-b373-85e6caabacf1",
"metadata": null,
"tickets_awarded": null,
"timestamp": 1715714218408,
"win_amount": 0,
"win_pot_id": null,
"win_withheld": false
}
Error Result
{
"type": "error",
"status_code": 404,
"code": "GAME_NOT_FOUND",
"message": "sitewide-casino2",
}
Contribution Request Errors
A contribution request may result in a direct
or a downstream
error. A direct
error is an error that is the result of the ThrillPots system return an error to the contribution request itself. A downstream
error is an error that is propogated to the contribution request caller from a downstream system, such as ThrillGate or the operator wallet itself.
List of Direct Errors
For Direct Errors, you can expect:
Error Code | Description |
---|---|
CONTRIBUTION_REJECTED | The contribution was rejected due to a contribution rule failing, The rule in question will be contained within the CONTRIBUTION_REJECTED message |
GAME_NOT_FOUND | this occurs when making a contribution to source and the source does not exist |
CURRENCY_MULTIPLIERS_NOT_FOUND | self explanatory |
SYSTEM_ERROR | This is what you get with 500 http responses from ThrillPots |
OPTIN_ERROR | This occurs if the player;s optin record could not be updated |
SOURCE_JACKPOT_NOT_FOUND | This occurs if the jackpot mapped to the source could not be found |
SOURCE_JACKPOTS_NOT_ALLOWED | This occurs if the jackpot mapped to the source does not allow a contribution from this player (either country or brand not allowed) |
DB_ERROR | An internal DB ERROR |
UNSUPPORTED_BRAND | This is returned when the brand of the player (specified in contribution) is not supported by the jackpot or system |
Passing Metadata
If you need to pass contextual metadata from your event processor to your wallet, you can do so by adding a metadata
field to the Contribution Request. This data will be passed through the system and attached to transaction requests to your wallet.
The metadata
field can be any valid JSON value, for example:
Metadata containing an Object:
{
"token": "token_00001",
"brand_id": "thrilltech:brand1",
"player_id": "player_00001",
"player_country": "UK",
"source_id": "casino-sitewide",
"gameround_id": "1",
"currency": "EUR",
"base_wager": 1,
"metadata": {
"value1": "some value",
"value2": 1234
}
}
Metadata containing a String:
{
"token": "token_00001",
"brand_id": "thrilltech:brand1",
"player_id": "player_00001",
"player_country": "UK",
"source_id": "casino-sitewide",
"gameround_id": "1",
"currency": "EUR",
"base_wager": 1,
"metadata": "This is an arbitrary string value"
}
Contribution Sources
Contribution Sources are a concept in ThrillPots that allow operators create well-known identifiers for one or more Jackpot Instances. A contribution source is bound to an operator and brand ID.
Contribution Sources are valid targets/identifiers for jackpot contribution bets (as described in the Contributing to Jackpots section).
Why use sources instead of Jackpot Instance IDs
Sources provide a mechanism of indirection to Jackpot Instances. Since a Source
will usually have a well-known and human-defined identifier, and can represent one or more Jackpot Instances at any point in time, they provide a very convenient way for Integrating services and frontends to work with Jackpot Instances.
For example, instead of hard coding a specific Jackpot Instance ID into your frontend or backend services, you can simply configure the more human-readable source_id
and use the Source to determine at runtime which Jackpot Instance ID is being used. This is especially useful when Jackpot models are changed over time since your integrated product will not need to be modified unless there is a fundamental structural change to the jackpot itself (which is rarely the case).
Example
An early, but very common use-case Contribution Source can be seen below, where a Source
has been created for Operator thrilltech
, Brand brand1
and is the source for the "site wide casino jackpot".
In this case, the contribution flow would look like this:
┌──────────────────────────────┐
│Contribution to Source Request│ (POST https://thrillpots_gateway_host/jackpots/contribute/source)
└──────────────┬───────────────┘
│
│
│
▼
┌────────┐
│ Source │
└────────┘
│
│
│
▼
┌──────────────────┐
│ Jackpot Instance │
└──────────────────┘
Under the covers (in the data), this Contribution Source
will most probably look something like this:
{
"owner_id": "thrilltech:brand1",
"source_name": "Casino Sitewide Source",
"source_id": "sitewide-casino",
"jackpots": [
{
"priority": {
"$numberLong": "0"
},
"owner_id": "thrilltech:brand1",
"instance_id": "12231b6a-a774-4a93-8f16-f8af9aee2076"
}
]
}
The jackpots
array in this Contribution contains a single Jackpot Instance ID because in this case, there is only one Jackpot Instance required. We will discuss use cases where having multiple Jackpot Instances in this array can be useful.
Retrieving the Jackpot Instance from a source
To retrieve that relevant Jackpot Instance for a specific source, you can use the following methods:
ThrillPots Gateway
GET /jackpots/instances/source/:source_id/brand/:brand_id?player_id=:player_id
The parameters in the url above are:
Parameter | Description |
---|---|
source_id | The Source ID (for example, sitewide-casino from the example above) |
brand_id | This is the identifier for the brand in question, which is comprised of the operator_id :brand_id pairing |
player_id | [OPTIONAL] If a player_id is specified, the returned Jackpot Instance will also contain the opt-in details for the specified player |
ThrillConnect (used by the Frontend)
GET /v1/thrillpots/instances/source/:source_id/brand/:brand_id?player_id=:player_id
The parameters in the url above are the same as for ThrillPots Gateway:
Parameter | Description |
---|---|
source_id | The Source ID (for example, sitewide-casino from the example above) |
brand_id | This is the identifier for the brand in question, which is comprised of the operator_id :brand_id pairing |
player_id | [OPTIONAL] If a player_id is specified, the returned Jackpot Instance will also contain the opt-in details for the specified player |
Retrieving all sources in the System
To retrieve a list of sources for a specific operator brand, you can use one of the following methods:
ThrillPots Gateway
GET /sources?owner_id=:brand_id
The brand_id
parameter in the URL is once again comprised of the operator_id
:brand_id
pair which identifies a specific brand. If any sources have been configured for the operator_id
:brand_id
specified, they will be returned in a response which contains a list of Source
JSON objects and will look similar to this example:
[
{
"owner_id": "thrilltech:brand1",
"source_name": "Casino Sitewide Source",
"source_id": "sitewide-casino",
"jackpots": [
{
"priority": 0,
"owner_id": "thrilltech:brand1",
"instance_id": "12231b6a-a774-4a93-8f16-f8af9aee2076"
}
]
}
]
ThrillConnect (used by the Frontend)
GET /v1/thrillpots/sources?owner_id=:brand_id
As in the ThrillPots Gateway example above, the brand_id
parameter in the URL is once again comprised of the operator_id
:brand_id
pair which identifies a specific brand. The response payload will look exactly the same as the response from the ThrillPots Gateway service above.
ThrillPots Events
ThrillPots publishes a number of events which your integration service can subscribe to. There are a number of reasons you may want to consume these events, for example:
- Synthesizing related Kafka/RabbitMQ events
- Storing the events for BI / Analysis purposes
The following events are currently published by ThrillPots Gateway:
JackpotUpdateEvent
- contains the latest jackpot values for the specified Jackpot Instance- Reference
{
"event_type": "JackpotUpdateEvent",
"event_id": "d6f05820-1da2-4152-bcba-6c0186f6cd77"
"data": {
"id": "jackpot instance ID",
"status": String,
"currency": String,
"allowed_brands": [String],
"allowed_sources": [String],
"pots": [
{
"id": String,
"is_progressive": Boolean,
"current_value": Number
}
],
"last_updated": Number
}
}
JackpotWinEvent
- contains the details of a jackpot win- Reference
{
"event_type": "JackpotWinEvent",
"event_id": "3fe809f4-c94f-4950-9b86-5f2d0b8f604f"
"data": {
"brand_id": String,
"player_id": String,
"source_id": String | null,
"instance_id": String,
"jackpot_name": String,
"timestamp": Number,
"win_pot_it": String,
"win_amount": Number,
"currency_multipliers": {
"brand_id": String,
"base_currency": String,
"multipliers": {
"EUR": Number,
"GBP": Number,
"ZAR": Number,
...
"NZD": Number,
"SEK": Number
}
}
"games_in_jackpot": [String],
"seed": Number,
"win_withheld": Boolean,
"seed_deficit": Number,
"community_winners": null | [{
"player_id": String,
"brand_id": String,
"currency": String,
"win_amount": Number
}]
}
}
RaffleWinEvent
- contains the details of a Raffle Win- Reference
{
"brand_id": String,
"instance_id": String,
"jackpot_name": String,
"jackpot_currency": String,
"currency_multipliers": {
"brand_id": String,
"base_currency": String,
"multipliers": {
"EUR": Number,
"GBP": Number,
"ZAR": Number,
...
"NZD": Number,
"SEK": Number
}
}
"timestamp": Number,
"winners": [
{
"player_id": String,
"brand_id": String,
"currency": String,
"win_amount": Number
}
],
"win_withheld": bool
}
OptInEvent
- contains the details of a player opt-in or opt-out into a Jackpot Instance Reference
{
"event_type": "OptInEvent",
"event_id": "27045bf8-78d2-4f99-97f1-e7d2e3aa434d"
"data": {
"instance_id": String,
"player_id": String,
"ext_player_id": String,
"player_brand_id": String,
"preferred_contribution_value": [Number],
"contribution_count": Integer,
"contribution_value": Number,
"opted_in": Boolean,
"last_updated": Integer
}
}
CommunityPayoutErrorEvent
- sent in case of an error that is encountered when processing community payouts Reference
{
"event_type": "CommunityPayoutErrorEvent",
"event_id": "c034a751-cf91-4722-bc89-a2f8af472805"
"data": {
"instance_id": String,
"gameround_id": String,
"tx_credit_id": String,
"failed_payouts": [
{
"player_id": String,
"brand_id": String,
"currency": String,
"win_amount": Number
}
]
}
}
RafflePayoutErrorEvent
- sent in case of an error that is encountered when processing raffle payouts Reference
{
"event_type": "RafflePayoutErrorEvent",
"event_id": "e981296b-199f-4454-b4ec-b3f36910c2cc"
"data": {
"instance_id": String,
"failed_payouts": [
{
"player_id": String,
"brand_id": String,
"currency": String,
"win_amount": Number
}
]
}
}
The ThrillPots events are published via the WebSocket endpoint /events
.
Authenticating the Websocket connection to receive events
Once you have established a WebSocket connection from your event processor service to ThrillPots Gateway, you will need to send an Authenticate
message which contains your Thrill-ID JWT token to authenticate your service to receive events.
{
"action": {
"Authenticate": {
"auth_token": "{{thrill-id-jwt}}"
}
}
}
If the authentication fails, the connection will be closed. Once you have authenticated, you should start receiving the events from the ThrillPots service.
Wallet Integration
Introduction
When integrating ThrillPots to your wallet, you will need to implement what is known as the "Standard Wallet API". This API has been defined by ThrillTech and is what our ThrillGate services uses to communicate with your backend to process:
- Player Authentication
- Transactions
- Transaction cancellations
- Batch transactions
- Batch transaction cancellations
All communications from ThrillGate are conducted over secure SSL REST calls to your system.
As part of all calls to your system, ThrillGate sends an HMAC in the X-Server-Authorization
header which is calculated from the body of the request only. You can use this HMAC value to verify that the request is coming from the expected ThrillGate server.
NOTE: During integration you will receive the secret key that you can use to verify the HMAC value with.
Sequence Diagram for Wallet integration with ThrillGate
Standard Wallet API: Player Authentication
In order for the ThrillPots system to take wagers (debit the player's wallet) and payout winnings (credit the player's wallet), it needs to be able to authenticate the player with the operator wallet.
This is done by calling the Standard Wallet's auth
endpoint, passing in the provided player token and game code to the operator wallet and receiving the required player details (including the token that should be used for transaction calls)
This is done by ThrillGate calling the endpoint defined in endpoints.auth
of the Standard Wallet's configuration. An example call's payload would look as follows:
{
"operator_id": "your_operator_id",
"brand_id": "your_brand_id",
"player_token": "token_00001",
"game_code": "AwesomeJackpotGameCode",
"currency": "EUR"
}
If successful, the operator wallet must respond with a valid session token and player details that can be used for future transaction calls for this player.
Response example:
{
"id": "player_00001",
"token": "session_token_00001",
"currency": "EUR",
"balance": 100001927.79,
"operator_id": "thrilltech",
"brand_id": "brand1",
"nickname": null,
"gender": "?",
"country": "MT",
"jurisdiction": null,
"segments": null
}
Standard Wallet API: Transactions
Transactions
Once the player token has been authenticated, the ThrillPots system can start making transaction calls through ThrillGate.
In standard operation, the first transaction call will be a Debit
transaction request to fetch funds from a player's wallet for the Jackpot Contribution bet. This call is also intended to open the game round for the jackpot contribution.
If successful, ThrillPots will process the jackpot contribution and determine if a win occurred.
The next transaction call that will be made will be a Credit
transaction request. This call is intended to pay any winnings to the player account and to close the game round that was opened with the Debit
transaction.
Transaction Errors
If an error occurs while executing transactions with the operator wallet, ThrillGate and ThrillPots cooperate to ensure that the transaction error is handled correctly.
When an error occurs, ThrillGate will attempt to retry the transaction request a set number of times. If all retries fail, the error will be sent to ThrillPots for further handling.
If there are certain wallet errors that you do not wish ThrillGate to perform its retry logic, you can configure that as part of the wallet configuration in ThrillGate.
Please see the ThrillGate section on Configuring Wallet Error Behaviour for more information on how to configure ThrillGate's wallet error handling.
Once an error has been sent back to ThrillPots, ThrillPots will decide whether a transaction needs to be cancelled or not. Transaction cancellation is discussed next.
#@ Transaction Cancellation
In certain situations (as described in the errors section above), it is necessary for transactions to be cancelled. In general, ThrillPots handles transaction cancellation logic as follows:
If the Debit transaction failed
ThrillPots will send a cancellation request for the Debit
transaction using the Debit transaction ID.
If the Credit transaction failed
ThrillPots will first send a cancellation request for the Credit
transaction and then a separate cancellation request for the Debit
transaction. Both requests will be sent with the respective transaction IDs.
Transaction Batches (Credit only)
ThrillPots uses Transaction Batch requests to communicate payouts to multiple players.
These types of payouts are only relevant to jackpots that are either:
- Multi-player payouts (community payouts)
- Raffle jackpot payouts
In both situations, since multiple players are considered winners from a single jackpot win, ThrillPots needs a way to credit wins to multiple players. Since these players are not guaranteed to be online at the time of the win, ThrillPots will not have access to any session token information for all the winners.
Transaction Batches are used in these special situations to communicate a set of credit operations that need to be applied to multiple players accounts.
Although unlikely, it is possible that not all the specified player accounts will be able to be credited with the winnings. Such a situation may arise if, for example, the player account has been banned/blocked or is self-excluded at the time of the jackpot win.
In these cases, the operator wallet is expected to flag the player account as an exception and continue to pay the remaining players in the transaction batch.
It is not considered an error if a player account in a transaction batch cannot be paid. The operator wallet should simply indicate this exception in the response and attempt to pay all other players.
Transaction Batch Cancellation
We have discussed what Transaction Batch exceptions are and how they are handled.
There is another limited set of errors that require Transaction Batches to be cancelled.
These errors are typically (but not limited to) errors such as network errors and timeouts. When an error occurs that leads ThrillGate to not be sure whether the operator's wallet has handled the transaction batch request, the request will first be retried, but after failing a specific number of times, the transaction batch will be cancelled.
Each transaction batch request has a unique identifier, and this identifier will be sent as part of the transaction batch cancellation request.
Frontend Integration
The final piece of the ThrillPots integration puzzle is the frontend integration. The frontend is responsible for displaying the Jackpot Ticker widget, showing players what the value of the various pots within the Jackpot are, the opt-in widget, allowing players to opt-in or opt-out of participation in the jackpot and so on.
The ThrillConnect Service has been specifically developed to provide an API and event stream over WebSockets to frontend clients to be able to interact with the ThrillPots system.
Integration Options
When integrating the frontend, there are two options that you can take:
- Use the existing libraries/components that ThrillTech has built to ease the effort of frontend integration:
- Develop your own integration with ThrillConnect and your own animation layer for the win animations
The sections below will detail the low level integration approach to help you understand how things work. You can then decide which of the options mentioned above you wish to take.
Sequence Diagram for the frontend to ThrillConnect integration
Integration Flow in detail
Fetching a Jackpot's details
One of the first things your frontend will most likely need to do is to retrieve jackpot details for your jackpot widget to display.
If you have followed the section on settings up the AIO container, you would have created a
Source
calledsitewide-casino
.If you haven't gone through the process of setting up a source, we suggest that you review and understand sources and how they are used before continuing
To retrieve the jackpot for the sitewide-casino
source, you will need to call:
GET /v1/thrillpots/instances/source/:source_id/brand/:brand_id?player_id=:player_id
replacing the :source_id
and :brand_id
values with the appropriate values that have been configured. If you used the default values from the Postman collection, you can use sitewide-casino
for the source_id
and thrilltech:brand1
for the brand_id
.
If the player is already logged in, you can also pass the ID of the player via the query parameter player_id
. Doing so will ensure that the player's opt-in status is returned in the jackpot instance information.
Establishing a WebSocket connection
In order to receive ThrillPots events and be able to opt players in or out of the jackpot, you will need to establish a websocket connection.
Once a player is logged into an operator's site, you can establish a WebSocket connection with ThrillConnect, passing in the player's session token.
NOTE
WebSocket connections are protected and can only be established by logged in players to prevent unauthorized and potentially dangerous abuse by attackers. Requiring a player a valid player session token in order to establish a WebSocket connection is a security-driven decision
To establish a WebSocket connection with ThrillConnect, open a WebSocket to:
/v1/events/{operator_id}/{brand_id}?token=PLAYER_TOKEN¤cy=PLAYER_CURRENCY
ThrillConnect will authenticate the token
(the Player session token) from the query parameters with the operator's platform via ThrillGate. If the token is valid, the websocket connection will be established. If the token is invalid, the connection will receive a 403 FORBIDDEN
error.
Subscribing to ThrillPots events
Once you have successfully established a WebSocket connection, you can now subscribe to ThrillPots events. This is done by sending a subscription request via the WebSocket to ThrillConnect. See below for the SubscribeRequest
message that should be sent to subscribe to all ThrillPots events:
{
"SubscribeRequest": {
"events": [{
"source": "thrillpots",
"event_type": "*"
}]
}
}
If you would like to subscribe to only certain events, you can do so by explicitly specifying the events by source one-by-one.
ThrillPots currently publishes the folliowing event types:
- JackpotUpdateEvent
- WinEvent
- RaffleWinEvent
- OptInEvent
For more information about the structure of each of these events, see ThrillPots Event Structures
Player Opt-in / Opt-out
To opt a player in or out of a jackpot, you must send a PlayerOptInRequest
message via the WebSocket connection.
Below are a few examples of opting a player in and out of a jackpot instance (please note, you will need to have the jackpot instance ID):
Opting in
{
"PlayerOptInRequest": {
"instance_id": "8dcc9f5a-f1c5-466f-83e9-928277d8bfb7",
"player_id": "player_00001",
"brand_id": "thrilltech:brand1",
"player_country": "MT",
"opt_in": true
}
}
Opting in with a preferred contribution value of 0.20
{
"PlayerOptInRequest": {
"instance_id": "8dcc9f5a-f1c5-466f-83e9-928277d8bfb7",
"player_id": "player_00001",
"brand_id": "thrilltech:brand1",
"player_country": "MT",
"opt_in": true,
"contribution_value": 0.2
}
}
Opting out of a Jackpot
{
"PlayerOptInRequest": {
"instance_id": "8dcc9f5a-f1c5-466f-83e9-928277d8bfb7",
"player_id": "player_00001",
"brand_id": "thrilltech:brand1",
"player_country": "MT",
"opt_in": false
}
}
Retrieving Exchange Rates
You may need to convert the values of a jackpot instance from the Jackpot currency to a player's currency. To help facilitate this, ThrillConnect exposes a currency endpoint which allows you to fetch the exchange rates used by ThrillPots.
To retrieve the 202408-1 exchange rates, you can call:
GET /v1/currencies
Retrieving a player's raffle ticket count
If player's are contributing to a Raffle jackpot, you may want to show the player how many tickets they have earned so far in the raffle. You can retrieve the player's current ticket count by requesting it via the WebSocket connection:
To retrieve a player's ticket count, send a PlayerRaffleTicketsRequest
message:
{
"player_id": String,
"instance_id": String,
"brand_id": String
}
The instance_id
is the instance ID of the Raffle jackpot, and the brand_id
is in the format operator_id:brand_id
.
If the request can be serviced, you should received a PlayerRaffleTicketsResponse
message back:
{
"msg_type": "Message",
"source": "thrillpots",
"msg_name": "PlayerRaffleTicketResponse",
"operator_id": "OPERATOR_ID",
"brand_id": "BRAND_ID",
"player_id": "PLAYER_ID",
"data": {
"ticket_count": 4
},
"timestamp": 1711452762485
}
If there was an error processing the request, you will receive an Error
message in response which will contain the message name that errored, as well as any relevant error details. For example:
{
"msg_type": "Error",
"source": "thrillpots",
"msg_name": "PlayerRaffleTicketRequest",
"operator_id": "OPERATOR_ID",
"brand_id": "BRAND_ID",
"player_id": "PLAYER_ID",
"data": {
"status_code": 404,
"code": "",
"message": "Error 404 Not Found from http://localhost:8084/instances/raffle/e0dee1ae-6231-458a-ad6d-4dc0c941e5c3/tickets/player_00001/brand/thrilltech:brand1"
},
"timestamp": 1711452757807
}
In this case, the request Jackpot instance ID could not be found.
ThrillConnect JS Client
ThrillConnect Client is the glue that connects your Portal and ThrillTech systems to provide seamless experience for your players. It is designed with minimialistic, yet powerful API, that can be easily consumed and covers all the narrow and tricky edgecases of the frontend integration. It's purpose is to make your frontend development trivial and expose the full API surface with minimum effort.
On this page you can find all the relevant details on how to use the Client, as well as examples and use cases.
Client version will be aligned with service version and just like that you'll be subscribed to all the latest and greatest features of our platform.
Source
Source code is avaiable for review & fork for all ThrilTech customers. You can find the client at https://github.com/thrilltech-io/connect-client.
Initialization
Client constructor needs the host address and BrandContext. Player context can optionally be passed on initialization or later on via authenticate
method.
Additionally one can specify dev options, like the use of unsecure http/ws and client internal logs for dev convenience.
All the events of interest must be passed on to the constructor in the events
array so that client can subscribe to relevant systems on the WS channel.
Player context
Player context type provides all necessary player details for establishing the WSS connection and interacting with the Jackpots from player perspective.
type PlayerContext = {
id: string,
token: string,
currency: string,
country: string,
}
Initialization without player context
Prior to having a valid player session and auth token, one can initialize the client without PlayerContext. In this limited mode the WS events will not be available and only public REST endpoints can be used to make requests. ( see API section for what is available )
import { ThrillConnect, ConnectEvents } from "./thrillconnect.js"
const client = new ThrillConnect({
host: "localhost:11000",
brand: {
operator_id: "thrilltech",
brand_id: "brand1",
},
dev: {
secure: false
},
events: [
ConnectEvents.JackpotUpdateEvent,
ConnectEvents.RaffleWinEvent,
ConnectEvents.JackpotWinEvent,
ConnectEvents.OptInEvent,
]
})
Later on, once we have player details, we can authenticate and subscribe to full functionality of the client.
client.authenticate({
id: "player_id_token_00001",
token: "token_00001",
country: "USA",
currency: "USD",
})
Initialization with player context
Alternatively, if player details are known from the start, those can be passed directly to the client constructor.
const client = new ThrillConnect({
host: "localhost:11000",
player: {
id: "player_00001",
token: "token_00001",
country: "USA",
currency: "USD",
},
brand: {
operator_id: "thrilltech",
brand_id: "brand1",
},
dev: {
secure: false
},
events: [
ConnectEvents.JackpotUpdateEvent,
ConnectEvents.RaffleWinEvent,
ConnectEvents.JackpotWinEvent,
ConnectEvents.OptInEvent,
]
})
API
Following is a list of all the available methods on connect client.
Adding an event listener
client.on(ConnectEvent, handler)
Adding an once off event listener
client.once(ConnectEvent, handler)
Removing an event listener
client.off(ConnectEvent, handler)
Passing player context
client.authenticate(PlayerContext)
Fetching the currency multipliers
const multipliers = await client.request().getCurrencies()
Fetching the list of defined sources for the provided BrandContext
const sources = await client.request().getSources()
Getting the Jackpot instance that maps to a source
const sourceId = "sitewide-jackpot"
const instance = await client.request().getJackpotForSource(sourceId)
Getting the player OptIn status for a source
Note: PlayerContext is required for this request.
const sourceId = "sitewide-jackpot"
const status = await client.request().getOptInStatusForSource(sourceId)
Opting in/out from a source
Note: PlayerContext is required for this request. This request uses the authenticated WS channel. When jackpot allows for variable contribution, preferred contribution value can be passed as 3 parameter.
const sourceId = "sitewide-jackpot"
const optIn = true
const preferredContributionValue = undefined
client.request().optIntoSource(sourceId, optIn, preferredContributionValue)
Opting in/out from an instance
Note: PlayerContext is required for this request. This request uses the authenticated WS channel. When jackpot allows for variable contribution, preferred contribution value can be passed as 3 parameter.
const instanceId = "dd7243ea-9992-47ae-a2a6-531b3f0e2197"
const optIn = true
const preferredContributionValue = undefined
client.request().optIntoInstance(instanceId, optIn, preferredContributionValue)
Events
Client receives events via the WS connection. In order to receive an event, it needs to explicitly be listed in the list of events in the Client constructor.
All the available events are listed in ConnectEvents
.
import { ConnectEvents } from "./thrillconnect.js"
function updateTickers(e:JackpotUpdateEvent) {
console.log(e.status)
}
// subscribe to Jackpot updates
client.on(ConnectEvents.JackpotUpdateEvent, updateTickers)
// unsubscribe from Jackpot updates
client.off(ConnectEvents.JackpotUpdateEvent, updateTickers)
Animation Driver
ThrillTech supplies a default set of Jackpot win animations to enrich the player experience during a Jackpot win. The animations driver is a JS library that takes care of win animations loading and playback. Animations are easily customizable and the driver allows for flexible cusomizations of the playback.
Source
Source code is avaiable for review & fork for all ThrilTech customers. You can find the driver at https://github.com/thrilltech-io/animations-driver.
Overview
The JS driver exposes two functions:
preload(config, tier, muted)
- loads the required assets per pased configuration object. When muted, sounds will not be loaded.run(config, tier, amount, muted)
- starts the animation sequence defined in the configuration. Run will do load if assets are not already loaded.
The preload function is intended to provide separation of the loading phase, so that in case of unreasonably slow connection, stale loading can be detected and acted upon (for example using a fallback alert / win message if assets load didnt complete in a certain period).
Mute state cannot be controlled after the animation is run. The current sound preference should be passed to the run
( and optionally preload
) and based on that the defined in configuration sfx are either loaded or not.
Usage
import { preload, run } from "./main.js"
const config = "/configs/example.json"
const tier = "super"
const amount = 10000
const muted = false
preload(config, tier, muted).then(()=>{
run(config, tier, amount, muted)
})
Configuration
See example configurations in ./public/configs in the driver repository.
Following is a full possible configuration with all settings commented inline.
{
"dom": {
// optional - skip "top" section if no header is required
"top": {
// id of top container
"id": "top-container",
// messages to display during presentation phase
"message": {
"id":"top-message",
// message during wheel spin
"wheel": "Stop the wheel and win BIG! BIG!",
// message during tickup
"tickup": "Congratulations!"
}
},
// optional - skip "bottom" section if no footer is required
"bottom": {
// id of bottom container
"id": "bottom-container",
// action button
"button": {
// id of the action button
"id": "action-button",
// actions during wheel phase
"wheel": {
"stop": "STOP THE WHEEL",
"skip": "SKIP THE WHEEL"
},
// actions during tickup phase
"tickup": {
"skip": "SKIP TICKUP"
},
// actions after tickup
"end": {
"close": "CLOSE"
}
}
},
// enable touch controls during phase
"touch": {
// touch during wheel acts as stop / skip
"wheel": {
"stop": true,
"skip": true
},
// touch during tickup acts as skip
"tickup": true
}
},
// ticker skin and font settings -
// skin provided and customised by thrilltech
"ticker": {
"skin": "/ticker/Win_BG.skel",
"font": "/fonts/rubik.woff",
"fontFamily": "rubik",
// maximum font size for the tickup
"maxFontSize": 80,
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat
// the currency for the win amount as per ISO 4217 currency codes
// optional, leave empty for no currency or monetary amount format
"currency":"JPY",
// A string with a BCP 47 language tag, optional
"currencyFormat":"en-US"
},
// wheel skin and segments settings -
// skin provided and customised by thrilltech
"wheel": {
"rotate": 0,
"base": "/wheel/Wheel_of_Fortune.skel",
// wheel has 8 segments, following is the order of tiers per segments
"segments": [
"mini",
"super",
"mini",
"epic",
"mini",
"super",
"epic",
"super"
],
// map of segment textures
"skins": {
"mini": "/skins/demo/mini.png",
"super": "/skins/demo/super.png",
"epic": "/skins/demo/epic.png"
}
},
// jackpot animation skin -
// skin provided and customised by thrilltech
"pots": {
"mini": {
// path of the spine export containing the mini tier animation
"source": "/pots/mini/Thrillpot.skel",
// prefix of the animation for this tier
"prefix": "",
// sound clips for all animation phases
"sfx": {
"intro": ["/sfx/base/mini/intro.mp3"],
"particles": ["/sfx/base/mini/confetti.mp3"],
"tickup_start": ["/sfx/base/mini/tickup-start.mp3"],
"tickup_loop": ["/sfx/base/mini/tickup-loop.mp3"],
"outro": ["/sfx/base/mini/outro.mp3]"
}
},
"super": {
// path of the spine export containing the mini tier animation
"source": "/pots/super/Thrillpot.skel",
// prefix of the animation for this tier
"prefix": "",
// sound clips for all animation phases
"sfx": {
"intro": ["/sfx/base/super/intro.mp3"],
"particles": ["/sfx/base/super/confetti.mp3"],
"tickup_start": ["/sfx/base/super/tickup-start.mp3"],
"tickup_loop": ["/sfx/base/super/tickup-loop.mp3"],
"outro": ["/sfx/base/super/outro.mp3]"
}
},
"epic": {
// path of the spine export containing the mini tier animation
"source": "/pots/epic/Thrillpot.skel",
// prefix of the animation for this tier
"prefix": "",
// sound clips for all animation phases
"sfx": {
"intro": ["/sfx/base/epic/intro.mp3"],
"particles": ["/sfx/base/epic/confetti.mp3"],
"tickup_start": ["/sfx/base/epic/tickup-start.mp3"],
"tickup_loop": ["/sfx/base/epic/tickup-loop.mp3"],
"outro": ["/sfx/base/epic/outro.mp3]"
}
},
},
// particles animation skin -
// skin provided and customised by thrilltech
"particles": {
"mini": {
"source": "/particles/confetti/Thrillpot.skel",
"prefix": ""
},
"super": {
"source": "/particles/confetti/Thrillpot.skel",
"prefix": ""
},
"epic": {
"source": "/particles/confetti/Thrillpot.skel",
"prefix": ""
}
}
}
SFX
Config contains sound definitions for various phases of the animation. All sounds are optional.
Sounds per animation phase are defined as an array. All elements of the phase array refer to the same sound effect. The intention is to provide multiple sfx formats and the runtime will automatically pick the one supported on the client system. Recommended formats to use are webm
, wav
and mp3
. wav
has the widest support accross devices, but is not as optimal as webm
and mp3
in terms of filesize.
"sfx": {
"intro": ["/sfx/base/epic/intro.webm", "/sfx/base/epic/intro.wav"],
"particles": ["/sfx/base/epic/confetti.webm", "/sfx/base/epic/confetti.wav"],
"tickup_start": ["/sfx/base/epic/tickup-start.webm", "/sfx/base/epic/tickup-start.wav"],
"tickup_loop": ["/sfx/base/epic/tickup-loop.webm", "/sfx/base/epic/tickup-loop.wav"],
"outro": ["/sfx/base/epic/outro.webm", "/sfx/base/epic/outro.wav"]
}
ThrillPots Event Structures
This section provides the data definitions (in JSON) for each of the ThrillPots events.
Event: JackpotUpdateEvent
{
"id": String,
"currency": String,
"pots": [PotTicker],
"allowed_brands": [String],
"allowed_sources": [String],
"status": String,
"last_updated": Number
}
References:
Event: WinEvent
{
"brand_id": String,
"player_id": String,
"source_id": String,
"instance_id": String,
"jackpot_name": String,
"jackpot_currency": String,
"timestamp": Number,
"win_pot_id": String,
"win_amounts": [CurrencyValue],
"win_withheld": bool,
"community_winners": [PayoutRecord],
"games_in_jackpot": [String],
"seed": Number
}
References:
Event: RaffleWinEvent
{
"brand_id": String,
"instance_id": String,
"jackpot_name": String,
"jackpot_currency": String,
"currency_multipliers": {
"brand_id": String,
"base_currency": String,
"multipliers": {
"EUR": Number,
"GBP": Number,
"ZAR": Number,
...
"NZD": Number,
"SEK": Number
}
}
"timestamp": Number,
"winners": [
{
"player_id": String,
"brand_id": String,
"currency": String,
"win_amount": Number
}
],
"win_withheld": bool
}
References:
The winners
field contains an array of tuples. The structure of each tuples is (String, CurrencyValue)
.
The first element in the tuple contains the ID of a winning player and the second element contains the amount that the player won.
Event: OptInEvent
{
"instance_id": String,
"player_id": String,
"ext_player_id": String,
"player_brand_id": String,
"preferred_contribution_value": Number,
"contribution_count": Number,
"contribution_value": Number,
"opted_in": Boolean,
"last_updated": Number,
}
Event: CommunityPayoutErrorEvent
{
"instance_id": String,
"gameround_id": String,
"tx_credit_id": String,
"failed_payouts": [
{
"player_id": String,
"brand_id": String,
"currency": String,
"win_amount": Number
}
]
}
Event: RafflePayoutErrorEvent
{
"instance_id": String,
"failed_payouts": [
{
"player_id": String,
"brand_id": String,
"currency": String,
"win_amount": Number
}
]
}
Structure References
PotTicker
{
"id": String,
"is_progressive": Boolean,
"current_value": Number
}
CurrencyValue
{
"currency": String,
"value": Number
}
PayoutRecord
{
"player_id": String,
"brand_id": String,
"currency": String,
"win_amount": Number
}
APIs
In this section, you will find the necessary API documentation for the relevant integration services for a SaaS integration:
Thrillpots Gateway
ThrillGate
ThrillConnect
NOTE: This is early documentation for the scheduling system and the documentation will be further extended over time with additional examples and more details
Advanced Scheduling
The ThrillPots system provides a relatively sophisticated sub-system which allows you to create schedules for your jackpot products.
It is important to understand what a schedule is in the context of ThrillPots.
At its core, a schedule is always bound to a Jackpot Instance. A schedule can be as simple as defining the date and time that a jackpot starts at, or defining an end date and time for jackpot.
Here are some interesting use cases that can be solved with schedules as well:
- Happy Hour Jackpot: Creating a jackpot that only accepts contributions during 17:00 and 18:00
- Promotional Jackpots: Creating a jackpot that only accepts contributions at peak times of site activity or to encourage players during low activity times
- Weekend Jackpots: Creating a jackpot that is only available on weekends
Schedules become even more powerful when used together with Raffle Jackpots. Raffle Jackpots are jackpots that resolve at the end of a predefined period of time. While players participate in the Raffle Jackpot by way of contribution (as with any other jackpot), raffle jackpots issue tickets to players based on either their Contribution or the base wager that they make into games.
Recurrence Rulesets
All the rules for the scheduling system revolve around "recurrence rules". Currently, recurrence rules are implemented for "Daily" and "Weekly" rulesets.
Daily rules
Daily rules define a set of hours within which the jackpot is available in. Traditionally, jackpot contributions are allowed during all hours of the day, but lets imagine that you wanted to create a jackpot that was only available during your site's "Happy Hour" which was between the hours of 7pm to 9pm UTC.
For such a rule to exist, you would only need to define a Daily
recurrence rule which stipulated that the hours of 19:00 to 21:00 UTC were valid.
Weekly rules
Taking the example from above, lets imagine that we wanted to further constrain the available days of the raffle to be from Monday to Friday (no weekend contributions allowed!). In this case, we would create a "Weekly" ruleset which define the following days as being valid: Monday through to Friday.
As a last minute change, business might want to allow contributions to happen on a Saturday, but only between 08:00 UTC to 20:00 UTC. To allow this specificity of ruleset, we can apply an additional override for Saturday for those specific hours at the Weekly schedule level.
Technical Example
For a technical example of what a complete schedule as described above would look like, the following JSON structure accurately describes the ruleset. For arguments sake, we will define the schedule to start on the 1st of January 2024 UTC, with no end to the schedule.
To summarise, we will be creating a schedule that:
- Allows contributions to occur Monday, Tuesday, Wednesday, Thursday, Friday and Saturday
- From Monday to Friday, contributions will be allowed between 19:00:00 UTC and 21:00:00 UTC
- On Saturdays, contributions will be allowed between 08:00:00 UTC and 20:00:00 UTC
{
"timestamp_start": 1704067200000,
// No `timestamp_end` is specified since the schedule has no end
"recurrence_rules": [
{
"frequency": {
"Daily": {
"hours": [
[
{ "hour": 19, "minute": 0, "sec": 0 }.
{ "hour": 21, "minute": 0, "sec": 0 }
]
]
}
},
"interval": 1, // 1 means "every day". 2 would mean "every second day"
},
{
"frequency": {
"Weekly": {
"days": [
["Mon", null].
["Tue", null],
["Wed", null],
["Thu", null],
["Fri", null],
["Sat", {
"Daily": {
"hours": [
[
{ "hour": 8, "minute": 0, "sec": 0 },
{ "hour": 20, "minute": 0, "sec": 0 }
]
]
}
}]
]
}
}
}
]
}
As can be seen from this example, when defining the Weekly
rule, each day of validity needs to be specified, along with any overrides to the underlying Daily
rules that may exist.
Order of Precendence
It is important to note that any hourly overrides present in the Weekly
ruleset will take precedence over those specified in the Daily
rules.
How Scheduled Jackpots work
When a schedule is applied to a normal Jackpot Instance, the system performs some rudimentary initial checks (making sure that when the jackpot is created with a schedule in the future, that the status is correctly set to Pending
).
Once the Jackpot Instance is Active
, the applied schedule defines the periods of time during which contributions will be accepted by the Jackpot Instance. When the schedule is not accepting contributions, the Jackpot Instance will continue to be Active
(this behaviour may change in the future).
How Scheduled Raffles work
When instantiating Raffle Jackpots, a schedule must be provided during instantiation time
The reason for this is due to the fact that raffles are fundamentally time-based entities with at least a start time and duration-per-raffle.
Raffles have an explicit duration which is defined as part of the Raffle Rules. Durations can be defined in units of Seconds, Minutes, Hours, Days or Weeks.
Raffles that have a schedule that is longer than a raffles duration are considered "recurring raffles" while raffles that have a schedule equal to their duration are considered "once-off raffles".
Lets examime a few examples to explore this concept:
Once off Raffles
Lets imagine a scenario where an operator wants to run a once-off raffle for the Festive season (Xmas) period which start from 00:00:00 UTC on the 1st of December 2024 and the raffle resolves (pays out) at 09:00:00 UTC on the 25th of December 2024.
Additional requirements for the raffle are that the raffle should only accept contributions between the hours of 8am CET until the end of each day.
In order to create a schedule for this type of raffle, we need to create rules that specify the hourly restrictions as well as the start and end of the raffle.
Example
{
// Sunday, 1 December 2024 00:00:00
"timestamp_start": 1733011200000,
// Wednesday, 25 December 2024 09:00:00
"timestamp_end": 1735117200000
"recurrence_rules": [
{
"frequency": {
"Daily": {
"hours": [
[
{ "hour": 8, "minute": 0, "sec": 0 }.
{ "hour": 23, "minute": 59, "sec": 59 }
]
]
}
},
"interval": 1,
}
]
}
As can be seen in the example, the timestamp_start
and timestamp_end
have been set to the period of the Festive Season (December 1st, 2024 to December 25th 2024 respectively) and the hours of availability are set from 08:00:00 UTC to 23:59:59 UTC.
Since the jackpot is available on all days through the period, there is no need to define the Weekly
ruleset.
In addition to the schedule, the raffle will also need to be configured to run for the duration of the schedule. In this case, the duration will be 24 days and 9 hours.
NOTE In general, you as an operator do not need to worry about the duration configuration as this is configured as part of the Jackpot template by the ThrillTech Jackpot Model design team and not something you as an operator need to worry about.
Daily Raffles
In this example, we will be configuring a Raffle jackpot that is available on all days of the week and will resolve (pay prizes to players) at 10pm UTC (22:00:00 UTC) each day. The raffle will start at 00:00:00 of each day and end when it resolves daily.
Example:
In this example, the raffle started on August 1st, 2024 at 00:00:00 UTC:
{
// Thursday, 1 August 2024 00:00:00
"timestamp_start": 1722470400000,
"recurrence_rules": [
{
"frequency": {
"Daily": {
"hours": [
[
{ "hour": 0, "minute": 0, "sec": 0 }.
{ "hour": 22, "minute": 0, "sec": 0 }
]
]
}
},
"interval": 1,
}
]
}
In addition to the schedule, the raffle's duration will be defined to last 22 hours.
General Services
ThrillConnect Service
The ThrillConnect Service is designed to be an "edge" service, meaning that it can be deployed to the edge of your hosting environment and service requests from your frontend(s) as well as other services (both internal or 3rd party).
ThrillConnect provides the following API interfaces for your frontend to use:
- REST API (for information retrieval purposes)
- Authenticate WebSocket interface (for authenticated requests and ad-hoc event delivery)
ThrillConnect: ThrillPots REST API
ThrillConnect provides a REST API for your applications (frontend or otherwise) to safely retrieve information about jackpots that are running in the environment.
Retrieving a Jackpot for a particular Source
If you want to retrieve a jackpot for a specific source_id
, you can call the following endpoint:
GET /v1/thrillpots/instances/source/:source_id/brand/:brand_id
Parameter | Type | Required | Description |
---|---|---|---|
source_id | Path | Yes | The source ID for the request |
brand_id | Path | Yes | The brand ID for the request |
player_id | Query | No | The player ID that the request should be specific for |
country_code | Query | No | The country code for the request |
This request will use the provided parameters to retrieve the most appropriate jackpot for the source_id, brand_id, player_id and country_code combination.
If you specific the player_id
, you will also receive the opt-in status for that player in the response.
HINT: Once you have retrieved the Jackpot for a source, you can use the
id
of the Jackpot instance for when you need to opt a player in or out
Retrieving Currency Exchange Rates
If you need to retrieve the active exchange rates in use by the ThrillPots system, you can call the currencies endpoint:
GET /v1/currencies
This will retrieve the current exchange rates from the base currency of the system, for example:
{
"last_updated": 1715126401000,
"base_currency": "EUR",
"multipliers": {
"EUR": 1.0,
"USD": 1.0762,
"GBP": 0.8592,
"CAD": 1.4753,
"PLN": 4.311,
...
"NZD": 1.7921,
"AUD": 1.6303,
"RON": 4.9753,
"SGD": 1.4567,
"SEK": 11.6761,
}
}
Retrieving ThrillPots Sources
You can retrieve all configured sources for a specific brand by using:
GET /v1/thrillpots/sources?owner_id=XXX
The response to this query, if any sources have been configured for the owner_id
will look something like this:
[
{
"owner_id": "thrilltech:brand1",
"source_name": "site-wide",
"source_id": "site-wide-source",
"jackpots": [
{
"priority": 0,
"owner_id": "thrilltech",
"instance_id": "209cc142-ccb2-4e28-a763-0a031b560d74"
}
]
},
{
"owner_id": "thrilltech:brand1",
"source_name": "Deposit jackpot",
"source_id": "deposit-source",
"jackpots": [
{
"priority": 0,
"owner_id": "thrilltech",
"instance_id": "0a031b56-4e28-a763-ccb2-2090d74cc142"
}
]
}
]
ThrillConnect: WebSocket API
ThrillConnect exposes an authenticated WebSocket API for use by your frontend or service applications.
Connecting to the WebSocket endpoint
In order to connect to the ThrillConnect WebSocket endpoint, create a WebSocket client and connect to:
ws://thrillconnect_service_host/v1/events/:operator_id/:brand_id
Parameter | Type | Required | Description |
---|---|---|---|
operator_id | Path | Yes | The operator ID of the casino |
brand_id | Path | Yes | The brand ID of the casino |
token | Query | Yes | The session token for the player that is connecting |
currency | Query | Yes | The currency of the player that connecting |
Example
ws://thrillconnect_service_host/v1/events/casino-group/awesome-brand?token=session_token_00001¤cy=USD
Once a connection is established, ThrillConnect will attempt to authenticate the player using the token
provided with your wallet/account system. This authentication will take place using the Authentication endpoint via ThrillGate.
If authentication is successful, the connection will remain open. If authentication fails, the connection will be closed with a 401
error.
WS Message Structure
All messages that you receive from the ThrillConnect WebSocket connection have the following structure:
{
"msg_type": String, ("Event" | "Message" | "Error"),
"source": String,
"msg_name": String,
"operator_id": String,
"brand_id": String,
"player_id": String,
"data": Object,
"timestamp: Number
}
Field | Description |
---|---|
msg_type | This can contain one of the following values: - Event - Message - Error |
source | This indicates the source system that sent the message. In the case of ThrillPots, the value will be thrillpots |
msg_name | The name of the message. Refer to the events and requests sections for more information |
operator_id | The operator ID that this message is targetted for |
brand_id | The brand ID that this message is targetted for |
player_id | If not null, the player_id that the message is targetted for |
data | The message payload (structure is dependent on the msg_type ) |
timestamp | The timestamp (UNIX epoch) that the message was sent at |
ThrillConnect: Event Subscription
Subscribing for events
Once you have a connection established, you will usually want to subscribe for events. The ThrillTech event system allows you to specify which systems, and which events from those systems, you wish to subscribe to.
To subscribe for events from the ThrillPots system, you must send a SubscribeRequest
message via the websocket connection. For example, to subscribe to all events from the thrillpots
system, you can send the following message:
{
"SubscribeRequest": {
"events": [{
"source": "thrillpots",
"event_type": "*"
}]
}
}
If you want to subscribe to specific events only, for example if you only want to subscribe to JackpotUpdateEvents, you could send the following request:
{
"SubscribeRequest": {
"events": [{
"source": "thrillpots",
"event_type": "JackpotUpdate"
}]
}
}
Event Types
The following events are available to be subscribe to for ThrillPots:
Event | Description |
---|---|
JackpotUpdate | These events provide periodic updates for all active jackpots |
OptInEvent | These events provide updates on the connected player's opt-in status |
WinEvent | These events provide win notifications (not specifically for the connected player) |
RaffleWinEvent | These events provide win notifications for raffle jackpot wins |
JackpotUpdate
JackpotUpdate
events are sent periodically to keep your application informed of the latest jackpot values.
An example JackpotUpdate
event could look like this:
{
"msg_type": "Event",
"source": "thrillpots",
"msg_name": "JackpotUpdate",
"operator_id": "thrilltech",
"brand_id": "brand1",
"player_id": null,
"data": {
"id": "f689317d-81c8-4395-b689-10ce6f88089e",
"currency": "EUR",
"pots": [
{
"id": "minor",
"is_progressive": true,
"current_value": 10.0
},
{
"id": "major",
"is_progressive": true,
"current_value": 100.21749999999994
},
{
"id": "mega",
"is_progressive": true,
"current_value": 1000.045
}
],
"allowed_brands": [
"thrilltech:brand1",
"thrilltech:brand2",
],
"allowed_sources": [],
"status": "Active",
"last_updated": 1715154276442
},
"timestamp": 1715191298453
}
OptInEvent
When a player opts-in or opts-out of a jackpot, an event will be sent to that player's WebSocket connection. An structure of the data
for an OptInEvent looks like this:
{
"instance_id": String,
"player_id": String,
"player_brand_id": String,
"preferred_contribution_value": Number,
"opted_in": Boolean,
"last_updated": Number,
}
WinEvent
When a Jackpot is won, the ThrillPots system publishes a WinEvent
which contains the details of the win. This message is sent to all connections that are subscribed to the receive the event. The structure of the data
portion of the Event message looks like this:
{
"brand_id": String,
"player_id": String,
"source_id": Option<String>,
"instance_id": String,
"jackpot_name": String,
"jackpot_currency": String,
"timestamp": u64,
"win_pot_id": String,
"win_amount": Number,
"currency_multipliers": {
"brand_id": String,
"base_currency": String,
"multipliers": {
"EUR": Number,
"GBP": Number,
"ZAR": Number,
...
"NZD": Number,
"SEK": Number
}
}
"win_withheld": bool,
"community_winners": null | [
{
"player_id": String,
"brand_id": String,
"currency": String,
"win_amount": Number
}
],
"games_in_jackpot": Vec<String>,
"seed": Decimal
}
RaffleWinEvent
When a Raffle Jackpot resolves and winners are determines, a RaffleWinEvent
which contains the details of the wins will be sent. The message is sent to all connections that are subscribed to receive the event. The structure of the data
portion of the Event message looks like this:
{
"brand_id": String,
"instance_id": String,
"jackpot_name": String,
"jackpot_currency": String,
"currency_multipliers": {
"brand_id": String,
"base_currency": String,
"multipliers": {
"EUR": Number,
"GBP": Number,
"ZAR": Number,
...
"NZD": Number,
"SEK": Number
}
}
"timestamp": Number,
"winners": [
{
"player_id": String,
"brand_id": String,
"currency": String,
"win_amount": Number
}
],
"win_withheld": bool
}
ThrillConnect: ThrillPots Requests
You can use the authenticated WebSocket connection to send requests that are relevant to the authenticated player.
Opt-In/Out Request
In order to opt a player into or out of a jackpot, you use the PlayerOptInRequest
message. This allows you to send not only standard opt-in / opt-out requests, but also to specify the contribution value that the player wishes to opt-in with.
Example: Opting a player in with the default contribution value
{
"PlayerOptInRequest": {
"instance_id": "209cc142-ccb2-4e28-a763-0a031b560d74",
"player_id": "player_id_token_00001",
"brand_id": "thrilltech:brand1",
"player_country": "MT",
"opt_in": true
}
}
Example: Opting a player in with a specific contribution value (0.30)
{
"PlayerOptInRequest": {
"instance_id": "209cc142-ccb2-4e28-a763-0a031b560d74",
"player_id": "player_id_token_00001",
"brand_id": "thrilltech:brand1",
"player_country": "MT",
"opt_in": true,
"contribution_value": 0.3
}
}
Example: Opting a player out of a jackpot
{
"PlayerOptInRequest": {
"instance_id": "209cc142-ccb2-4e28-a763-0a031b560d74",
"player_id": "player_id_token_00001",
"brand_id": "thrilltech:brand1",
"player_country": "MT",
"opt_in": false
}
}
If the opt-in or opt-out request was successful, you will receive an OptInEvent
Retrieving a player's raffle tickets for a specific instance
To retrieve a player's raffle ticket count for a specific Raffle Jackpot, send the PlayerRaffleTicketsRequest
message:
{
"PlayerRaffleTicketsRequest": {
"player_id": "player_00001",
"instance_id": "f0dee1ae-6231-458a-ad6d-4dc0c941e5c3",
"brand_id": "thrilltech:brand1"
}
}
If the request was valid, you will receive a PlayerRaffleTicketResponse
message:
{
"msg_type": "Message",
"source": "thrillpots",
"msg_name": "PlayerRaffleTicketResponse",
"operator_id": "thrilltech",
"brand_id": "brand1",
"player_id": "player_00001",
"data": {
"instance_id": "f0dee1ae-6231-458a-ad6d-4dc0c941e5c3",
"ticket_count": 8
"timestamp_start": 134857982371,
"timestamp_end": 14384723487,
},
"timestamp": 1715191298453
}
Retrieving all of a player's raffle tickets for active raffles
To retrieve all the raffle tickets for all active raffles for a player (in other words, not specific to a particular raffle), you can use a modified version of the above PlayerRaffleTicketsRequest
request (omitting the instance_id
on the request):
{
"PlayerRaffleTicketsRequest": {
"player_id": "player_00001",
"brand_id": "thrilltech:brand1"
}
}
If the player has earned any raffle tickets on any active raffles, the response will be a PlayerRaffleTicketListResponse
and will look something like this:
{
"msg_type": "Message",
"source": "thrillpots",
"msg_name": "PlayerRaffleTicketListResponse",
"operator_id": "thrilltech",
"brand_id": "brand1",
"player_id": "player_00001",
"data": {
"instance_tickets": [
{
"instance_id": "raffle_instance_a_id",
"ticket_count": 8
"timestamp_start": 134857982371,
"timestamp_end": 14384723487,
},
{
"instance_id": "raffle_instance_b_id",
"ticket_count": 3
"timestamp_start": 134857982371,
"timestamp_end": 14384723487,
},
]
},
"timestamp": 1715191298453
}
In the case that a player has not earned any raffle tickets for active raffles, the list will be empty. For example:
{
"msg_type": "Message",
"source": "thrillpots",
"msg_name": "PlayerRaffleTicketListResponse",
"operator_id": "thrilltech",
"brand_id": "brand1",
"player_id": "player_01010",
"data": {
"instance_tickets": []
},
"timestamp": 1715191298453
}
ThrillGate Service
ThrillGate is the service used to integrate with an operator's wallet and bonus APIs. It supports both Provider-to-Operator and Operator-to-Provider integration models, meaning that either ThrillTech can integrate to an operator's APIs or the operator can integrate to ThrillTech's "Standard" integration API.
At its core, ThrillGate provides a standard approach to authenticating player session tokens, performing transactions (both single and batches of transaction) as well as transaction cancellation mechanics.
Standard Wallet API
When doing an Operator-to-Provider integration, ThrillGate provides a definition of an API that should be exposed by the operator wallet. This definition is called the "Standard Wallet API" and supports all the functionality that ThrillTech services require from an integration with the operator platform.
Security
The Standard Wallet API uses HMAC to secure its payloads and allow the operator system to verify that the request has been sent from the expected ThrillGate source service.
Integrating
Refer to the product specific section(s) on integrating ThrillGate's Standard Wallet API with your platform.
Configuring Wallet Error Behaviour
NOTE: Self-Hosted customers have the ability to define these conditions themselves within ThrillGate. If you are a SaaS customer, you will need to request any specific rules that you wish you to have via your Account Manager
It is possible to configure the way ThrillGate reacts to specific wallet errors.
The standard wallet error structure is defined as:
{
"code": String,
"message": String
}
Therefore, if your wallet need to respond with a 403
error (for example), the response would be:
HTTP Error Code: 403
Body:
{
"code": "FORBIDDEN",
"message": "",
}
Now, if you wanted to configure ThrillGate to never retry when your wallet returns a 403
error, you could add the following sub-document to your wallet's config
field:
{
...
"config": {
"error_response_rules": {
"403:FORBIDDEN": {
"must_retry": false
}
}
}
}
From this example, you can see that you can also specialise specific errors based on their code
value in the error response.
In other words, you could create different rules for handling a 400
error with code
set to INVALID_STRUCTURE
and separate rules for 400
with code set to INVALID_PROPERTY_VALUE
.
This type of control can be useful if your wallet has specific requirements for retry or cancellation handling from ThrillGate.
The error_response_rules
object structure is defined as:
{
"HTTP_ERROR_CODE:ERROR_CODE_VALUE": {
"must_retry": Boolean,
"must_cancel": Boolean,
}
}
Both must_retry
and must_cancel
are optional values and default to true
if not set.
ThrillOffice Overview
The highlight of our September release is the new ThrillOffice service. A complementary update of Thrill-ID brings the required system definition and default service credentials for ThrillOffice.
Release Notes - September 2024
ThrillOffice
September brings big updates for our BackOffice! Along with lots of new frontend features, it comes with its own service. This service will take responsibility of all the reporting functionallity, currently exposed on ThrillPots. This way new BackOffice features will not be tied with upgrades on the core service and will come more frequently and easier to digest. ThrillOffice service will also provide historical data over instances, various stats and much more data to analyze and give insight on Jackpots performance.
New Features
Dashboard view
Dashboard provides a quick overview over brands performance. It introduces several widgets ( with more coming up soon):
- Total Contributions
- Total Winners
- Total opted in players
- Total GGR
- Bets distribution
- Top Contributors
- Top Wins
- Top Net Contributors
All widgets use derived timeseries data which initially will only show all-time totals and in a month time will enable more precise time frame selection.
Raffles
Raffles view is specialized instances view that targets raffles. It provides all relevant details for a Raffle Jackpot. Allows for precise filtering on brand and/or status. Expanding a Raffle instance row will display details on prizes and schedule.
Raffle Winners
Raffle Winners view is a specialized winners view for Raffles. It can be accessed by selecting Winners in Raffle instance's context menu.
Liability Report
Liability report view provides an overview of each Jackpot instances month-to-month liability. Like other reporting views it allows for targeting a brand, single instance or precise time frame.
Improved Filtering
Filters slider now includes an improved time selector that provides shortcuts for frequently used time frames.
Cross brand reporting
All reporting views now allow viewing entries across all available brands.
ThrillPots Overview
Welcome to the ThrillPots Integration Guide.
ThrillPots is an advanced standalone Jackpot Platform that allows casinos to offer their players jackpots over "everything". Be it offering a sitewide jackpot across games from various providers, to a seasonal Raffle jackpot for the 12 days of Christmas or even a Bad Beat jackpot for your poker players, ThrillPots can do it all (and more).
The goal of this guide is to make integrating with ThrillPots as painless as possible by providing you, the technical reader, with all the information you need and taking you step by step through a standard integration process.
Release Notes - August 2024
General
- Improvements to the OpenAPI Documentation continue to be made and this release has focused on documentation accuracy on the Standard Wallet API protocol, ThrillConnect and ThrillPots Gateway. This is an ongoing effort.
New Features
ThrillPots
-
Recurring Raffles
- In previous releases, raffles were limited to being once-off scheduled jackpots. In this release, we have extended the scheduling capabilities of the system to allow granular control of jackpot and raffle schedules.
- More information about scheduling can be found here
- In previous releases, raffles were limited to being once-off scheduled jackpots. In this release, we have extended the scheduling capabilities of the system to allow granular control of jackpot and raffle schedules.
-
Raffle Ticket Enhancements
- As of this release, raffle tickets can be configured based on a player's
base_wager
orcontribution
. Previous releases only supported ticket costs based oncontribution
. - It is now possible to retrieve all of a player's raffle tickets for all active raffles (instead of retrieving them one raffle instance at a time).
- ThrillPots Gateway:
GET /jackpots/instances/raffle/tickets/brand/:brand_id/:player_id
- ThrillPots Gateway:
- As of this release, raffle tickets can be configured based on a player's
-
Advanced Scheduling
- As mentioned in the Recurring Raffles feature above, we have introduced a more advanced scheduling subsystem to the platform.
- In ThrillPots, schedules are bound to a Jackpot Instance and a brand
-
Seed Boosts
- The seed boosts feature allows operators to add additional funds to a Jackpot which will act as additional seed buffers when a jackpot is won.
- Seed Boosts can be applied to specific pots within a Jackpot. For example, if you wished to add a Seed Boost to your top tier only, you could do so.
Changes/Improvements
ThrillPots
-
Async Contribution Errors now carry metadata
- For integrations that make use of asynchronous contributions, you may have noticed that the
metadata
supplied on the contribution call was not propogated on errors reported to the webhook. - This issue has now been addressed and the webhook will receive the original metadata on all errors under the
metadata
field.
- For integrations that make use of asynchronous contributions, you may have noticed that the
-
JackpotEventUpdate
event changes- Added the following new fields to the event:
jackpot_type
- Indicates where the instance is aJackpot
or aRaffle
(these are the two valid values for this field)timestamp_start
- If the instance has a schedule, this field will contain the UTC timestamp for the starting time of the active jackpot instancetimestamp_end
- If the instance has a schedule and an end time for the instance, this field will contain the UTC timestamp for the end
- An example of the new structure looks like this:
{ "event_type": "JackpotUpdateEvent", "data": { "id": "ab775921-0743-47d4-8ad2-cd60aae27b39", "jackpot_type": "Raffle", "currency": "EUR", "pots": [ { "id": "main", "is_progressive": false, "current_value": 100.0 } ], "allowed_brands": [ "thrilltech:brand1", "thrilltech:brand2", "thrilltech:my-new-brand" ], "allowed_sources": [ "raffle-test" ], "status": "Active", "timestamp_start": 1728604800000, "timestamp_end": 1728691199000, "last_updated": 1728604800000 } }
- Resolve Raffles not actively updating to Active state based on scheduling
- Added the following new fields to the event:
-
Zero value contributions are allowed
- Up until now, Jackpot Templates did not allow contribution values to be specified as ZERO.
- As of this release, this restriction as been lifted (with certain caveats - explained below)
- Reasons to allow zero-value contributions:
- Promotional Jackpots: Promotional jackpots should allow zero value contributions if they are non-progressive and/or do not have value based tipping points
- Caveats:
- Zero value contributions can only be made to jackpots that are fully operator funded AND have all their pots defined as probability or time based tipping points.
- For zero value contributions, there is no RTP to be calculated for wins
-
WinEvent changes
- In previous versions, the
WinEvent
was only broadcast to players of the brand on which the win occurred. In this release, theWinEvent
is also broadcast to all brands that are participating in the jackpot.
- In previous versions, the
-
Improved Handling for Limited Jackpot Tiers
- We have improved the handling of limited jackpot tiers. Limited Jackpot Tiers are tiers that are configured to only drop a certain amount of times. With this release, if the last available tier of a jackpot is a limited tier and the drop limit has been reached, the jackpot itself will automatically end (
status
==Ended
) and the frontend will stop receivingJackpotUpdateEvents
for the jackpot.
- We have improved the handling of limited jackpot tiers. Limited Jackpot Tiers are tiers that are configured to only drop a certain amount of times. With this release, if the last available tier of a jackpot is a limited tier and the drop limit has been reached, the jackpot itself will automatically end (
ThrillConnect
- Updated payload for Get Instance By Source endpoint
- Affected endpoint:
GET /v1/thrillpots/instances/source/:source_id/brand/:brand_id
- The response now contains three additional fields:
status
- The status of the instancetimestamp_start
- The UTC timestamp containing when the jackpot starts/startedtimestamp_end
- The UTC timestamp containing when the jackpot will end
- These additions allow frontends to:
- determine whether a jackpot is active for contributions
- if
status
==Active
, the jackpot is active within the schedule - if
status
==Pending
, the jackpot is scheduled to start at a future time
- if
- determine if a raffle is currently active or not
- if
status
==Active
, the raffle is active and accepting contributions - if
status
==Pending
, the raffle is scheduled to start at a future time (timestamp_start
).
- if
- determine whether a jackpot is active for contributions
- Affected endpoint: