Skip to content

Seamless wallet requests flow

Place-bet

graph TD
    %% Start Node
    Start([Place Bet request from user]) --> Proc[Bet processing in GR8 Platform]

    %% Main Decision
    Proc --> Logic{If bet ok?}

    %% Left Branch: Bet OK
    Logic -- Yes --> Credit[Request for credit money from user balance on clients platform]
    Credit --> CredOk{Successful response?}

    CredOk -- Yes --> Accepted1([Bet accepted])
    CredOk -- No --> Rollback[Rollback transaction]

    Rollback --> RollOk{Successful response?}
    RollOk -- Yes --> NotAccepted1([Bet is not accepted])
    RollOk -- No --> RetryQue[Rollback transaction request placed to the retry queue and will be retried later]

    %% Right Branch: Bet Not OK / Recovery
    Logic -- No --> GetTrans[Get transaction in case if service restart and bet was placed before]
    GetTrans --> TransExists{Transaction exists?}

    TransExists -- Yes --> Accepted2([Bet accepted])
    TransExists -- No --> NotAccepted2([Bet is not accepted])

    %% Styling to match original image
    style Accepted1 fill:#d4edda,stroke:#28a745
    style Accepted2 fill:#d4edda,stroke:#28a745
    style NotAccepted1 fill:#d4edda,stroke:#28a745
    style NotAccepted2 fill:#d4edda,stroke:#28a745
    style RetryQue fill:#f3e5f5,stroke:#9c27b0
    style Logic fill:#fff3e0,stroke:#ffa000
    style CredOk fill:#fff3e0,stroke:#ffa000
    style RollOk fill:#fff3e0,stroke:#ffa000
    style TransExists fill:#fff3e0,stroke:#ffa000

Danger

ATTENTION!
Get balance request will be always executed after EACH transaction request by default. If you want to disable it, please contact with AM/PM of GR8 TECH team

Wallet request example - place bet, withdrawal request transaction
{
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "withdrawal",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "bet",
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "10"
  }
}

Bet will be accepted in case of a successful response and there are no technical issues. In case of a technical issue, a rollback request could be sent and bet placement will be canceled. A rollback request example will be provided below.

Withdrawal success response transaction
{
  "balances": {
    "sport": {
      "main": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      },
      "sportsbook": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      }
    }
  },
  "alreadyProcessed": false,
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "withdrawal",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "bet",
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "10"
  }
}

In case of an unsuccessful response, the bet won't be accepted.

Withdrawal fail response transaction
{
  "error": {
    "code": "error.user.not-found",
    "message": "User with specified Id was not found",
    "origin": "{clientName}"
  },
  "alreadyProcessed": false
}

Wallet request example - place bet rollback

Warning

3rd party wallet must guarantee processing of rollback requests. We will retry each rollback every 5 minutes until the success or retry count reaches 100 (~retring during 8 hours). In the case when a rollback request can’t be applied, there could be a resynchronization between the client's wallet and bet state. The bet will be marked as broken on the GR8 Tech side and the operation can be retried manually by request to our team.

Info

Remote wallet is responsible for verifying if parent transaction (passed via context.parentId) exists. Expected remote wallet to return 400 status code with decline.parent.notfound error code in case no parent transaction found.

Rollback transaction request
{
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "rollback",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "sport rollback",
    "betId": "4494226fa9c24b978b975823e353616b",
    "parentId": "parentTransactionId"
  },
  "amountBreakdown": {
    "cash": "10"
  }
}

In case of success, we expect the next response.

Rollback success response
{
  "balances": {
    "sport": {
      "main": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      },
      "sportsbook": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      }
    }
  },
  "alreadyProcessed": false,
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "rollback",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "sport rollback",
    "betId": "4494226fa9c24b978b975823e353616b",
    "parentId": "parentId"
  },
  "amountBreakdown": {
    "cash": "10"
  }
}

In case of failure, we expect the next response.

Rollback error response
{
  "error": {
    "code": "decline.parent.notfound",
    "message": "ROLLBACK_NO_BET_FOUND - Transaction not found",
    "origin": "{clientName}"
  },
  "alreadyProcessed": false
}

"code": "decline.parent.notfound" - Parent transaction was not found

"code": "decline.parent.failed" - Parent transaction was found but it was failed


Wallet request example - get transaction before placement

In case of placement interruption and long processing (more than 30 seconds) for achieving consistency between the sportsbook and 3rd party wallet we can check if the transaction exists on 3rd party wallet. If the transaction exists we will accept it in our sportsbook. Otherwise, we will reject this bet.

