Guides

How to Accept USDT Payments on Your Website

A practical guide to accept USDT payments on your website - choosing networks, payment links vs API invoices, deposit addresses, and handling edge cases.

Flexrix Pay··6 min read

To accept USDT payments on your website, you need three things: a receiving address on each network you support, a way to tell which payment belongs to which order, and a reliable signal that the payment is final. You can build that yourself with a wallet and a block explorer, or use a payment gateway that issues addresses, watches the chain and notifies your back end. This guide walks through both, plus the decisions that matter most: networks, pricing and edge cases.

What USDT is, and why the network matters

USDT is a stablecoin issued by Tether and designed to track the US dollar. It is not a single token on a single chain. Tether issues USDT on many blockchains, and its list of supported protocols publishes the official contract address for each one. On TRON, for example, the official contract is TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t; on Ethereum it is 0xdac17f958d2ee523a2206206994597c13d831ec7.

This matters for two reasons.

  • USDT on one network is not interchangeable on-chain with USDT on another. A customer who sends USDT on BNB Smart Chain cannot pay an address that only watches TRON. The customer must pick the same network you expect.
  • Anyone can deploy a token called "USDT". Only the issuer's contract is real. A fake token can show up in a wallet with the right name and logo and still be worthless. Your system must check the contract address, not the symbol.

The network also sets the customer's fee and how long they wait. Fees on every chain change with demand, so treat any figure you see as a snapshot, not a quote.

Choosing which networks to support

You do not need every network. Start with the ones your customers already hold USDT on, and add more when people ask. The table below shows where USDT is available through Flexrix Pay and the approximate wait before a payment is credited. These are the confirmation waits Flexrix Pay uses, and they vary with network conditions.

NetworkToken standardApprox. wait before credit
TRONTRC-20~1 min
BNB Smart ChainBEP-20~1 min
SolanaSPL~1 min
TONJetton~1 min
Polygon PoSERC-20~1 min
EthereumERC-20~15 min
Arbitrum OneERC-20~20 min
OP MainnetERC-20~20 min

A sensible default for many businesses is one low-fee network (TRON is common for USDT) plus Ethereum for customers who hold funds there. If your audience uses Telegram wallets, TON is worth adding. If they use self-custody wallets such as Phantom, add Solana.

Three ways to accept USDT

1. Post a wallet address

The simplest method is to show a static address on your checkout page and ask customers to send the exact amount. It costs nothing to set up, but it breaks down quickly:

  • You cannot tell two customers apart if they send the same amount.
  • You must check the explorer by hand and match transfers to orders.
  • Customers who send on the wrong network, or send a fake token, create support tickets you cannot resolve automatically.
  • You have no sanctions screening on incoming funds.

It can work for a handful of invoices a month. It does not scale.

A payment link is a hosted page with a unique address, an amount and a countdown. You create it in a dashboard and share it by email, WhatsApp or Telegram. The customer opens it on their phone, scans a QR code or taps to pay from their wallet, and you get a notification when the payment lands. No code is needed. This suits freelancers, agencies and anyone who invoices by hand.

3. Integrate an API

For a store or SaaS checkout, you create the payment from your back end. There are two common patterns:

  • Invoices: one address per order, with a fixed amount and an expiry. Best for one-off purchases.
  • Permanent deposit addresses: one stable address per customer per network. Every top-up to it is credited to that customer. Best for account balances, wallets and repeat buyers.

A step-by-step setup with an API

Here is the shape of a typical integration. The details below use the Flexrix Pay API, but the steps carry over to most gateways.

  1. Create an account and an API key with only the scopes you need. For accepting payments, that is read and payments. Keep any key with payout rights on your server only.
  2. Register a webhook endpoint so your back end hears about payments as they happen.
  3. When a customer checks out, create an invoice with your order id as foreign_id.
  4. Redirect the customer to the returned checkout_url, or show the address and amount on your own page.
  5. When your webhook receives invoice.paid, mark the order paid and deliver.
  6. If you receive invoice.underpaid, invoice.overpaid or a late payment, apply your policy (see below).

