Operator PAM Integration¶
At the heart of the Player API flow is the PAM integration. The PAM integration serves as an interface between Gamnify and the operator's wallet, identity and accounts concerns. Diagrams outlining this can be found in the Process Diagrams section of the documentation.
To make the integration process easier, a mock PAM integration has been made available via swagger and is accessible here. The Endpoints outlined in the MockIntegration section will need to be integrated.
Please note that the same PAM integration can be re-used for any of the Gamnify's product lines.
IMPORTANT: It is crucial that the operator implements hash checks as described here. Failure to do so can result in an unauthorized person crediting their own wallets.
The below endpoints will need to be available on the Operator's PAM API for transactions to be effected successfully. Every payload has a standardized payload with fields:
- ResponseCode: The response from the operator's PAM
- Message: A free-text message, used especially in case of errors.
- Data: The payload as a json object.
The operator PAM integration must be idempotent against the PlatformTxId property sent in the request payload.
/v1/integration/wallet/transaction¶
Verb: Post
This is used for all debit and credit calls, together with reversals of transactions. Please note that this endpoint assumes idempotency based on the Gamnify's internal transaction Id.
Request Parameters¶
| Type | Name | Format | Description |
|---|---|---|---|
| header | X-AUTH-REQUEST-HASH-BYPASS | boolean | Set this value to 'true' to bypass the authentication validation. |
| header | X-AUTH-OPERATOR-ID | integer | The operator id of the user making the request. |
| header | X-AUTH-REQUEST-HASH | string | The hash of the request. |
Request Payload¶
| Name | Format | Description |
|---|---|---|
| platformTxId | string (uuid) | A unique id for the transaction on the Gamnify's Platform side. |
| operatorId | number | ID representing the operator configuration. Should be used in multi-configuration scenarios. |
| reversedPlatformTxId | string (uuid) | In case of reversals, this is the Gamnify's Platform id of the transaction that is being reversed. |
| gameRoundData.id | string (uuid) | The round id. This is a unique identifier for the round and is used to track the round through its lifecycle. The gameRound is a nullable field which may not be sent in cases where a transaction is not attributed to a Game Round. At the time of writing, such a use case is not yet implemented, however future features such as promotional mechanics would leverage this behavior. |
| gameRoundData.activityCode | string | This is the code of the activity that initiated the transaction and is usually a player friendly code (e.g.: Ticke Code) |
| gameRoundData.walletStakeAmount.gross | number | The gross stake amount in wallet currency. |
| gameRoundData.walletStakeAmount.tax | number | The taxed stake amount in wallet currency. |
| gameRoundData.walletWonAmount.gross | number | The gross won amount in wallet currency. |
| gameRoundData.walletWonAmount.tax | number | The taxed won amount in wallet currency. |
| gameRoundData.wonMultiplier | number | The multiplier amount that the player has won. |
| gameRoundData.placedDate | string (date-time) | The date the bet was placed. All date times are in UTC. |
| gameRoundData.settlementDate | string (date-time) | The date the round was settled. This field is nullable in case the round is not yet settled. |
| productId | number | The Gamnify's internal Product Id for this round. The implementor is not obliged to store this field anywhere, but might be useful for reporting purposes. |
| verifyPlayerToken | boolean | Flag used to tell the operator whether the operator should validate the token against its expiry. In case of bet placement, this will be set to true (as the originator of the transaction is the user). In case of settlements, this will be set to false (as the originator of the transaction is the settlement server, who doesn't have a player token). |
| playerToken | string | The session token of the user that the transaction is for. The PAM integration will always send the original playerToken the session was initiated with. The operator should always check is the playerToken EXISTS but only validate it's not expired when validatePlayerToken = true |
| operatorPlayerId | string | The user identifier on the operator's side the transaction is for. It is the operator responsibility to ensure that the session token belongs to this user. |
| walletType | string | The wallet type for the transaction. |
| transactionType | string | The transaction type for this transaction. Please note that transaction amounts are always positive and depending on the transaction type, the wallet needs to credit or debit accounts (Credit and DebitReversal will credit the player's account, whilst Debit and CreditReversal will debit the player's account. |
| description | string | A short description of the transaction. This may be used to supply more information about the transaction. |
| createdTimeUtc | string (date-time) | The creation time of the transaction. |
| amount.walletCurrencyIsoCode | string | The Currency ISO code of the wallet amount. This wallet is expected to exist on the operator side as this is the real currency we will be transacting in. |
| amount.walletAmount | number | The amount of the transaction in the wallet's currency. We assume here that the amount is always positive and the wallet will handle the sign of the transaction according to the transaction type. |
| amount.anchorCurrencyIsoCode | string | The currency for the secondary currency. If the operator platform does not support dual currencies, this value can be safely ignored, as this is just a representational value. Also, this currency is passed over solely to help the operator understand the amount seen by the player in the traditional currency selected by them. |
| amount.anchorAmount | number | The amount of money displayed to the player, in the anchor currency. This value is just representational and should never be taken as a financially important value. Always use the WalletAmount to understand how much money to credit/debit to/from the player's account. |
| amount.inputInAnchorCurrency | boolean | This flag is passed through to the PAM for informational purposes only, mainly to understand the player's preference at the time of round creation. |
Reponse Payload¶
| Type | Name | Format | Description |
|---|---|---|---|
| body | message | string | A message describe the response. Mostly useful in case of errors. |
| body | data.operatorTxId | string | The transaction ID generated by the operator. |
| body | data.walletAmount | number | The amount of the transaction in the wallet's currency. This will represent the gross amount credited or debited on the player's wallet. |
| body | data.walletBalanceAfterTx | number | The balance of the player after the transaction is effected. |
| body | data.anchorToWalletExchangeRate | number | The conversion rate used. Can be kept as 1 if the anchor and wallet currencies are identical |
| body | data.walletId | string | An optional parameter representing the wallet id on the operator's side. |
| body | data.creationTime | string (date-time) | The time at which the transaction was created on the operator's side. |
| body | responseCode | string | The response code. |
v1/identity/player/{playerToken}¶
Verb: GET
Get the user information provided the token for the user. This is called just once per session, and is not expected to be called often.
Request Parameters¶
| Type | Name | Format | Description |
|---|---|---|---|
| path | playerToken | string | Operator generated user token used by Gamnify to authenticate the request agains the Operator PAM API. |
| header | X-AUTH-REQUEST-HASH-BYPASS | boolean | Set this value to 'true' to bypass the authentication validation. |
| header | X-AUTH-OPERATOR-ID | integer | The operator id of the user making the request. |
| header | X-AUTH-REQUEST-HASH | string | The hash of the request. |
Response Payload¶
| Name | Format | Description |
|---|---|---|
| message | string | A message describe the response. Mostly useful in case of errors. |
| data.isTest | boolean | Flags user as a test user. Should only be used for internal users. Test users are excluded from invoicing |
| data.isEnabled | boolean | Flag storing whether the player is enabled or not. |
| data.username | string | User's username. Mostly used for social proofing. |
| data.operatorPlayerId | string | The external user id that the operator uses to identify the user. Must be unique per operator. |
| data.parentOperatorPlayerId | string | The parent id of the user. This is used to link the user to a parent user especially for retail. |
| data.extraDetails.additionalProp | string | An optional dictionary of extra details. Please note that 'additionalProp' is just an example. |
| responseCode | string | The response code. |
¶
Infrastructure & Performance¶
It is expected that the operator offers two installations for the PAM integration: one for testing and one for production. The operator is also expected to respect the above endpoint names, failure of which will result in the integration to malfunction.
Once the development is done, the Gamnify team will run background checks on the integration to make sure it is functioning properly. For this reason the operator will be requested to share the following users in a testing environment:
- 2 player accounts with funds (ideally, an appreciable amount of test funds so that tests can be made without any issues and without disturbing the operator's engineering teams
- An account with zero balance
- An inactive account (optional)
- A blocked account (optional)
- A self-excluded account (optional)
Whilst there is no expectation on performance on the test environment, we recommend that the 95th percentile of the calls be way below 500ms, ideally in the ranges between 50 - 150ms. Since every client gets their own infrastructure, please discuss with the Gamnify team the best geographic location to make the latency between the systems as low as possible.