Payout (payment/disbursement) is the capability for merchants to initiate payments to recipients through NUSDpay. After integrating the Payout API, merchants can pay recipients from their NUSD wallet balance, enabling business scenarios such as withdrawals, revenue sharing, refunds, and paying NUSD Wallet users. NUSDpay offers two payout methods with different effects — choose based on the recipient type:
MethodAPIEffectRecipientUse cases
On-chain payout (Withdraw)POST /nps/withdraw/onchainOn-chain payment: constructs a blockchain transaction, sends USDT/USDC to an on-chain address; requires block confirmation and incurs gasExternal on-chain wallet address (to, e.g. 0x...)Withdrawals, revenue sharing, refunds to crypto wallets
In-platform payout (Transfer)POST /nps/withdraw/internalIn-platform payment: settled within the NUSDpay ledger, moving funds from one wallet to another; instant, off-chain, no gasA wallet inside the NUSD system (wallet_to); can target a NUSD Wallet end user (user_token)Paying NUSD Wallet users, inter-project settlement
Key difference: with an on-chain payout (Withdraw), the funds actually leave NUSDpay and move on-chain to an external address; with an in-platform payout (Transfer), the funds always stay inside NUSDpay and only change wallet ownership. Use the former to pay on-chain crypto wallets, and the latter to pay recipients within the NUSD system.

1. On-chain payout (Withdraw)

Initiate a cryptocurrency payment to an external on-chain wallet address, transferred over the blockchain network. Suitable for withdrawals, revenue sharing, and refunds to crypto wallets.

Sequence Diagram

The following shows the complete lifecycle of an on-chain payout (Withdraw) transaction:
Payout sequence diagram

Operation Steps

1

Initiate the withdrawal request

Call the POST /nps/withdraw/onchain API, passing the recipient on-chain address, amount, chain, and token.
{
  "request_id": "d8551182-0aee-4346-929e-05c99081352a",
  "wallet_id": "e9167870-e18b-4e82-8b87-92ec7ede8e45",
  "to": "0xdc2e6b357766aa4b66f41dc29598379ce7d61d46",
  "amount": "100.00",
  "chain_id": "BASE_ETH",
  "token_id": "BASE_USDT",
  "payer": "App"
}
request_id must be globally unique and is used to prevent duplicate submissions. The same request_id will not create a new transaction.
2

System validation and freezing

The NUSDpay system performs the following validations:
  • Whether the balance is sufficient (including fees)
  • Whether the chain and token are supported
  • Whether the recipient address format is valid
Once validation passes, the corresponding amount is moved from the available balance into the frozen (hold) balance.
3

Risk control review

The transaction enters the risk control workflow:
  • AML/KYC review: Anti-money laundering and customer identity verification
  • Address allowlist check: Whether the recipient address is in the allowlist
  • Risk control rule engine: Whether the transaction amount, frequency, etc., trigger risk control rules
4

On-chain broadcast and confirmation

After the review passes, the system constructs the on-chain transaction and broadcasts it to the blockchain network. After block confirmation, the transaction is complete.
5

Webhook notification

After the transaction is complete, the system pushes a withdrawal result event to the Webhook URL configured by the merchant. See Withdraw Webhook.

2. In-platform payout (Transfer)

Pay a wallet inside the NUSDpay system (such as a NUSD Wallet end user). Funds move from one wallet to another within the ledger — instant, off-chain, and gas-free — suitable for paying NUSD Wallet users and inter-project settlement.

Sequence Diagram

In-platform payout (Transfer) sequence

Operation Steps

1

Initiate the transfer request

Call the POST /nps/withdraw/internal API, passing the source wallet, destination wallet, and amount. Unlike a withdrawal, a transfer does not require a chain or token (because it is off-chain).
{
  "request_id": "ea6f928b-0b1f-4fd3-a4fe-fc10695d2642",
  "wallet_from": "332cf3e4-af07-46f9-a3da-4aa2cbe3bdd4",
  "wallet_to": "1b8d5efd-d7a8-48ac-a195-cc8e043ae36b",
  "amount": "50.00",
  "user_token": "10001",
  "user_name": "John Doe",
  "notes": "June revenue share"
}
user_token, user_name, and notes are optional: when the recipient is a NUSD Wallet end user, use user_token to specify the corresponding app user, user_name to record the recipient’s name, and notes for the purpose.
2

System validation

NUSDpay validates that the source wallet has sufficient available balance and that the destination wallet is valid.
3

In-platform ledger crediting

After validation passes, the amount is deducted from wallet_from’s available balance and credited to wallet_to in real time. No on-chain transaction is constructed; no block confirmation; no gas fee.
4

Webhook notification

After the transfer is complete, the system pushes a transfer result event to the Webhook URL configured by the merchant. See Transfer Webhook.
In-platform payout (Transfer) uses the same underlying capability as the Transfer Solution: this page focuses on paying recipients inside the NUSD system (such as NUSD Wallet users) via the API; the Transfer Solution focuses on a merchant moving funds between its own project wallets. Neither involves an on-chain transaction.

