TRON addresses

TRC20 Address API: generate addresses and watch them for deposits

Why TRON addresses start with T, how a TRC20 contract address differs from a wallet address, and how to create and monitor TRC20 deposit addresses over REST.

7-day free trial — no card, no KYC to start Non-custodial — private keys stay under your control Plans start at €49/month (€490/year) — view plans and rate limits

This page is about the API side of TRC20 addresses: creating them at whatever volume your integration needs, subscribing to deposits on them, and sending USDT-TRC20 out of them again. If you came here for the format question instead, read What is a TRC20 address? first. It covers why an address starts with T, what the 34 Base58Check characters encode, why the same address also has a hex spelling beginning with 41, and how TRC-20 differs from ERC-20 and BEP-20. Then come back here for the endpoints.

Everything below runs against https://app.chaingateway.io with a Bearer token in the Authorization header. Adding X-Network: testnet to any call moves it to the TRON testnet, so the whole flow can be rehearsed with free test TRX.

TRC20 address endpoints: create, read, watch, send

Four jobs, and the routes that do them. Address creation and webhook registration need no private key at all; only sending does.

EndpointWhat it does
POST /api/v2/tron/addressesGenerate a new TRON address
POST /api/v2/tron/addresses/importImport an existing private key so the API can sign for that address
POST /api/v2/tron/addresses/{address}Change the password that encrypts a stored key
DELETE /api/v2/tron/addresses/{address}Remove an address from your account
GET /api/v2/tron/balances/{address}TRX balance of the address
GET /api/v2/tron/balances/{address}/trc20/{contract_address}Balance of one TRC-20 token, USDT included
GET /api/v2/tron/balances/{address}/trc10/{token_id}Balance of a TRC-10 token
POST /api/v2/tron/webhooksSubscribe to TRX, TRC-10, TRC-20 or TRC-721 transfers for the address
GET /api/v2/tron/webhooks/notificationsList the notifications already delivered, for reconciliation
POST /api/v2/tron/transactions/trc20Send a TRC-20 token such as USDT from the address

That is the whole surface a deposit system touches. The complete TRON reference, all 40 operations including staking and self-signing, is on the TRON API page. The type field on a webhook and the separate /transactions/trc10 route exist because TRON carries two token standards; the TRC10 vs TRC20 comparison covers which one to issue on if you are launching a token rather than accepting an existing one.

Generate a TRC20 address over REST

POST /api/v2/tron/addresses creates one. The body takes a single optional field, password, and that field decides the custody model. Send a password and the private key is stored encrypted behind it, so later transfers authenticate with the password instead of the key. Leave it out and the response hands you the private key directly, for storage in your own vault. The reference is explicit that passwords are not stored: lose it and the wallet cannot be restored, which is the same sentence read from the other side — nobody else can unlock it either.

curl -X POST https://app.chaingateway.io/api/v2/tron/addresses \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"password": "a-strong-password-per-wallet"}'

If your platform already generates keys itself, the second route fits better: POST /api/v2/tron/addresses/import registers an address you derived elsewhere, together with its private key and an encryption password, and the API can sign for it from then on. Addresses you only want to watch need neither call, because a webhook subscription references an address by string.

Two housekeeping routes belong to the same set. POST /api/v2/tron/addresses/{address} changes the encryption password on a stored key. DELETE /api/v2/tron/addresses/{address} removes the address from your account, which the reference notes also lowers your used-address count — worth wiring into the job that retires expired deposit addresses if you run close to a plan limit.

Watch a TRC20 address for incoming USDT

Polling Tronscan for deposits is the version of this that breaks quietly. POST /api/v2/tron/webhooks is the version that scales. url is the only field the reference marks as required; to narrows the subscription to deposits at your address, from to transfers leaving it, and contractaddress to a single token. type selects the asset class and accepts TRX, TRC10, TRC20 or TRC721. reference holds up to 255 characters of your own text, which is where the order or customer ID belongs so the notification arrives with your lookup key already attached.

curl -X POST https://app.chaingateway.io/api/v2/tron/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-backend.example/hooks/tron",
    "to": "TYourDepositAddress",
    "type": "TRC20",
    "contractaddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "reference": "customer-4711"
  }'

