TRON account not activated: what it blocks and how to clear it
An address is a key pair until the network has an account for it. That is the whole of “TRON account not activated”, and it is the answer that surprises people: the address is well formed, the wallet displays it, the QR code scans, and the chain has never heard of it. For a payout desk the state turns up in two different places — the wallet that sends and the address being paid — and only one of them is a refusal.
What activation actually is
A TRON address is derived from a key pair offline. Nothing is registered anywhere when it is made, and the network learns of it only when a transaction creates an account record for it. Our own check is literal about that: we ask a node for the account behind the address, and an empty answer is what activated: false means. Not “we could not find it” and not “it looks new” — there is no account there.
The ordinary way one comes into existence is an incoming TRX transfer: send TRX to the address and the network creates the account while carrying that transfer out. Creating an account is not free. What it costs is a chain parameter rather than a figure worth printing on a page, so read it from the network rather than from anywhere that could be a year out of date. What matters here is that it is one ordinary transaction, and afterwards the address is an account like any other.
What it blocks: the wallet that will send
Energy is delegated to an account, and there is nothing to delegate to when no account exists. That is the whole of the refusal. An order in mode A or mode C naming such a wallet as from comes back 422 invalid_address with details.reason set to inactive_wallet, along with details.index — which transfer of the batch — and details.address. It is one of the four failures a payout desk meets over and over, and one of the two an order refuses outright instead of pricing.
Three properties of that refusal matter before the handler is written.
It does not consume the Idempotency-Key. None of the refusals in this family do: the request is well formed and we simply cannot take it on those addresses. Once the wallet exists, the same key with byte-identical body is a valid replay rather than a conflict, so nothing has to be re-derived at your end.
It is not answered out of a cache. Address state is cached here, but activation is re-read past the cache before an order is refused for it — a wallet activated seconds ago is accepted straight away rather than once some entry expires. Repeat immediately; there is nothing to wait out.
It does not exist in mode B. There the transaction arrives already signed by the owner of the sending address, so the account is there by construction and the check would be asking a question that has answered itself.
Not activated is not malformed
Two answers carry the same error code and mean opposite things. 400 invalid_address, with no details.reason at all, is about the shape of the string: it is not a TRON address, and nothing that happens on chain will make it one. 422 invalid_address with a details.reason is about the state of a perfectly good address, and a single transaction fixes it. A pipeline that treats them alike retries the first forever and abandons the second, so the presence of details.reason is worth branching on rather than on the error code, which the two share.
What it costs: the address being paid
On the receiving side nothing is refused; an unactivated recipient is a price. A transfer to an address with no USDT balance has to open the recipient's token account as well as move the tokens, which takes about 131,000 units of energy against about 65,000 for an address that already holds USDT (why the two differ). At the protocol rate that is 13.1 TRX of burn instead of 6.5 TRX, and in a payout run to new customers most of the batch can be in that state at once — what renting that energy costs moves with the market, the burn does not.
Here the two questions come apart, and the names invite the conflation, so be exact. activated asks whether the network has an account for the address. holds_usdt asks whether its USDT balance is above zero. The price follows the second: kind is double whenever the address holds no USDT, activated or not. The inactive_recipient warning follows the first. So an address activated years ago that has simply never been paid in USDT carries no warning and is still priced double; and an address that has never been activated can still hold USDT — a TRC-20 balance lives in the token contract's own storage, so a transfer in creates a balance and not an account — which prices it single and warns inactive_recipient at the same time. The two look like one question until an address answers them differently.
Checking one address, and checking five hundred
For a single address, GET /v1/address-check answers both questions and two more in one call: activated, holds_usdt, blacklisted, is_contract, and the expected_kind that follows from them.
For a batch, POST /v1/estimate takes up to 500 transfers and refuses nothing — everything it notices comes back as warnings on the item, including findings that would stop an order. Recipients are always examined. The sender is examined only if you name one: from is optional on an estimate item and changes no price, and the single thing it buys is the answer. inactive_sender there is the same finding an order reports as a 422, arriving while nothing is at stake.
POST /v1/estimate
{"transfers":[{"from":"TN3W…","to":"TMu1…"}]}
# warnings an item can carry: blacklisted, inactive_recipient,
# contract_recipient, inactive_sender, blacklisted_sender
Neither call reserves or charges anything, so a list can be screened as often as the rate limits allow. What neither of them rehearses is the order itself, which spends real money in every mode.
The fix
Send the address some TRX, let that transaction confirm, and replay the order with the same key and the same bytes. There is no registration step, no application and no second call to us. The one ordering rule worth writing down is that the wallet has to exist before the order, not before the transfer: energy is delivered to an account, so the account has to be there to receive it.
The same requirement stands for a wallet you want kept topped up. An Auto-refill rule is refused on an unactivated address with that same reason word, and on a contract address with contract_wallet — a contract's energy consumption works differently and the rule has nothing to size. Activate first, then set the rule.