Every request is signed with HMAC-SHA256. Creating an invoice for 25 USDT on TRON looks like this in Node.js, using the signing helper from the API reference:

js
const body = JSON.stringify({
  foreign_id: 'order-1001',
  network: 'tron',
  asset: 'USDT-TRON',
  amount: '25',
});
const res = await fetch('https://api.flexrixpay.com/v1/invoices', {
  method: 'POST',
  body,
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': 'order-1001-create',
    ...signed(KEY_ID, SECRET, 'POST', '/v1/invoices', body),
  },
});
const { invoice } = await res.json();
// invoice.checkout_url, invoice.address, invoice.amount, invoice.expires_at

Two details make this safe to retry. Amounts are decimal strings, never floats, so "25" stays exactly 25. And re-sending the same foreign_id with the same content returns the existing invoice instead of creating a second one.

For a permanent deposit address, you call POST /v1/channels with a network and your customer id as foreign_id. The same customer always gets the same address, and each credited top-up arrives as a deposit.credited webhook.

Pricing in dollars or euros

Most businesses price in a local currency, not in USDT. USDT tracks the dollar closely, but not perfectly, and if you sell in euros or pounds you need a conversion anyway. You can check live prices on the Tether price page or run a quick conversion with the currency converter.

With Flexrix Pay, you can price an invoice in one of 145 fiat currencies by sending price_amount and price_currency instead of amount. The exchange rate is locked when the invoice is created, and the invoice is valid for at most one hour. A short window keeps the locked rate fair for both sides.

Edge cases you should plan for

Crypto payments are pushed by the customer, so they do not always match the request. Decide your rules before launch.

  • Underpayments. The customer sent less than requested, often because an exchange deducted a withdrawal fee. Decide whether to ask for the remainder, accept small shortfalls, or refund.
  • Overpayments. Decide whether to refund the difference or keep it as account credit.
  • Late payments. The customer paid after the invoice expired. Decide whether to honor the original price.
  • Wrong network or wrong token. Show the network name prominently and repeat it next to the address.
  • Refunds. There is no "reverse" button on a blockchain. A refund is a new outgoing payment, so ask the customer for a refund address on the right network.

With Flexrix Pay, every on-chain payment above the network minimum to an invoice or deposit address is credited to your balance once confirmed and screened, including underpayments, overpayments and late payments. The invoice is marked paid, underpaid or overpaid, a webhook is sent, and you decide whether to deliver, ask for the rest, or refund by payout.

Security and compliance basics

Accepting stablecoins means you receive funds from addresses you do not know. Two kinds of lists matter:

  • The US Treasury's Office of Foreign Assets Control can list specific digital currency addresses on its sanctions (SDN) list.
  • Stablecoin issuers can freeze addresses. Tether's terms reserve the right to do so.

A good setup screens incoming funds against both before crediting them. Also keep clean records: order id, transaction hash, amount, network and the rate used for any fiat price. Tax and reporting rules depend on where you operate, so check with a qualified accountant or lawyer before you launch.

Key takeaways

  • USDT exists on many networks; the customer must pay on the network you expect, and only the official contract counts.
  • Start with one or two networks your customers already use, and expand on demand.
  • Payment links need no code; an API with invoices or permanent deposit addresses scales to a full checkout.
  • Write down your rules for underpayments, overpayments, late payments and refunds before launch.
  • Screen incoming funds and keep the transaction hash with every order.

Try it with Flexrix Pay

Flexrix Pay accepts USDT on TRON, Ethereum, BNB Smart Chain, Solana, TON, Arbitrum One, OP Mainnet and Polygon PoS, through payment links or the API. Creating an account is free, and the API reference covers invoices, deposit addresses and webhooks in detail.

Keep reading