Set a personal secret in your account and every delivery carries an X-Signature header, a base64-encoded HMAC-SHA256 over the payload's txid. Verify it before you parse anything else. Nothing re-sends a failed delivery on its own: GET /api/v2/tron/webhooks/notifications/failed lists what never got through, and POST /api/v2/tron/webhooks/notifications/{id}/retry is the call that sends one again. An entry leaves the failed list when its retry starts and comes back only if that retry fails too. Because a retry delivers the same event a second time, store the transaction hash of every credited deposit under a unique constraint and let the database reject the duplicate. Signature code and payload shapes are in the webhook guide.

Send USDT-TRC20 out of the address

POST /api/v2/tron/transactions/trc20 requires four fields: from, to, contractaddress and amount. The amount is a plain number in token units, so 25 USDT is 25, not a value scaled by the contract's six decimals. Alongside them you send either password, for a key the API holds encrypted, or privatekey, if you kept the key yourself.

The contractaddress field is where the distinction between a wallet address and a token contract address turns into a concrete integration rule: the contract address identifies which token moves, it is never the destination. USDT's is TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t, and it belongs in contractaddress, never in to. Tokens sent to a contract address are, in almost every case, unrecoverable. The blog guide explains why the two look identical — both are T strings, and nothing in the string tells them apart.

Sending costs Energy and Bandwidth while receiving is free, so a deposit system pays on the sweep rather than on the deposit. The TRON fee calculator prices a specific transfer, and GET /api/v2/tron/chainparameters returns the live resource prices so your code never hard-codes a constant that a governance vote invalidates.

Validate an address before you send to it

Check the destination the moment a user submits it, not after the broadcast. A TRC-20 address is 34 characters, starts with T and carries a Base58Check checksum that a single mistyped character breaks, so a well-formed string can be told from a typo without touching the network. The address validator runs that check for TRC-20, ERC-20 and BEP-20 in the browser when you want to verify one address by hand.

One thing the check cannot do is tell a TRON address from an EVM one by accident, because the formats differ visibly: a T string fails Ethereum's validation and a 0x string fails TRON's. TRON's TVM runs much of the Solidity written for the EVM, but it is a separate runtime with its own resource metering, Energy and Bandwidth instead of gas, and its own address encoding. Treating "TRON EVM" as literally true is where cross-chain address bugs start.

Building a checkout or exchange backend that needs TRC20 addresses at scale? Create a free account and generate a batch on testnet — 7-day trial, no card, no KYC.

FAQ: the TRC20 address API

POST /api/v2/tron/addresses creates one. Send a password in the body and the private key is stored encrypted behind it; leave the password out and the response returns the key for you to store yourself. Add the header X-Network: testnet to generate on the TRON testnet first.

Register a webhook with POST /api/v2/tron/webhooks. Set url to your endpoint, to to the deposit address, type to TRC20 and contractaddress to the token. Each delivery carries an X-Signature header you verify before crediting anything.

No. GET /api/v2/tron/webhooks/notifications/failed lists deliveries that never got through, and POST /api/v2/tron/webhooks/notifications/{id}/retry re-sends one when you call it. Plan the recovery path yourself, and make your crediting logic idempotent, because a retry delivers the same event again.

No. A webhook subscription references the address as a string. A key is only needed to send from it, either by importing it with POST /api/v2/tron/addresses/import or by passing privatekey on the transfer call.

In the contractaddress field, never in to. It identifies which TRC-20 token moves; USDT's is TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t. Tokens sent to a contract address are in almost every case unrecoverable.

GET /api/v2/tron/balances/{address}/trc20/{contract_address} returns the balance of one TRC-20 token. GET /api/v2/tron/balances/{address} returns the TRX balance, which is what the address needs for Energy and Bandwidth when it sends.

34 characters beginning with T in the Base58Check form users see, and the same address written in hex begins with 41. The format, the checksum and the conversion between the two spellings are covered in the guide: What is a TRC20 address?

Ready to create your first TRC20 address?

Create an account and generate a testnet TRC20 address today — 7-day trial, no card, no KYC. The full endpoint reference sits on the TRON API page, the format question is answered in What is a TRC20 address?, and all seven chains run through the same schema in the multi-chain blockchain API.