Recovery needs no support ticket and no new wallet. Refer to the chains
overview for the support tier of the chain in question, since the tier
determines whether Privy broadcasts the transaction or the transaction must be broadcast
independently.
Why the dashboard cannot send an asset
The dashboard displays balances for a broader set of assets than it can transfer, so a balance appearing in the UI is not a guarantee that the UI can move it. Identify the cause first, because it determines the cheapest recovery path.Choosing a recovery path
Token watchlist
No code. Registers the token so the dashboard transfer flow can send it. Covers ERC-20, SPL, and
Token-2022 on supported networks.
Transfer action API
Recommended. One request moves any ERC-20 or SPL token on a supported chain, from any wallet,
with no transaction construction.
Low-level RPC
For chains the transfer API does not cover. Build the transaction, have Privy sign it, and
broadcast it if Privy does not.
Transfer intent
For a wallet owned by a key quorum of team members. Propose the transfer, then approve it from
the dashboard.
Prerequisites
- The wallet’s ID, from the Wallets page of the dashboard
- The app’s ID and app secret, from the Basics tab of the app’s settings
- The token’s contract address (EVM) or mint address (Solana)
- A destination address that can hold the asset
- Enough native currency in the wallet to pay gas, unless the app has gas sponsorship configured
Check whether the wallet has an owner
Whether the wallet has an owner determines how each request is authorized, so establish it before starting. Fetch the wallet and checkowner_id, which is null for an ownerless wallet:
A wallet owned by a key quorum cannot be recovered with a direct API call, because the request
carries no authorization signatures from the quorum. Propose the transfer as an
intent instead, then have the quorum’s reviewers
approve it in the dashboard. Intents expire 72 hours after creation.
Option 1: Token watchlist
Privy’s transfer flow sends well-known assets such as USDC, USDT, EURC, ETH, and SOL out of the box. Any other ERC-20 or SPL token becomes sendable once it is registered as a custom asset for the app. This is the only recovery path that requires no code, so it is worth attempting first.1
Register the token
Open the Token
watchlist tab of the
Wallets page, then add the token’s contract or mint address on the network holding the
balance.
2
Confirm the balance appears
Return to the wallet’s page. The token now appears as a selectable asset in the transfer flow
rather than a display-only balance.
3
Send the balance
Start a transfer from the wallet, select the newly registered token, and enter the destination
address.
Option 2: Transfer action API
The transfer action API accepts a human-readable asset, amount, chain, and destination, and handles the onchain construction. It works from any wallet the caller is authorized to use, including end-user and embedded wallets that the dashboard cannot send from, and it resolves token decimals so the amount is a plain decimal string. Register the token in the token watchlist first, then pass its address assource.asset_address:
source.asset instead of source.asset_address, using the asset’s API
value such as usdc. Provide exactly one of the two fields; sending both is rejected. Refer to
transfer usage for the full parameter list and response shape.
The response is an action rather than a transaction, returning an id and a status of pending. Poll
the action until it reports a terminal status to confirm the recovery landed:
source.amount. Recovering the wallet’s native balance is the same request with asset set to the
native token, run last so the earlier transfers still have gas available.
Option 3: Low-level RPC
The transfer action API covers a fixed set of chains. Outside that set, build the transaction and use Privy’s signing RPCs directly. Which RPC applies depends on the wallet’schain_type, not on the token.
- ERC-20 on any EVM chain
- SPL on Solana
For an EVM chain that Privy broadcasts to, encode a If Privy does not broadcast to the chain, sign the transaction and submit it independently. Use
Signing this way means populating
transfer call and send it as a normal transaction.
The to field is the token contract; the destination is an argument to transfer.eth_signTransaction, which returns an
RLP-encoded signed transaction ready for eth_sendRawTransaction. It takes an explicit chain_id and no
caip2, so it works on EVM chains Privy does not broadcast to:nonce, gas_limit, and the fee fields, since Privy is not
estimating them.Recovering a token on a chain type other than EVM or Solana, such as a TRC-20 balance on Tron,
uses that chain’s own signing RPC rather than the methods above. Refer to the Tier 2 chains
recipe for per-chain examples, and adapt the transaction being built from a
native transfer to the chain’s token transfer.
Verify the recovery
Confirm the transaction onchain, then re-check the wallet’s balances in the dashboard. A recovered wallet shows a zero balance for the asset, plus whatever native currency was left behind for gas. Repeat per asset and per network, since each transfer moves one asset on one chain.Related resources
Transfer action API
Supported assets and chains, custom assets, and native bridging.
Propose intents
Recovering from a wallet owned by a key quorum of team members.
Chain support
Which chains Privy signs for, and which it also broadcasts for.
Sending ERC-20s
Encoding an ERC-20 transfer across Privy’s SDKs.
Sending SPL tokens
Building SPL transfers and handling associated token accounts.
Using Tier 2 chains
Signing and broadcasting examples for chain types beyond EVM and Solana.