Fund Flow

Balance Model

The merchant wallet balance is divided into two parts:
TypeDescription
Available balance (available)Amount that can be used to initiate payouts (Withdraw / Transfer)
Frozen balance (hold)On-chain withdrawal amounts that have been initiated but not yet completed
Total balanceAvailable balance + frozen balance
Balance change example (on-chain withdrawal):
Initial state: available = 1000, hold = 0

Initiate withdrawal of 100 NUSD:
  → available = 900, hold = 100

Withdrawal completed (success):
  → available = 900, hold = 0  (after fee deduction)

Withdrawal failed:
  → available = 1000, hold = 0  (freeze released, balance restored)
In-platform payout (Transfer) settles within the ledger in real time: the amount is deducted directly from the source wallet’s available balance and credited to the destination wallet, generally without an intermediate “frozen” state.

Funding Modes

Payout funds come from the merchant’s NUSD wallet balance. Merchants need to ensure the wallet has sufficient available NUSD balance. There are two ways to fund:
  • Option 1: Internal transfer — Use an in-platform transfer to move NUSD from another project wallet of the merchant (such as a Payin wallet) to the payout wallet (see Transfer Solution)
  • Option 2: External top-up — The merchant deposits USDT/USDC directly to the payout wallet address, and the system automatically converts it to NUSD for crediting
We recommend setting up a balance alert in the admin console to top up funds promptly when the available balance falls below the threshold, avoiding payout failures due to insufficient balance.

Fee Model

ItemOn-chain payout (Withdraw)In-platform payout (Transfer)
Gas feeYes (advanced by the platform, included in the service fee)None (off-chain)
Fee bearerDetermined by the payer field in the request (App = merchant pays / User = recipient pays; defaults to the recipient)No gas for in-platform transfers; service fee per the contractual agreement
The two fee modes for on-chain withdrawals:

App-Pays Mode (Merchant Pays the Fee)

The fee is borne by the merchant; the recipient receives the full amount.
Recipient receives = Payment amount × Exchange rate
The fee is additionally deducted from the merchant's balance
Applicable scenarios: The merchant wants to ensure the recipient receives the precise agreed amount (e.g., refunds, payroll).

User-Pays Mode (Recipient Pays the Fee)

The fee is deducted from the payment amount; the amount actually received by the recipient is reduced.
Recipient receives = Payment amount × (1 - Service fee rate) × Exchange rate
Applicable scenarios: The merchant wants to control costs and have the recipient pay the fee (e.g., withdrawals).

Fee Description

Fee TypeDescription
Service fee rateConfigured per project; supports custom rates
Exchange rateRefers to the real-time market exchange rate (USDC/USDT); the API returns the actual rate
Gas feeAdvanced by the platform; already included in the service fee (incurred only for on-chain payouts)
The specific fee rates are subject to the contractual agreement. You can obtain the current fee configuration via the Query Platform Fees API.

Transaction Status

Complete status flow of an on-chain payout (Withdraw) transaction:
Payout status flow
StatusDescription
ReviewingTransaction under review
PendingWaiting to be processed (including sub-statuses such as AML review, risk control review, and address allowlist check)
ConfirmingBroadcast to the chain, waiting for block confirmation
CompletedTransaction completed; funds delivered
FailedTransaction failed (includes specific failure reasons)
In-platform payout (Transfer) is off-chain and has no Confirming (block confirmation) stage — it completes in real time once validation passes.
For detailed status and sub-status descriptions, see Transaction Status Reference.

Exception Handling

Insufficient Balance

When initiating a payout, if the available balance is insufficient (on-chain withdrawals also require fees), the API will return an error. Please ensure the wallet has sufficient available balance.

Risk Control Interception

When an on-chain withdrawal is intercepted by risk control rules, the status changes to Failed, and the frozen funds are automatically released. The Webhook notification contains the specific failure reason. Common interception reasons:
  • Recipient address is not on the allowlist
  • Single transaction amount exceeds the limit
  • AML rule triggered

On-Chain Failure (on-chain payouts only)

In rare cases, the withdrawal fails on-chain (e.g., insufficient gas, contract exception). The NUSDpay system will automatically retry or mark the transaction as failed and release the frozen NUSD funds. In-platform payouts (Transfer) are off-chain and not subject to this type of exception.

Webhook Not Received

If Webhook delivery fails (timeout or non-200/201 response), the system automatically retries up to 10 times. We recommend:
  • Ensure the Webhook endpoint responds within 2 seconds
  • Use request_id for idempotent handling
  • Periodically call the Transaction Records API as a reconciliation fallback

Next Steps

Payin Solution

Learn how to receive cryptocurrency deposits from customers.

Transfer Solution

Learn how to move funds between a merchant’s own project wallets.