Note

3rd party wallet must always return the correct state of the transaction.

Schema and example are provided upper in - get-transaction-by-id

Settle bet

%%{init: {'theme': 'base', 'themeVariables': {'lineColor': '#B0B0FF', 'arrowheadColor': '#B0B0FF'}} }%%
graph TD
    %% Start Node
    Start([Event settled in GR8 Platform]) --> Result[Settlement result determined]

    %% Settlement result
    Result --> Deposit[Request deposit transaction to Operator BE]
    Deposit --> DepOk{Successful response?}

    %% Success path
    DepOk -- Yes --> GetBal1[get-user-balance → Operator BE]
    GetBal1 --> Settled[Bet settled]

    %% Failure path
    DepOk -- No --> Retry[Transaction placed to retry queue]
    Retry --> RetryAttempt[Retry deposit transaction]
    RetryAttempt --> RetryOk{Successful response?}
    RetryOk -- Yes --> GetBal2[get-user-balance → Operator BE]
    GetBal2 --> Settled2[Bet settled]
    RetryOk -- No --> RetryAgain[Retry again until success or max retries reached]

    %% Styling
    style Settled fill:#d4edda,stroke:#28a745
    style Settled2 fill:#d4edda,stroke:#28a745
    style DepOk fill:#fff3e0,stroke:#ffa000
    style RetryOk fill:#fff3e0,stroke:#ffa000
    style Retry fill:#f3e5f5,stroke:#9c27b0
    style RetryAgain fill:#f3e5f5,stroke:#9c27b0

Wallet request example - settle

Each settlement result will trigger a deposit transaction to the wallet. Be careful, that this transaction can have amount=0 in case of lost settlement result.

Settlement results:

  • win
  • lose
  • return
  • techreturn
  • return025
  • return075
  • cashout
  • deadheat
Deposit settle transaction
{
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "deposit",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "settle",
    "betAmount": 10,
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "20" // Lose result - "cash": "0"
  }
}

In case of a successful response

deposit success response
{
  "balances": {
    "sport": {
      "main": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      },
      "sportsbook": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      }
    }
  },
  "alreadyProcessed": false,
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "deposit",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "settle",
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "20"
  }
}

In case of an unsuccessful wallet response, the settlement will fail

Deposit error response
{
  "error": {
    "code": "error.user.not-found",
    "message": "User with specified Id was not found",
    "origin": "{clientName}"
  },
  "alreadyProcessed": false
}

Resettle and cancel settlement

%%{init: {'theme': 'base', 'themeVariables': {'lineColor': '#B0B0FF', 'arrowheadColor': '#B0B0FF'}} }%%
graph TD
    %% Start Node
    Start([Resettlement or cancel settlement triggered]) --> Check[Determine transaction type based on amount change]

    %% Decision: deposit or withdrawal
    Check --> Direction{New amount > previous amount?}

    %% Deposit branch (new amount greater or equal)
    Direction -- "No (deposit)" --> DepReq[Request deposit transaction to Operator BE]
    DepReq --> DepOk{Successful response?}
    DepOk -- Yes --> GetBal1[get-user-balance → Operator BE]
    GetBal1 --> Resettled1([Bet resettled])
    DepOk -- No --> DepRetry[Transaction placed to retry queue]
    DepRetry --> DepRetryAttempt[Retry deposit transaction]
    DepRetryAttempt --> DepRetryOk{Successful response?}
    DepRetryOk -- Yes --> GetBal3[get-user-balance → Operator BE]
    GetBal3 --> Resettled3([Bet resettled])
    DepRetryOk -- No --> DepRetryAgain[Retry again until success or max retries reached]

    %% Withdrawal branch (new amount less)
    Direction -- "Yes (withdrawal)" --> WdReq[Request withdrawal transaction to Operator BE]
    WdReq --> WdOk{Successful response?}
    WdOk -- Yes --> GetBal2[get-user-balance → Operator BE]
    GetBal2 --> Resettled2([Bet resettled])
    WdOk -- No --> NotResettled([Bet stays in previous state])

    %% Styling
    style Resettled1 fill:#d4edda,stroke:#28a745
    style Resettled2 fill:#d4edda,stroke:#28a745
    style Resettled3 fill:#d4edda,stroke:#28a745
    style NotResettled fill:#d4edda,stroke:#28a745
    style Direction fill:#fff3e0,stroke:#ffa000
    style DepOk fill:#fff3e0,stroke:#ffa000
    style WdOk fill:#fff3e0,stroke:#ffa000
    style DepRetryOk fill:#fff3e0,stroke:#ffa000
    style DepRetry fill:#f3e5f5,stroke:#9c27b0
    style DepRetryAgain fill:#f3e5f5,stroke:#9c27b0

