How to Send USDT Payouts to Your Users with an API

What it takes to pay users in USDT or USDC at scale, and how to send withdrawals, rewards and refunds with one API call, without a hot wallet or gas.

· 5 min read

Taking crypto in is half of a product. Sooner or later money has to go out too: a user withdraws their balance, an affiliate earns a commission, an order is refunded. This guide looks at what sending stablecoins reliably involves, and how to do it with one request.

What a payout system has to handle

  • A hot wallet with enough USDT or USDC in it on every network you pay on.
  • Gas. To send a token you need the network's own coin (ETH, BNB or POL) in the same wallet, and it runs out at the worst moment.
  • Order. Transactions from one wallet go out one after another, and one that gets stuck blocks every payout behind it until it is replaced with a higher fee.
  • Confirmations and failures. You need to know when a payout is final, and to return the money to the user's balance when it is not sent.
  • Not paying twice. A retry after a timeout must never become a second transfer.

The Payouts API does all five. You say where the money goes and how much, and read back the status.

Step 1: have a balance

Payouts are paid from your LirChain balance, in dollars. It fills up with the deposits and payments your customers make through deposit wallets and one-time payments, and you can add USDT or USDC to it yourself from the dashboard.

Step 2: create a payout

Create a free account, open the Payouts project in the dashboard and copy its API key. Then send the network, the stablecoin, the receiver's address and the amount. external_id is your own id for the payout, such as the id of the withdrawal in your database.

curl https://api.lirchain.com/merchant/payout/create \
  -H "x-api-key: YOUR_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "network": "polygon",
    "asset": "USDT",
    "address": "0x52aE0F1c8D4b7A90e3B6c2D15f8A47e09B3C91F3",
    "amount": "25.50",
    "external_id": "user-5521"
  }'

The amount is in dollars, at least $1, with at most two decimals. The fee is taken on top: receive_amount is what the receiver gets, and pay_amount is what leaves your balance. Both are taken the moment the payout is created, so you can never send more than you have. If the balance is too low the answer is 402 and nothing happens.

A payout cannot be cancelled once it is created. Check the address and the network with the user before you send the request.

Step 3: follow the status

A payout is pending, then processing once it is sent (a few seconds after it is created), then completed when the network has safely confirmed it, 12 blocks later. Read it to see where it is and to get the transaction hash to show your user:

curl "https://api.lirchain.com/merchant/payout/payout?id=8a1f4c2e-6d3b-4f70-9c15-2e7b0a94d6c3" \
  -H "x-api-key: YOUR_API_KEY"

A payout that could not be sent becomes failed, and its amount and fee are back on your balance. Poll a payout every few seconds until it is completed or failed, then stop.

A safe withdrawal flow

  1. The user asks to withdraw. In one database transaction, take the amount from their balance in your system and save a withdrawal with a new id.
  2. Create the payout with that id as external_id. If the request times out, look the payout up in the payouts list before trying again, so a retry cannot pay twice.
  3. Poll the payout. On completed, mark the withdrawal done and show the transaction hash. On failed, give the amount back to the user.

What it costs

  • A payout costs the percentage of your plan, from 1% on Free down to 0.25% on Enterprise, at least $0.10.
  • The network gas is included. You never hold ETH, BNB or POL.
  • Every plan, including Free, sends unlimited payouts.

Questions and answers

Which networks can I pay out on?
USDT and USDC on Ethereum (ERC-20), BNB Chain (BEP-20) and Polygon. You choose the network and the stablecoin for every payout.
Who pays the gas?
LirChain does. The network fee is part of the payout fee, so there is no gas wallet for you to keep topped up.
How do I avoid paying a user twice?
Save the withdrawal in your own database first and send its id as external_id. If a request fails or times out, check the payouts list for that id before you create another payout.

Try it on the Free plan

Every product is included, and no card is needed to sign up.

Create a free account

Keep reading