{"name":"tokens","oldName":"get_token_accounts","title":"Tokens held","category":"wallets","useWhen":"Run to learn which tokens a wallet holds and how much. Ranked by USD value; unverified (often spam airdrop) tokens are flagged so you don't report fake holdings.","benefit":{"kind":"accuracy","text":"Ranks holdings by USD value and flags unverified tokens, so an agent doesn't report a wallet's spam airdrops as real money."},"description":"Lists a wallet's tokens (SPL Token and Token-2022) with exact amounts, whether each is verified, and USD value where priced.","price":"$0.01","priceText":"25 free calls a day, then $0.01 USDC per call (x402)","http":{"method":"POST","path":"/api/tools/tokens","body":"JSON object with the inputs below"},"mcp":{"method":"tools/call","name":"tokens"},"inputs":[{"name":"wallet","type":"string (base58 address)","required":true,"lookingFor":"The wallet to read the tokens of.","whereToGet":"The user's address (from their wallet app) or your agent's public key. Not a .sol name or ticker."},{"name":"how_many","type":"integer 1-100","required":false,"lookingFor":"How many tokens, highest USD value first, to return.","whereToGet":"Default 25."},{"name":"include_empty","type":"boolean","required":false,"lookingFor":"Include empty token accounts.","whereToGet":"True only to find empty accounts, e.g. to close them."},{"name":"network","type":"\"mainnet-beta\" | \"devnet\"","required":false,"lookingFor":"Default \"mainnet-beta\" (real money).","whereToGet":"\"devnet\" only for test wallets."}],"outputs":[{"field":"wallet","type":"string","is":"The wallet that was read.","howWorkedOut":"Your input, cleaned up."},{"field":"accounts_total","type":"number","is":"Every token account the wallet owns, empty ones included.","howWorkedOut":"Token accounts across the SPL Token and Token-2022 programs."},{"field":"accounts_with_balance","type":"number","is":"Token accounts holding more than zero.","howWorkedOut":"Accounts with a raw amount above 0."},{"field":"returned","type":"number","is":"How many tokens are in this answer.","howWorkedOut":"Up to how_many, after sorting."},{"field":"lookup_failed","type":"boolean","is":"True when Jupiter couldn't be reached for some tokens. Their verified, symbol and price are then null (unknown), and the USD totals are null. Ask again in a few seconds.","howWorkedOut":"Jupiter's token lookup failed twice for those tokens."},{"field":"unverified_count","type":"number","is":"Returned tokens Jupiter doesn't mark verified. A big number usually means spam airdrops.","howWorkedOut":"Tokens without Jupiter's verified flag, or that Jupiter doesn't know. Tokens whose lookup failed are not counted."},{"field":"total_usd","type":"number | null","is":"USD value of the returned tokens that are verified and priced. Spam often has a price from a tiny pool, so unverified tokens are left out. null when lookup_failed.","howWorkedOut":"Sum of tokens[].usd_value for verified tokens. Unpriced tokens add nothing, so this can be low."},{"field":"unverified_usd","type":"number | null","is":"The claimed USD value of the unverified tokens, kept apart. Don't trust it. null when lookup_failed.","howWorkedOut":"Sum of tokens[].usd_value for unverified tokens."},{"field":"tokens[].address","type":"string","is":"The token's address, its unique identity. Tickers aren't unique; addresses are.","howWorkedOut":"From the token account."},{"field":"tokens[].symbol / name","type":"string | null","is":"Ticker and name from Jupiter. Copycats can share a ticker, so trust the address, not the symbol.","howWorkedOut":"Jupiter token search by address."},{"field":"tokens[].verified","type":"boolean | null","is":"Whether Jupiter lists the token as verified. null when Jupiter couldn't be reached (unknown, not unverified).","howWorkedOut":"Jupiter's isVerified flag. false when Jupiter doesn't know the token."},{"field":"tokens[].amount","type":"string (decimal)","is":"The balance in normal units.","howWorkedOut":"raw_amount / 10^decimals with exact integer math."},{"field":"tokens[].raw_amount","type":"string (integer)","is":"The balance in raw units, the number that goes into transfers.","howWorkedOut":"From the token account."},{"field":"tokens[].decimals","type":"number","is":"How many decimal places the token uses.","howWorkedOut":"From the token account."},{"field":"tokens[].holding_account","type":"string","is":"The account that holds this balance (not the wallet itself).","howWorkedOut":"The token account's address."},{"field":"tokens[].token_program","type":"\"spl-token\" | \"token-2022\"","is":"Which token program owns the account. Transfers must use the same one.","howWorkedOut":"Which program's lookup found it."},{"field":"tokens[].frozen","type":"boolean","is":"True if the issuer froze this account. Frozen tokens can't move.","howWorkedOut":"The account state is \"frozen\"."},{"field":"tokens[].usd_price","type":"number | null","is":"Price of one token in USD.","howWorkedOut":"Jupiter usdPrice. null when Jupiter has no price."},{"field":"tokens[].usd_value","type":"number | null","is":"USD value of this holding.","howWorkedOut":"amount x usd_price, rounded to cents. null without a price."}],"notes":["Prices come from Jupiter and can lag, or be missing for thinly traded tokens.","Very large wallets are capped: prices are looked up for at most 300 tokens."],"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"wallet":{"type":"string","description":"The wallet to read the tokens of. The user's address (from their wallet app) or your agent's public key. Not a .sol name or ticker."},"how_many":{"default":25,"description":"How many tokens, highest USD value first, to return. Default 25.","type":"integer","minimum":1,"maximum":100},"include_empty":{"default":false,"description":"Include empty token accounts. True only to find empty accounts, e.g. to close them.","type":"boolean"},"network":{"default":"mainnet-beta","description":"Default \"mainnet-beta\" (real money). \"devnet\" only for test wallets.","type":"string","enum":["mainnet-beta","devnet"]}},"required":["wallet"]}}