Payment Service Providers
Guide describing how PSPs integrate with inabit’s our Terminal Gateway API
Overview
This guide describes the end-to-end integration between a PSP and inabit to power crypto payments for multiple merchants under a single PSP-owned account. The integration provides a compliant, secure, and scalable self-custodial setup using inabit’s infrastructure, paired with the PSP’s front-end and back-office systems.
Key Highlights
Single PSP account on inabit; each merchant is mapped to its own widget
Treasury owned by the PSP: automatic sweeping, crypto-to-crypto swaps, withdrawals, and off-ramping executed under PSP policy and compliance.
Remote Approver App (Approver Docker) hosted by the PSP or managed by inabit to enforce policy-based approvals.
Operational visibility via webhooks plus safety-net API polling for deposits/withdrawals, enabling accurate settlement and reconciliation per merchant.
This approach gives the PSP full operational control and compliance ownership while delivering fast merchant onboarding, reliable settlement, and transparent status updates—without requiring merchants to manage crypto infrastructure.
2. Architecture & Concepts
Before integrating, it is critical to understand the three main components of the inabit ecosystem:
A. Wallet Hierarchy
inabit utilizes a dual-wallet system to separate customer deposits from treasury operations:
API Wallets (Deposit Addresses): These are generated programmatically for every transaction or customer. They serve as the entry point for funds and automatically sweep received assets into your central treasury.
UI Wallets (Treasury & Operations): These are the permanent wallets managed via the Inabit Dashboard or Admin API (e.g., Master Wallet, Operational Wallet). They are used to aggregate funds, manage liquidity, and execute settlements.
Important: For the mandatory architecture regarding how to separate your Master Wallet (Cold/Treasury) from your Operational Wallet (Hot/Settlement), please refer to the [Wallet Structures Best Practices] guide.
B. The Approver (Security Layer)
inabit utilizes a "Remote Approver App" (Approver Docker) to enforce security policies.
Function: It cryptographically signs transactions based on your defined policies (e.g., "Auto-approve transfers under $10k").
Deployment: You can Self-Host (recommended for full control) or use inabit-Hosted (managed service).
C. API Structure
The integration uses a hybrid API approach:
GraphQL API: Used for backend operations (Withdrawals, Wallet Management, Reporting).
REST API (Terminal): Used for frontend payment intent creation and widget rendering.
3. API Credentials
Once onboarding is complete, inabit generates the following keys. (except for the widget API key, that is generated upon widget's creation) You must use the correct key for the specific task:
Which key do I use, and when?
Create/list UI wallets create withdrawals,view wallets, open new wallet, add coins
API Admin (GraphQL)
Platform-level ops & governance
At account opening - provided by inabit Support
Authorization: Bearer <API_ADMIN_TOKEN>
Org-wide Terminal reads (e.g., get all widgets, get all customers), org-scoped deposit lookups
Terminal Organization API Key (REST)
Organization-level Terminal access across widgets/customers
When Terminal is enabled - provided by inabit Support
Authorization: Bearer <TERMINAL_ORG_API_KEY>
Single-widget reads (e.g., get widget details, purchase and deposit statuses)
Terminal Widget API Key (REST)
Per-widget access; safer for widget-scoped services
During widget setup - shown on the widget implementation instructions page in the platform
Authorization: Bearer <TERMINAL_WIDGET_API_KEY>
Additional Reference
We highly advise taking a look at the following pages as you start developing:
API Login Access / Authentication
Remote & Automatic Approvals (Docker Configuration)
Automate Signing Transactions
Supported Blockchains & Assets
4. Onboarding to inabit
a. Open account + pairing
b. signs up: https://use.inabit.com/create_account
c. Pair the owner’s mobile device (key custody + approvals). Device pairing enables secure, policy-enforced approvals for sensitive actions.
d. inabit Enables API Access
inabit automatically generates two API users.
API Signer
Created for the sole purpose of serving as the "Approver" to sign transactions using inabit's Approvals Docker.
API Admin
Serves as the API key/access user for inabit's API endpoints.
Note that the account owner will need to approve the creation of these users on the inabit mobile app.
e. Open UI wallets
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
For recommended best-practice wallet structures, see here: For inabit wallet types guide, see here
f .Implement Remote Approver App
The Remote Approver App (Approver Docker) enables policy-based, automated approvals for API wallets only (it does not apply to UI wallets).
Deployment options
Self-hosted (recommended default): One-time Docker setup via the inabit CLI on your own infrastructure.
inabit-hosted (managed): inabit can host and operate the Remote Approver App for you
For inabit-hosted contact inabit support
When to choose which?
Choose self-hosted if you require full infrastructure control or have strict internal hosting policies.
Choose inabit-hosted to reduce ops overhead; in this managed mode, API wallets can transfer funds only to internal wallets within your organization, and you still retain self-custody via your approval policies and paired identities.
5. Enabling Terminal
To enable inabit Terminal, contact our Support.
6. Creates & Configures Widgets
Widget Creation
Widgets are created and managed directly in the inabit Terminal UI. The PSP creates a separate widget for each merchant, and configures its parameters (supported blockchains, assets, visual settings) and generates the widget-specific API key and snippet, which is then embedded.
Widget Configuration
Choosing the Right Widget Type:
The PSP selects and configures the widget per merchant use case. inabit supports two types: Purchase Address and Customer Address.”
One-time payment per transaction (e.g., single bet, fixed-price checkout, specific game session)
Purchase Address
Creates a time-boxed, amount-bound address per purchase with clear success/expiry states.
Funding a customer wallet / account balance with flexible amounts used across sessions
Customer Address
Provides a persistent address per customer for ongoing top-ups and balance management.
Dedicated address per customer for recurring deposits, reconciliation, and linking on-chain flows to a user profile
Customer Address
Stable, per-customer address simplifies reconciliation and KYC/accounting.
Quick picker:
Need exact amount + expiry for a single transaction? → Purchase Address
Need recurring or flexible deposits tied to a customer? → Customer Address
Implementation notes:
Both types support: confirmations policy, auto-sweep to Master Wallet, and coin/chain allow-lists.
Typically: shorter expiry for Purchase Address; no expiry (or long TTL) for Customer Address.
For a full description of widget types, their behavior, and recommended use cases, see here :
Functionality Settings
Once the widget type is chosen, customize the widget based on the merchant’s requirements. inabit offers robust, per-widget configuration options that allow fine-tuning of how each widget behaves. Key parameters include:
Supported Coins – Define which cryptocurrencies the widget will accept.
Deposit Amount – (Purchase Address only)
Predefined: The widget displays a specific amount to be deposited by the end-customer.
Flexible: The widget does not enforce a specific deposit amount, allowing users to send any amount to the assigned address. In this mode, the deposit address remains the same for that customer/session, and any funds received at that address will be credited accordingly.
Sweeping Frequency – Set how often received funds are automatically moved to the Master Wallet.
Expiration Time (Purchase Address only) – Configure how long each payment request remains valid.
Blockchain Confirmations – Configure the required number of confirmations per chain.
These and other advanced options allow for flexible and secure integration into any existing merchant flow.
For the full list of available settings and best practices, refer to:
Creating Widgets Guide
Advanced Widget Settings
Customizing the Widget Interface / UX
By default, you can adjust the following UI parameters:
Widget Name – A unique name to identify your widget (e.g., “Basic Plan Payment”).
Description (Optional) – Short text explaining what this widget is used for.
Merchant Name (Optional) – Merchant name displayed to the end user (if applicable).
If further customization is required:
Is required (logos, fonts, colors, layout, etc.), you can override the widget’s CSS.
The merchant (or the PSP on their behalf) can also decide whether to let the end user select the asset & blockchain inside the widget. The widget can always be reviewed in preview mode before going live to ensure it looks and behaves as expected.
(Example widget preview details and images remain as in the original guide.)
Installs Widgets
inabit supports multiple, straightforward implementation methods per widget type. Choose the approach that best fits your stack and UX-each method is intuitive and easy to set up.
Purchase Address Widget (one-time, amount-bound)
Supported methods:
Redirect
API:
A. Redirect-API (hosted flow)
Best for: quickest go-live and minimal frontend work.
How it works: Create a purchase via API → receive a hosted URL → redirect the customer. Full flow.
B. Embedded-API (embedded/open on demand)
Best for: full control from your app with a light client snippet.
How it works: Create a purchase via API → open the widget using the purchase id (popup or new window). Widget implementation guide
Customer Address (persistent address per customer)
Supported methods:
Redirect
iframe
API
A. Redirect (hosted flow):
Best for: fastest integration when you want inabit to fully host the UI.
How it works: Create/obtain the Customer Address session or token → redirect the user to the hosted page tied to that customer. Widget implementation guide
B. iframe (embedded hosted UI):
Best for: native feel while keeping low frontend effort.
How it works: Generate the Customer Address URL (session/token) server-side → embed in an <iframe> in your account page. Widget implementation guide
C. Fully API:
Best for: fully custom UI with your own components.
How it works: Use inabit’s APIs to create or fetch the customer’s persistent address, show it in your UI, and track status via webhooks. Widget implementation guide
Deposit Management
How Will the PSP Stay Up-to-Date on Incoming Deposits?
In many industries 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 merchant 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.
Best practice for monitoring deposits: use a hybrid of webhooks and API polling for real-time state changes, plus periodic polling as a safety net (e.g., to recover from missed callbacks or network hiccups). See the full guidance here.
List of Potential Deposit Statuses:
Purchase Address - only
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.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.
For both widget types (Purchase Address & Customer Address):
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).Completed– The required number of blockchain confirmations has been received, and the deposit is finalized successfully.PendingFork- Tx confirmed on a forked block; credit on hold until reorg resolves. After settlement, the deposit may complete or fail.Failed- The deposit cannot be credited (e.g., transaction invalid/dropped, double-spent or replaced via RBF to a different address). The payment attempt should be considered unsuccessful.
Get deposit by UUID for merchant:
GET https://api.inabit.biz/v1/merchant/purchase/{{purchaseId}}
(Sample JSON response as in the original guide.)
Withdrawal Process
How Are Withdrawals Handled?
Withdrawals are processed centrally from the Master Wallet, which acts as the secure treasury account for each merchant. This wallet receives funds via automatic sweeps from all the individual deposit wallets (API wallets) that are generated through inabit’s POS widgets.
Here's How It Works:
Deposit Collection & Sweeping Each time a user deposits via a widget, a unique blockchain address (API wallet) is created. Once a deposit is confirmed, inabit automatically sweeps the funds from these individual wallets to the merchant’s Master Wallet at predefined intervals (e.g., hourly, daily). Refer to our docs to learn more about Gas Fees and Sweeping.
Withdrawal Execution Once the funds are consolidated in the Master Wallet, withdrawals can be initiated. The PSP can trigger a withdrawal using inabit’s APIs or the UI
Creating a Withdrawal via API
Initiate a mutation to create an asset transfer request to send for approval from the Master Wallet.
mutation CreateWithdrawal($data: WithdrawalCreateInput!) {
createWithdrawal(data: $data) {
id
}
}Headers
Content-Type: application/json
Authorization: Bearer <token>
Body (WithdrawalCreateInput object)
wallet.id(String, required) – Master Wallet IDfinancialAsset.id(String, required) – Asset IDaddress(String, required) – Destination address (To)amount(Integer, required) – Transfer amountblockchain.id(String, required) – Blockchain IDnote(String, optional) – Transaction notepriority(String, optional) – Transaction priority (Slow, Medium, Fast, etc.)
Example body:
{
"data": {
"wallet": {
"id": "clol7o576002oaz011mmtnvru"
},
"financialAsset": {
"id": "clefn78gv011olc6rcwtt0wel"
},
"address": "0x7582f3483116105e0b7845ac1a0df5eb0c8cd062",
"amount": 5,
"blockchain": {
"id": "clefn78em00mslc6r3lzf3h5a"
},
"note": "",
"priority": "Medium"
}
}Response
id(String) – Withdrawal ID
Real-Time Visibility
inabit provides real-time status updates on withdrawal requests, including initiation, signing, blockchain confirmation, and completion, allowing the psp to reflect up-to-date information within its platform and back office.
To find out how to subscribe to Withdrawal Webhooks, please visit our Webhooks page.
Security and Policy
All outgoing transactions undergo approval logic (via the Approver Docker and mobile app). Only authorized signers (e.g., the API Signer configured during onboarding) can approve withdrawal
Last updated
Was this helpful?