Wallet request example - withdrawal resettle

Withdrawal transaction is used for all transactions when the previous amount is less than the current one, hanging statuses:

win => lose/return/techreturn/return025/return075/deadheat

return => lose/return025/return075/deadheat

deadheat => lose/return/techreturn/return025/return075

Withdrawal resettle transaction
{
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "withdrawal",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "resettle",
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "10"
  }
}

In case of a successful response, the bet will be resettled, otherwise, resettlement will be unsuccessful and the bet will stay in the previous state

Withdrawal success response
{
  "balances": {
    "sport": {
      "main": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      },
      "sportsbook": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      }
    }
  },
  "alreadyProcessed": false,
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "withdrawal",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "10"
  }
}
Withdrawal error response
{
  "error": {
    "code": "error.user.not-found",
    "message": "User with specified Id was not found",
    "origin": "{clientName}"
  },
  "alreadyProcessed": false
}

Wallet request example - deposit resettle

Deposit transactions are used for all transactions when the previous amount is greater or equal to the current one, changing statuses:

lose => win/return/return075/return025/deadheat

return => win/techreturn/deadheat

return025/return075 => techreturn/return

deadheat => win/return/return075/return025

Deposit resettle transaction
{
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "deposit",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "resettle",
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "20" //Lose result - "cash": "0"
  }
}

In case of success response, the bet will be resettled, otherwise resettlement will be unsuccessful and bet will stay in previous state

Deposit success response
{
  "balances": {
    "sport": {
      "main": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      },
      "sportsbook": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      }
    }
  },
  "alreadyProcessed": false,
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "deposit",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "20"
  }
}
Deposit error response
{
  "error": {
    "code": "error.user.not-found",
    "message": "User with specified Id was not found",
    "origin": "{clientName}"
  },
  "alreadyProcessed": false
}

Wallet request example - cancel settle - withdrawal

Previous settlement result: win/lose/return/techreturn/return025/return075/cashout/deadheat

New settlement result: unknown

Withdrawal cancel settle transaction
{
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "withdrawal",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "cancelsettle",
    "betAmount": 10,
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "10" //if previous result is Lose - "cash": "0"
  }
}

In case of a successful response, the settlement will be canceled, otherwise, cancel settlement will be unsuccessful, and bet will stay in the previous state

Withdrawal success response
{
  "balances": {
    "sport": {
      "main": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      },
      "sportsbook": {
        "USD": {
          "cash": "100",
          "bonus": "0",
          "locked": "0"
        }
      }
    }
  },
  "alreadyProcessed": false,
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "withdrawal",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "10"
  }
}
withdrawal error response
{
  "error": {
    "code": "error.user.not-found",
    "message": "User with specified Id was not found",
    "origin": "{clientName}"
  },
  "alreadyProcessed": false
}

Partial settle bet

Wallet request example - settle

Each settlement result will trigger a deposit transaction to the wallet. Be careful, that this transaction have amount as part of full bet amount.

Partial settlement results:

  • cashout
Deposit settle transaction
{
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "deposit",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "partial settle", // new reason
    "betAmount": 10,
    "betId": "4494226fa9c24b978b975823e353616b",
  },
  "amountBreakdown": {
    "cash": "9" // it can be more or less than betAmount
  }
}

Partial resettle and cancel settlement

Wallet request example - withdrawal/deposit resettle (only for settled bets)

Previous settlement result: cashout

New settlement result: return

Withdrawal partial resettle transaction
{
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "withdrawal", // or "deposit"
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "partial resettle", // new reason
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "1"
  }
}

Wallet request example - partial cancel settle - withdrawal (only for unsettled bets)

Previous settlement result: cashout

New settlement result: unknown

Withdrawal cancel settle transaction
{
  "currency": "USD",
  "platform": "sport",
  "id": "id",
  "type": "withdrawal",
  "initiatedAt": "2021-01-20T00:00:00Z",
  "createdAt": "2021-01-20T00:00:00Z",
  "context": {
    "product": "sportsbook",
    "reason": "partial cancelsettle", // new reason
    "betAmount": 10,
    "betId": "4494226fa9c24b978b975823e353616b"
  },
  "amountBreakdown": {
    "cash": "9"
  }
}