# Payouts.com x inabit - Integration Guide

## Overview

This guide outlines the end-to-end integration flow between **Pragmatic Solutions** and **inabit**, enabling seamless crypto payment operations for gaming operators through a jointly managed setup.

The integration is designed to provide operators with a compliant, secure, and scalable infrastructure for managing crypto transactions and treasury operations using inabit's infrastructure, paired with Pragmatic's front-end gaming platform and back-office systems.

Operators onboard through inabit and gain access to a streamlined API-based system where **Pragmatic Solutions acts as the technical integrator**, managing API credentials, infrastructure components (like the inabit Approver Docker), and widget configurations on behalf of the operator.

#### Key Highlights of the Integration:

* **Dual API setup** under the operator’s inabit account to separate admin and signing roles.
* **Flexible deployment** of inabit’s Approver Docker by either Pragmatic or the operator.
* **Mobile app pairing flow** to securely authorize API access and infrastructure linkage.
* **Customizable widgets** set up and maintained by Pragmatic to reflect operator preferences (coins, sweep frequency, expiry, etc.).
* **Live data sync** via webhook and pull APIs for real-time balance updates and transaction visibility.

This integration ensures that the operator benefits from **full automation, visibility, and control**, while Pragmatic handles the complexity of configuration and ongoing updates, offering a plug-and-play experience for crypto enablement in gaming.

### API Introduction

Our API is based on **GraphQL**, allowing clients to query exactly the data they need with maximum flexibility and efficiency. This enables streamlined integration and reduces over-fetching or under-fetching of data.

{% hint style="info" %}
If you'd like to learn more, you're welcome to refer [here](/api-reference/introduction-to-graphql/what-is-graphql.md) for more information.
{% endhint %}

### Additional Reference

We highly advise taking a look at the following pages as you start developing:

