Accept USDT Payments on TRON via API: Merchant Integration Guide
Accepting USDT on TRON offers near-instant settlement and low fees — attractive for merchants, SaaS platforms, and OTC desks. Unlike card payments, on-chain USDT has no chargebacks and no native webhook — you build confirmation logic against TronGrid or your own full node.
This guide outlines production architecture for TRC-20 USDT payment acceptance.
Architecture overview
Customer → sends USDT to deposit address
↓
TronGrid / event indexer
↓
Your payment service (match txid)
↓
Webhook to app → order fulfilled
↓
Sweep to treasury (optional cron)
Official USDT contract (mainnet only):
TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t
Verify: USDT TRC-20 explained.
Address strategy
Unique address per invoice
Recommended. Generate new TRON address per order from HD wallet (BIP44 path m/44'/195'/0'/0/n — coin type 195 for TRON).
Benefits:
- Automatic order matching by
toaddress - Easier accounting
- Limits blast radius if key compromised
Single address + amount matching
One address, match by exact amount + time window.
Risks:
- Colliding payments same amount
- Customer sends wrong amount
- Requires manual reconciliation
Use only for low volume with human oversight.
Detecting deposits
Option A: TRC-20 transactions API
const USDT = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
const url = `https://api.trongrid.io/v1/accounts/${depositAddress}/transactions/trc20?only_confirmed=true&limit=50&contract_address=${USDT}`;
const res = await fetch(url, {
headers: { 'TRON-PRO-API-KEY': process.env.TRONGRID_KEY }
});
const { data } = await res.json();
for (const tx of data) {
if (processed.has(tx.transaction_id)) continue;
const amount = Number(tx.value) / 1e6; // USDT 6 decimals
await creditOrder(tx.to, amount, tx.transaction_id);
processed.add(tx.transaction_id);
}
Details: query TRC-20 balance API.
Option B: Event listeners
Filter Transfer(address,address,uint256) where to = deposit addresses. More scalable at volume.
Option C: Transaction hash from customer
Customer submits txid manually — you verify once:
Least automated; useful as fallback.
Validation rules
Before marking paid:
- Contract =
TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t - Result = SUCCESS (via
gettransactioninfobyid) - to = expected deposit address
- Amount ≥ order total (handle overpay policy)
- txid not previously processed (idempotency)
- Block timestamp within order expiry window
Reject fake USDT tokens with same symbol.
Confirmations
const info = await tronWeb.trx.getTransactionInfo(txid); const confirmed = info.blockNumber > 0 && info.receipt?.result === 'SUCCESS';
Policy examples:
| Risk tier | Blocks to wait |
|---|---|
| Low value digital goods | 1 |
| Standard e-commerce | 3–12 |
| High value / manual | 19+ or human approval |
TRON reorg risk is low but non-zero — tune to business risk.
Webhooks to your application
Internal flow after detection:
await fetch('https://yourapp.com/internal/payment-confirmed', {
method: 'POST',
headers: { 'X-Signature': hmac },
body: JSON.stringify({ orderId, txid, amount, asset: 'USDT-TRC20' })
});
Sign webhooks with HMAC. Retry with exponential backoff.
Sweeps and treasury
Hot deposit keys online for automation — periodically sweep to cold treasury:
// After confirmation await usdtContract.transfer(treasuryAddress, balance).send();
Account for Energy on sweep txs — freeze TRX on hot wallet or maintain TRX buffer.
Security
- Never store master seed on application server unencrypted — use HSM or KMS
- Validate addresses with
TronWeb.isAddress()— address validation - Rate-limit public invoice endpoints
- Monitor unexpected outflows (compromise alert)
- Smart contract security if using escrow contracts
UX recommendations
- Show QR code with address + network label "TRC-20 USDT"
- Display exact amount expected (6 decimals)
- Countdown invoice expiry
- Link to TronScan after payment
- Warn: wrong network loses funds — wrong network guide
Error handling
| Case | Action |
|---|---|
| Underpay | Partial credit or refund policy |
| Overpay | Credit excess or manual refund |
| Late payment | Expired order — manual support |
| Double txid | Idempotent ignore |
| Pending | Poll until SUCCESS or timeout |
Testing
- Deploy to Shasta testnet with test USDT
- Simulate SUCCESS and REVERT txs
- Load test TronGrid rate limits
- Chaos test: duplicate webhooks, API timeout
Related guides
FAQ
What is the official USDT contract on TRON for payments?
TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t — filter all detection to this contract.
How many confirmations should a merchant wait?
Most credit after one block (~3 seconds). High-value may wait longer.
Can I use TronLink instead of custom integration?
For manual business yes. Automated checkout requires API integration.
Do customers need TRX to pay me USDT?
Sender pays Energy/TRX fees — not the merchant. Merchant pays sweep fees.
Is USDT on TRON reversible?
No chargebacks. Refunds require sending USDT back manually.
Thanks — your feedback helps us improve the docs.