How to accept USDT payments on your website

USDT is the most used stablecoin for online payments: customers already hold it, and its value stays pegged to the dollar, so the price you quote is the price you receive. This guide shows the whole flow with TrezorPay: one request to create an address, a QR code for your customer, and a signed callback when the money reaches your wallet.

1. Pick the network

USDT exists on several networks. Your customer must send it on the network of the address you show them.

NetworkTickerMinimumConfirmations
Tron (TRC20)trc20/usdt10 USDT19
BNB Smart Chainbep20/usdt1 USDT15
Ethereumerc20/usdt2 USDT3

TRC20 is the most common for customers coming from exchanges; BEP20 is the cheapest for small payments. Our network comparison goes into the details.

2. Create a deposit address

There is no account and no API key. Call /create/ with the URL we should notify and the wallet that receives the money:

curl "https://api.trezorpay.com/trc20/usdt/create/?callback=https://your.shop/paid?order=1042&address=YOUR_TRON_WALLET&pending=1"
{
  "status": "success",
  "address_in": "TN7Zbu4UwtKneYDJyDKXkSorVu95hsE3q4",
  "address_out": "YOUR_TRON_WALLET",
  "callback_url": "https://your.shop/paid?order=1042",
  "minimum_transaction_coin": "10.00000000"
}

Put your own order id in the callback URL: the same callback URL always returns the same address, so retrying the request is safe.

3. Show the amount and a QR code

Convert your cart total, then display address_in with a QR code your customer can scan:

curl "https://api.trezorpay.com/trc20/usdt/convert/?value=49.90&from=usd"
curl "https://api.trezorpay.com/trc20/usdt/qrcode/?address=TN7Zbu4UwtKneYDJyDKXkSorVu95hsE3q4&value=49.90"

The address never expires. If your customer pays late, the payment is still received and reported.

4. Handle the callback

With pending=1, we call your URL twice for each payment:

  • as soon as the payment appears on-chain, with pending=1, so you can show "payment received";
  • once it is confirmed and forwarded to your wallet, with pending=0, value_forwarded_coin and txid_out.

Answer *ok* with HTTP 200. Anything else is retried for 3 days.

5. Verify the signature

Every callback carries x-ca-signature, an RSA-SHA256 signature of the full callback URL. Check it before marking the order paid:

import { createVerify } from 'node:crypto'

const pubkey = await (await fetch('https://api.trezorpay.com/pubkey/')).json()

export function isGenuine(fullUrl, signature) {
  return createVerify('sha256').update(fullUrl).verify(pubkey.pubkey, signature, 'base64')
}

What it costs

The fee is 1.25% of each payment, down to 0.25% as your volume grows. The network cost of forwarding a token is paid by us and recovered in USDT at the market price, so you never need TRX, BNB or ETH in your wallet. There is no sign-up, monthly or withdrawal fee.

Ready to try it? The quickstart walks through the same steps with a test payment.

More guides