* [API Login Access / Authentication](/api-reference/develop-with-inabit-api/getting-started/authentication.md)
* [Remote & Automatic Approvals (Docker Configuration)](broken://spaces/fUjQQn0pomEUaPpV3fnI/pages/ccXJuwRwg2gczKSBaHay)
* [Automate Signing Transactions](broken://spaces/fUjQQn0pomEUaPpV3fnI/pages/0VYX2RSRtyBlvXJfXQqb)
* [Supported Blockchains & Assets](/what-we-support/blockchains.md)

## Technical Architecture: Complete Money Flow

PICTURE HERE

### Money Flow Explained

#### 1. Operator Sends Fiat to Payouts.com

Payouts.com receives fiat from the operator.

#### 2. Payouts.com Sends Crypto to Operator's Wallet

Using inabit's API, Payouts.com initiates a transfer from its **Master Wallet** to the **operator's associated inabit crypto wallet**.

The Operator’s inabit wallet is used as an intermediate hop, this way funds can be routed through it for accounting purposes.

#### 3. Payouts are Sent to Customers

Payouts.com initiates payouts (withdrawals) from the operator's associated inabit wallet on behalf of the operator, to the end-customer's crypto wallet.

#### Now that the flow is clear, let's review the implementation process step by step! :sparkles:

#### 4. Rebalancing

Per need basis, Payouts.com can use inabit’s **Crypto Swap** feature to rebalance between USDT, USDC,  BTC or any other cryptocurrencies within their operational organization.

## Step By Step: Implementation

### Step 1: Payouts.com onboards to inabit

The first step for this integration is for payouts.com to onboard to inabit:

* Please visit the onboarding URL and create an account here:\
  <https://use.inabit.com/create_account>
* On the **Plan** **Selection** screen, select **Enterprise**.\
  This ensures that the account is granted access to all advanced platform features and API capabilities required for the integration.
* Complete **Devices Pairing**:\
  As the final onboarding step, the Operator must pair their mobile device with the inabit platform. This process is critical for enabling **self-custody**—meaning the Operator remains the sole custodian of their customers' funds.\
  The paired device acts as a cryptographic key manager and approval layer, ensuring secure signing of all transactions and operations on the platform.

{% hint style="info" %}
[How to Perform Device Pairing](/guides/devices-pairing.md)
{% endhint %}

### Step 2: inabit Enables API Access

Upon payouts.com's onboarding to inabit, the process begins with registration and device pairing using the inabit mobile app.

Once the account owner is registered and paired:

* **inabit generates two API users** under the account:
  * **API Signer**
  * **API Admin**

The **Payouts.com Account Owner** user then receives an approval request on their **inabit mobile app** and must approve the newly created API users.

After the API users are approved:

* **inabit securely shares the API credentials with Payouts.com**, enabling the next steps in the onboarding process. *(through a secured channel of choice like Slack/Telegram/etc.)*

Now Payouts.com can authenticate to inabit's GraphQL API and generate access tokens!

### Step 3: Implement Approvals Docker App

In order to automate signing transactions, Payouts.com needs to install inabit's Remote Approver App and pair the API Signer user.

Please refer to the full guide explaining the Docker's setup and configuration here:

> ### [Remote Approver App Setup](https://docs.inabit.com/api-reference/remote-approver-app/setup-and-configuration)

Once the docker is up and running, the pairing process will commence as follows:

1. The docker issues a Pairing Code in the docker logs.

```bash
{
  level: 'info',
  message: 'Approver needs to be paired, starts a pairing process...',
  metadata: { timestamp: '2024-02-21T08:54:16.071Z' },
  timestamp: '2024-02-21T08:54:16.071Z'
}
{
  level: 'info',
  message: 'Getting a pairing token.',
  metadata: { timestamp: '2024-02-21T08:54:16.075Z' },
  timestamp: '2024-02-21T08:54:16.075Z'
}
{
  level: 'info',
  message: 'Getting a pairing code',
  metadata: { timestamp: '2024-02-21T08:54:17.555Z' },
  timestamp: '2024-02-21T08:54:17.555Z'
}
{
  level: 'info',
  message: 'Pairing code: c754ce6d209dcc1b6f2312903ef31f0ac297b63e5dead29a6b877ecad8c77ada',
  metadata: { timestamp: '2024-02-21T08:54:17.560Z' },
  timestamp: '2024-02-21T08:54:17.560Z'
}
```

2. The docker proceeds to send an approval request to the owner to authorize the approver app (just like any other user).
3. Payouts.com will then send the **Pairing Code** from the docker logs to the account owner through a secure channel of choice.
4. Owner **inserts the pairing code on their inabit mobile app** to complete the pairing process.\
   ![](/files/3PD57eCwshXN6oingv5C)

Once all the above is done, the pairing is complete. :heavy\_check\_mark:

To complete the pairing process:

* The account owner **enters a pairing code** into their inabit mobile app that is received from inabit (via direct communication).

Now that pairing is done:

* **Payouts.com opens a Master Wallet** with the required blockchains.\
  (This is an inabit wallet used as a central aggregator for the crypto funds received)

### Step 4: Payouts.com Creates a Master Wallet

In this step, Payouts.com proceeds to create an inabit wallet under the name "Master Wallet".

**What is a Master Wallet?**

The Master Wallet serves as the **central aggregator** for all crypto transactions and funds flow. It is a secure, self-custody wallet fully accessible through the interface.

**Supported Blockchains**

During wallet creation, Payouts.com selects the required **blockchains** (e.g., Ethereum, Tron, Polygon). Each blockchain comes with its own address and supports its respective tokens (e.g., USDT on Tron, ETH on Ethereum).

**How to Create a Master Wallet?**

Creating one can be done via the interface or API, which ever preferred.

**For UI**, Head over to the "Wallets page:

* Click on "Add New" button.
* Select "inabit Wallet".
* Name the wallet "Master Wallet"
* Select the supported blockchains required from the list shown.
* Wallet Created!

**For API**, use the `CreateWalletWithInabit` mutation allows API admins to create a new inabit wallet (that is accessible in the platform's interface, unlike API wallets) with a designated address for a given asset & blockchain.

> Remember to authenticate to call our GraphQL API using an access token (bearer) with your **API** **Admin** credentials. (If you're not sure how, refer to [Authentication](https://docs.inabit.com/api-reference/develop-with-inabit-api/getting-started/authentication))

<pre class="language-graphql"><code class="lang-graphql">mutation CreateWalletWithInabit($data: WalletCreateWithInabitInput!) {
<strong>  createWalletWithInabit(data: $data) {
</strong>    id
    name
  }
}
</code></pre>

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |

#### **Body (**<mark style="color:orange;">WalletCreateWithInabitInput</mark> object)

| Name                                             | Type   | Description                      |
| ------------------------------------------------ | ------ | -------------------------------- |
| name<mark style="color:red;">\*</mark>           | string | Name of the wallet               |
| organizationId<mark style="color:red;">\*</mark> | string | ID of the organization in inabit |

Example body:

```graphql
{
  "data": {
    "name": "Master Wallet",
    "organization": {
      "id": "clu6oj0kg0004r4ub98guo82j"
    }
  }
}
```

#### Response

Return values:

| Name | Type   | Description         |
| ---- | ------ | ------------------- |
| id   | String | Created Wallet ID   |
| name | String | Created Wallet Name |

{% tabs %}
{% tab title="🟢 Success" %}

```graphql
{
  "data": {
    "createWalletWithInabit": {
      "id": "clvw5p0oj000er47qhe3atv9d",
      "name": "My Inabit Wallet",
    }
  }
}
```

{% endtab %}

{% tab title="🔴 Failure - Invalid Request" %}

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

{% endtab %}
{% endtabs %}

In the mutation's response, you will receive the created API wallet ID including the associated blockchain address.

#### Try it out!

{% embed url="<https://studio.apollographql.com/sandbox/explorer?endpoint=https://api.inabit.app/graphql&explorerURLState=N4IgJg9gxgrgtgUwHYBcQC4RxighigSwiQAIBhAJwXwQHVcAbBhFWglACwEklcAjdgAoAJGHy50JekxaVqKOu268BKHgAccAQgCUJYAB1SJKFRrTmrJT35CxeSaPF7DxkiQJgj7970TeSAF8jQJAAGhAAN1wKAn5mAGcMEHCQdQgElAAzBgIAcw4UAHl1BAp8IiQAZVMCdTRMEECgA>" %}

### Step 5: Payouts.com Sends Crypto to The Master Wallet

In this step, Payouts.com funds the Master Wallet with an initial crypto amount (in the relevant blockchains that are required), to be able to fund operator's inabit wallets.

{% hint style="info" %}
This is a one time deposit to the master wallet to allow the wallet to become operational, before onramping occurs.
{% endhint %}

### Step 6: Payouts.com Transfers Crypto from Master Wallet to Operator's Wallet

asdasdsad

### Step 7: Payouts are Sent to Customers

Payouts.com initiates a payout (withdrawal) from the operator's associated inabit wallet on behalf of the operator, to the end-customer's crypto wallet.

Payouts.com can trigger a withdrawal using inabit’s APIs.\
\
**Creating a Withdrawal via API**

Initiate a mutation to create an assets transfer request to send for approval from the operator's inabit wallet.

```graphql
mutation CreateWithdrawal($data: WithdrawalCreateInput!) {
  createWithdrawal(data: $data) {
    id
  }
}
```

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |
|               |                    |

**Body (**<mark style="color:orange;">**WithdrawalCreateInput**</mark>**) object**

| Name                                                  | Type    | Description                                                  |
| ----------------------------------------------------- | ------- | ------------------------------------------------------------ |
| id<mark style="color:red;">\*</mark>                  | String  | Master Wallet ID                                             |
| id<mark style="color:red;">\*</mark> (financialAsset) | String  | Asset ID                                                     |
| address<mark style="color:red;">\*</mark>             | String  | Destination Address (To)                                     |
| amount<mark style="color:red;">\*</mark>              | Integer | Transfer amount                                              |
| id<mark style="color:red;">\*</mark> (blockchain)     | String  | Blockchain ID                                                |
| note                                                  | String  | Transaction Note                                             |
| priority                                              | String  | <p>Transaction Priority</p><p>(Slow, medium, fast, etc.)</p> |

\
Example body:

```graphql
{
	"data": {
		"wallet": {
			"id": "clol7o576002oaz011mmtnvru"
		},
		"financialAsset": {
			"id": "clefn78gv011olc6rcwtt0wel"
		},
		"address": "0x7582f3483116105e0b7845ac1a0df5eb0c8cd062",
		"amount": 5,
		"blockchain": {
			"id": "clefn78em00mslc6r3lzf3h5a"
		},
		"note": "",
		"priority": "Medium"
	}
}
```

### Response

Return values:

| Name | Type   | Description   |
| ---- | ------ | ------------- |
| id   | String | Withdrawal ID |

### Step 7: Rebalancing

asdasd

{% tabs %}
{% tab title="🟢 Success" %}

```graphql
{
	"data": {
		"createSwap": {
			"id": "clph3mik5000t8f01qqr0ol74",
			"amount": 0.0051,
			"fee": 0.0014,
		}
	}
}
```

{% endtab %}

{% tab title="🔴 Failure - Invalid Request" %}

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

{% endtab %}

{% tab title="Failure - Assets Pair not Supported" %}

```graphql
{
  "errors": [
    {
      "code": "OPERATION_FAILED",
      "message": "No InabitWalletSupportedPair found",
      "path": [
        "createInabitWalletSwap"
      ],
      "extensions": {
        "code": "OPERATION_FAILED",
        "message": "No InabitWalletSupportedPair found"
      }
    }
  ],
  "data": null
}
```

{% endtab %}
{% endtabs %}

### Deposit Management (Webhooks) :bell:

#### How Will Pragmatic Stay Up-to-Date on Incoming Deposits?

In the **iGaming industry**, it's common practice to **lock funds once a deposit transaction is detected on-chain**, even before it has been fully confirmed. This provides a better user experience by showing a successful deposit immediately—while still protecting the operator by making the funds **non-withdrawable** until sufficient blockchain confirmations are received.

inabit's system fully supports this flow: once a transaction is detected, it updates the widget with a pending confirmation status, allowing the platform to reflect the deposit in the UI while ensuring risk mitigation through backend-level enforcement of fund availability only after confirmation.

To keep Pragmatic in sync, **inabit sends webhook callbacks** for each deposit event and any change in deposit status, enabling real-time tracking of user payments and status-based logic within Pragmatic’s environment.

**List of potential Deposit Statuses:**

* **`Initiated`** – The deposit request has been created, but no blockchain deposit address has been assigned yet.
* **`Allocated`** – A unique blockchain address has been successfully generated and linked to the deposit.
* **`Undercharge`** – The customer deposited **less** than the expected amount, but the deposit window is still active, allowing them to complete the payment.
* **`UnderchargeExpired`** – The customer deposited less than the required amount, **and the payment window has expired**, meaning the transaction cannot be completed.
* **`Confirming`** – The full amount has been received, and the system is now waiting for the required number of blockchain confirmations to mark the deposit as successful.
* **`Unconfirmed`** – A deposit has been detected on the blockchain **but has not yet been included in a block** (only relevant for UTXO-based networks such as Bitcoin).
* **`Overcharge`** – The customer deposited **more** than the required amount. The deposit will still be processed, and the system may handle the excess according to predefined rules (e.g., ignore, credit, or refund).
* **`Expired`** – The customer did not complete the payment within the allowed time window, and the transaction is no longer valid.
* **`Completed`** – The required number of blockchain confirmations has been received, and the deposit is finalized successfully.

```json
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.inabit.com/internal-review.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
