Assets
Curated, chain-agnostic assets with their variants on every chain, per-chain stats, a cross-chain aggregate and the off-chain reference market.
All endpoints below use https://api.tokens.xyz/v2 with an x-api-key header; see
Authentication. The model (assets vs variants, "all chains by default",
primary variant selection, how chainStats, aggregate, stats and referenceMarket relate)
is on Multichain assets; every type named below is in
Shared shapes. Tokens are looked up under
Variants.
GET /v2/assets
Curated assets from one list (or every curated list) with their primary variant on every chain, per-chain stats and the cross-chain aggregate. Rows are ordered by headline 24h volume.
Auth: x-api-key, scope assets:read.
Query params
list(optional):all(default) or a curated slug:majors,currencies,lsts,rwas,etfs,metals,stocks(the aliasesstablesandxstocksare accepted). Anything else is400 invalid_listwith the valid values indetails.lists.chain(optional): one chain id. Keeps only assets with at least one variant on that chain and, withinclude=variants, lists only that chain's variants. Stats are unaffected.category(optional): oneAssetCategory(invalid_categoryotherwise).q(optional, max 100 chars): case-insensitive substring over id, symbol, name, aliases and variant symbols of the curated set. Unregistered tokens live underGET /v2/search.primaryVariantStrategy(optional):liquidity,execution_qualityorstock_redeemability. Defaultliquidity, exceptlist=stocksand equity assets, which default tostock_redeemability.primaryScope(optional):executable(default) orglobal. See Primary variant andprimaryScope.include(optional):variantsattachesvariants[]to every row, sorted by liquidity across chains. Anything else is400 invalid_include.limit(1–500, default 100; clamped),offset(default 0).totalis the full count after filters, so page untiloffset + assets.length >= total.
Response
interface AssetsResponse {
assets: V2Asset[]; // each with `rank` set to its position in the full ordering
total: number;
list: string; // the resolved slug, or "all"
primaryVariantStrategy: PrimaryVariantStrategy; // the requested / list default; equities may apply their own
primaryScope: 'executable' | 'global';
}Example
# Majors with a variant on Base, listing only the Base variants
curl -sS "$API_BASE_URL/v2/assets?list=majors&chain=base&include=variants&limit=20" \
-H "x-api-key: $API_KEY"{
"assets": [
{
"assetId": "usd",
"name": "US Dollar",
"symbol": "USD",
"category": "stablecoin",
"chains": ["solana", "ethereum", "base", "arbitrum", "polygon", "bnb"],
"chainStats": {
"solana": { "liquidity": 410000000, "volume24hUSD": 2100000000, "trade24h": 7100000, "marketCap": 9800000000, "fdv": 9800000000, "circulatingSupply": 9800000000, "variantCount": 4, "issuedVariantCount": 2 },
"base": { "liquidity": 52000000, "volume24hUSD": 380000000, "trade24h": 1400000, "marketCap": 3900000000, "fdv": 3900000000, "circulatingSupply": 3900000000, "variantCount": 2, "issuedVariantCount": 1 }
},
"aggregate": { "liquidity": 1800000000, "volume24hUSD": 9400000000, "trade24h": 9200000, "marketCap": 170000000000, "fdv": 170000000000, "circulatingSupply": 170000000000, "variantCount": 14, "issuedVariantCount": 9, "chainCount": 6, "excludedFromSupplyCount": 5 },
"referenceMarket": { "source": "coingecko", "coinId": "usd-coin", "price": 0.9998, "marketCap": 171000000000, "circulatingSupply": 171000000000, "totalSupply": 171000000000, "maxSupply": null, "volume24hUSD": 12000000000, "priceChange24hPercent": 0.01, "asOf": 1792800000000, "lastFetchedAt": 1792800030000 },
"primaryScope": "executable",
"primaryVariantSelection": { "pool": "executable_active", "reason": "liquidity" },
"primaryVariant": { "key": "solana:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "chain": "solana", "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "symbol": "USDC", "issuance": "native", "rank": 0, "...": "..." },
"primaryVariantByChain": { "solana": { "...": "..." }, "base": { "key": "base:0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "...": "..." } },
"variants": [
{ "key": "base:0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "chain": "base", "address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "symbol": "USDC", "issuance": "native", "rank": 2, "explorerUrl": "https://basescan.org/token/0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "...": "..." }
],
"rank": 0,
"...": "..."
}
],
"total": 11,
"list": "majors",
"primaryVariantStrategy": "liquidity",
"primaryScope": "executable"
}chains, chainStats and aggregate still describe all six chains even though chain=base
was requested; only variants[] was narrowed.
Notes
- Variants carrying a
blockedadvisory are omitted from every row (asset.advisoriesstill names them); an asset whose variants are all blocked is dropped from the list. The detail route serves them. - Cached for 60 s (
stale-while-revalidate300 s). If the data layer is unavailable the endpoint returns the last healthy payload for the same params (up to 15 minutes old) with a200; usemarket.lastFetchedAt(our last successful provider write;market.asOfis only set for trade-sourced Solana rows) andreferenceMarket.asOfas the freshness signals.
GET /v2/assets/{assetId}
One asset with every variant on every chain, per-chain stats, the cross-chain aggregate and the off-chain reference market.
Auth: x-api-key, scope assets:read.
Path params
{assetId}: an asset id (usd,bitcoin,tesla) or an alias; renamed ids are followed. A Solana or0xaddress, or a<chain>:<address>key, is400 invalid_asset_id; look tokens up underGET /v2/variants/{chain}/{address}. Ids over 120 characters are alsoinvalid_asset_id.
Query params
primaryVariantStrategy(optional), as for the list route.primaryScope(optional), as for the list route.include(optional): any ofexecutionQuality,pegHealth,preStocks, comma-separated or repeated. Each requested value adds that key to every variant in the response (variants[],primaryVariantand eachprimaryVariantByChain.*): always present, an object when there is data,nullwhen the chain lacks the capability or there is no data for that variant.executionQualityneeds the chain'sexecutionQualitycapability;pegHealthneedsriskand astablecoin-category asset;preStocksis Solana PreStocks tokens only. Keys you did not ask for are absent. Anything else is400 invalid_include(details.include,details.values).
Response
interface AssetResponse extends V2Asset {
variants: V2Variant[]; // always present here, liquidity order across chains
resolvedBy: 'assetId' | 'alias' | 'rename';
}Example
curl -sS "$API_BASE_URL/v2/assets/usd" -H "x-api-key: $API_KEY"
# Aliases resolve; the body says how
curl -sS "$API_BASE_URL/v2/assets/usdc" -H "x-api-key: $API_KEY" | jq '{assetId, resolvedBy}'
# { "assetId": "usd", "resolvedBy": "alias" }
# Peg status on every variant: an object on Solana stablecoins, null on chains without `risk`
curl -sS "$API_BASE_URL/v2/assets/usd?include=pegHealth" -H "x-api-key: $API_KEY" \
| jq '.variants[] | {key, pegHealth}'
# { "key": "solana:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "pegHealth": { "provider": "webacy", "referenceKind": "fixed", "tier": "ok", "deviationPct": -0.01, "updatedAt": 1792800000000, "stale": false } }
# { "key": "base:0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "pegHealth": null }Notes
- Unknown ids are
404withdetails.code: "asset_not_found"(details.assetId). - Unlike the list route,
blockedvariants are served here with their advisory attached, so a direct read never hides a flagged sibling. - For the
solanaasset only,variants[]is bounded:yieldandlstvariants need at least $250k liquidity and at most 500 are returned. The/variantssub-route is never capped. - Cached for 60 s (
stale-while-revalidate120 s); served from a last-good copy (up to 15 minutes old) when the data layer is unavailable. A404is a real answer and is never cached as good.
GET /v2/assets/{assetId}/variants
The asset's variants on every chain (or one chain with chain=), filterable, sorted and
paginated. Nothing is capped, so this is the right call for the solana asset's LSTs and for any
UI that pages through variants.
Auth: x-api-key, scope assets:read.
Path params
{assetId}: as for the detail route (invalid_asset_idandasset_not_foundapply).
Query params
chain(optional): one chain id.kind(optional): oneVariantKind(invalid_kindotherwise).liquidityTier(optional):tier1,tier2ortier3(invalid_liquidity_tierotherwise).stockVariantTier(optional):share_redeemable,cash_redeemableornot_redeemable(invalid_stock_variant_tierotherwise).sort(optional):liquidity(default),stock_redeemability(redeemable tiers first, then liquidity) orexecution_quality(invalid_sortotherwise).execution_qualityis accepted but currently orders by liquidity on every chain; it will use fill-quality scores once they join v2.limit(1–1000, default 100; clamped),offset.
Response
interface AssetVariantsResponse {
assetId: string; // the canonical id, even when an alias was requested
variants: V2Variant[];
total: number; // after filters, before pagination
sort: 'liquidity' | 'execution_quality' | 'stock_redeemability';
}Example
# USD stablecoins on Solana, deepest three
curl -sS "$API_BASE_URL/v2/assets/usd/variants?chain=solana&limit=3" -H "x-api-key: $API_KEY"
# Tesla: redeemable tokenized shares first
curl -sS "$API_BASE_URL/v2/assets/tesla/variants?kind=tokenized_equity&sort=stock_redeemability" \
-H "x-api-key: $API_KEY"Notes
- Each variant's
rankis its liquidity rank within the whole asset across chains, independent ofchain=, the filters andsort, so a Base-only page still tells you where each token sits globally. blockedvariants are included with their advisory.- Cached for 30 s (
stale-while-revalidate60 s); last-good copy up to 10 minutes old when the data layer is unavailable.