TokensAPI

Migrating from v1

The endpoint map and field map from the v1 asset routes to the v2 asset and variant routes.

v1 keeps working unchanged. v2 is a different shape, not a renamed one: the variant is addressed by <chain>:<address>, every number is cross-chain by default, and raw-mint paths are gone from the asset surface.

Both APIs serve registered assets only. On v1 an unregistered Solana mint is 404 with details.code: "asset_not_registered"; on v2 it is 404 variant_not_found (or missing[] in a batch) and an address-shaped {assetId} is 400 invalid_asset_id. Neither API synthesises an asset for a mint it does not know. For those tokens use Token lists or GET /v2/search.

Endpoints

v1v2
GET /v1/assets/curated?list=…&groupBy=assetGET /v2/assets?list=…
GET /v1/assets/curated?variants=allGET /v2/assets?include=variants
GET /v1/assets/curated?groupBy=mintdropped; use GET /v2/assets/{assetId}/variants, or include=variants and flatten client-side
GET /v1/assets/search?q= (canonical rows)GET /v2/assets?q= for the curated set; unregistered tokens via GET /v2/search
GET /v1/assets/{assetId}GET /v2/assets/{assetId}
GET /v1/assets/{mint} (a registered mint)GET /v2/variants/solana/{mint}: the variant plus an asset summary. Unregistered mints are 404 on both (asset_not_registered on v1, variant_not_found on v2)
GET /v1/assets/{assetId}/variantsGET /v2/assets/{assetId}/variants
GET /v1/assets/resolve?ref=GET /v2/assets/{assetId} (resolvedBy) for ids and aliases; GET /v2/variants/{chain}/{address} for addresses
GET /v1/assets/variant-markets?mints=GET /v2/variants?keys=solana:{mint},…
GET /v1/assets/{assetId}?include=profile,risk,ohlcv,marketsprofile, risk, ohlcv and markets are not in v2. Keep using the v1 route and its /risk-*, /ohlcv and /markets siblings for Solana variants. The per-variant enrichments v1 attached implicitly are opt-in on v2: GET /v2/assets/{assetId}?include=executionQuality,pegHealth,preStocks

Unknown list= values are 400 invalid_list on v2; v1 silently coerced them to all.

Fields

v1v2
variant.mintvariant.key (<chain>:<address>), with variant.chain and variant.address split out
asset.variantGroups.spot[], .tokenizedEquity[], …variants[], flat and liquidity-ordered; group on variant.kind
asset.canonicalMarketreferenceMarket; source: "clickhouse_stock" is "stock"; the PreStocks arm's mint is key
asset.stats (on-Solana aggregate)stats (cross-chain headline); the on-Solana figures are chainStats.solana
—chains, chainStats, aggregate, primaryVariantByChain, variant.issuance, variant.explorerUrl (new)
resolution (top-level, detail) / resolvedBy (resolve)resolvedBy: 'assetId' | 'alias' | 'rename' on the detail response
advisories[].mintadvisories[].key + .chain + .address
symbol?, name?, issuer?, label? (absent when unknown)always present, null when unknown
pagination: { hasMore, nextOffset }total with limit / offset; page until offset + items.length >= total
variantsMode=allnot needed; /v2/assets/{assetId}/variants is never capped
variant.executionQuality, variant.pegHealth, variant.preStocks (always attached)opt-in via include=executionQuality,pegHealth,preStocks on GET /v2/assets/{assetId}; present on every variant when requested, null off-capability (EVM) or without data; executionQuality.quoteMint is quoteKey; pegHealth.provider and .referenceKind are always present
include=profile,risk,ohlcv,markets / resolutiondropped; include= on the v2 detail route takes the three variant enrichments above instead

The full type catalogue is in Shared shapes.

Addresses

Solana addresses are case-sensitive base58, exactly as in v1. EVM addresses are accepted in any casing and always returned lowercase; compare keys, not checksummed strings. The chain is always explicit on v2: a path segment on GET /v2/variants/{chain}/{address} or the key prefix in keys=. See Multichain assets → Variant keys.