Endpoints
Token report
Market data, security, Holder Score, holder metrics, clusters, dev history and trading activity of a token.
GET
/api/v1/tokens/{chain}/{address}Returns the latest report XCA has for a token. Reading a report never starts a scan: if the status is NONE, the token hasn't been scanned yet, so call POST /scans first.
Parameters#
chainpathrequiredChain id. Only solana for now."solana"
addresspathrequiredToken mint address.string
Request#
curl -s "https://app.xca.fun/api/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263" \
-H "Authorization: Bearer $XCA_API_KEY"Try it
Paste your API key to send a real request.
Response#
chainChain id.string
addressToken mint address.string
statusReport state. NONE means the token was never scanned."NONE" | "QUEUED" | "RUNNING" | "DONE" | "ERROR"
depthLIGHT for automatic scans of new pairs, FULL for complete analysis."LIGHT" | "FULL" | null
upgradingA LIGHT report is being upgraded to FULL.boolean
stepCurrent scan step while the scan runs.string | null
progressScan progress from 0 to 100.number
errorMessageWhy the last scan failed, when status is ERROR.string | null
symbolToken ticker.string | null
nameToken name.string | null
imageUrlToken logo URL.string | null
marketMain trading pair from DexScreener.object | null
marketMain trading pair from DexScreener.object | null
pairAddressAddress of the most liquid pair.string | null
dexIdDEX of that pair.string | null
urlDexScreener page of the pair.string | null
nameToken name from the pair.string | null
symbolToken ticker from the pair.string | null
quoteSymbolQuote asset of the pair, e.g. SOL.string | null
imageUrlToken logo from DexScreener.string | null
priceUsdPrice in USD.number | null
liquidityUsdLiquidity of all pools, USD.number | null
fdvUsdFully diluted valuation, USD.number | null
marketCapUsdMarket cap, USD.number | null
volume24hUsdTrading volume over 24 hours, USD.number | null
txns24hBuy and sell transactions over 24 hours.{ buys, sells } | null
changePrice change in percent over 5 minutes, 1, 6 and 24 hours.{ m5, h1, h6, h24 }
pairCreatedAtWhen the pair was created.string | null
poolAddressesAddresses of all known pools of the token.string[]
websitesProject websites.{ url, label }[]
socialsProject social links.{ type, url }[]
fetchedAtWhen the market data was fetched.string
securityOn-chain facts about the mint.object | null
securityOn-chain facts about the mint.object | null
mintAuthorityWho can mint new tokens; null when revoked.string | null
freezeAuthorityWho can freeze holder accounts; null when revoked.string | null
programToken program of the mint."spl-token" | "spl-token-2022" | "unknown"
supplyTotal supply in whole tokens.number
decimalsDecimal places of the token.number
creatorWallet that created the token, when known.string | null
createdAtWhen the mint was created.string | null
computedAtWhen the report was computed.string | null
staleThe report is older than its cache lifetime.boolean
holderScoreHolder Score from 0 (dangerous) to 100 (clean).number | null
riskLevelRisk level derived from the score."low" | "medium" | "high" | null
metricsDistribution metrics; keys depend on your plan.object | null
metricsDistribution metrics; keys depend on your plan.object | null
limitedHolder data was partial (provider limits).boolean
holdersTotalTotal number of holders.number
holdersAnalyzedHolders included in the analysis.number
profiledHolders with a full wallet profile.number
top10PctShare held by the 10 largest real holders (pools, burns and exchanges excluded).number
devPctShare held by the creator.number
devBundlePctShare held by wallets bundled with the creator.number
sniperCountNumber of sniper wallets.number
sniperPctShare held by snipers.number
freshCountNumber of fresh wallets.number
freshPctShare held by fresh wallets.number
clusterPctShare held by clusters of wallets with a common funder.number
smartCountNumber of smart-money holders.number
smartPctShare held by smart money.number
poolPctShare held by liquidity pools.number
burnPctShare sent to burn addresses.number
avgPnlUsdAverage 30-day PnL of profiled holders, USD.number | null
launchAtWhen trading started.string | null
launchSlotSolana slot of the first trade.number | null
breakdownEvery Holder Score factor with its points and measured value.{ key, points, value }[]
mainReasonThe factor that cost the most points.{ key, points, value } | null
clustersGroups of holders funded by the same wallet.object[] | null
clustersGroups of holders funded by the same wallet.object[] | null
idCluster id, referenced by holders' clusterId.string
funderWallet that funded the members.string
funderLabelKnown label of the funder, e.g. an exchange.string | null
membersMember wallets.string[]
sharePctShare held by the cluster.number
clustersCountNumber of clusters, also when the cluster list is locked.number
devHistoryPrevious launches of the creator.object | null
devHistoryPrevious launches of the creator.object | null
creatorCreator wallet.string | null
launchesTokens launched by the creator.number
rugsLaunches that lost their liquidity.number
avgLifespanSecAverage lifetime of the creator's tokens, when known.number | null
tokensThe launches, newest first.{ address, symbol, name, createdAt, liquidityUsd, fdvUsd, rugged }[]
approximateInferred from the creator's earliest buys, so treat it as an estimate.true
devTeaserLaunch and rug counts, also when dev history is locked.{ launches, rugs } | null
activityRecent trading on the main pair.object | null
activityRecent trading on the main pair.object | null
recentLatest swaps; time is a Unix timestamp in milliseconds.{ signature, time, wallet, side, amount, valueUsd }[]
topTradersMost profitable traders of the token.{ wallet, boughtUsd, soldUsd, pnlUsd, trades }[]
lockedFeatures your plan doesn't include; their fields are null or omitted.string[]
Example response#
{
"chain": "solana",
"address": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"status": "DONE",
"depth": "FULL",
"upgrading": false,
"step": "done",
"progress": 100,
"errorMessage": null,
"symbol": "Bonk",
"name": "Bonk",
"imageUrl": "https://arweave.net/hQiPZOsRZXGXBJd_82PhVdlM_hACsT_q6wqwf5cSY7I",
"market": {
"pairAddress": "6oFWm7KPLfxnwMb3z5xwBoXNSPP3JJyirAPqPSiVcnsp",
"dexId": "raydium",
"url": "https://dexscreener.com/solana/6ofwm7kplfxnwmb3z5xwboxnspp3jjyirapqpsivcnsp",
"name": "Bonk",
"symbol": "Bonk",
"quoteSymbol": "SOL",
"imageUrl": "https://arweave.net/hQiPZOsRZXGXBJd_82PhVdlM_hACsT_q6wqwf5cSY7I",
"priceUsd": 0.00002134,
"liquidityUsd": 2864210.4,
"fdvUsd": 1897000000,
"marketCapUsd": 1652000000,
"volume24hUsd": 18450000,
"txns24h": {
"buys": 18210,
"sells": 16930
},
"change": {
"m5": 0.4,
"h1": -1.2,
"h6": 3.8,
"h24": 5.1
},
"pairCreatedAt": "2022-12-25T11:04:12.000Z",
"poolAddresses": [
"6oFWm7KPLfxnwMb3z5xwBoXNSPP3JJyirAPqPSiVcnsp"
],
"websites": [
{
"url": "https://bonkcoin.com",
"label": "Website"
}
],
"socials": [
{
"type": "twitter",
"url": "https://x.com/bonk_inu"
}
],
"fetchedAt": "2026-10-02T09:12:40.000Z"
},
"security": {
"mintAuthority": null,
"freezeAuthority": null,
"program": "spl-token",
"supply": 88870000000000,
"decimals": 5,
"creator": "9AhKqLR67hwapvG8SA2JFXaCshXc9nALJjpKaHZrsbkw",
"createdAt": "2022-12-25T10:52:01.000Z"
},
"computedAt": "2026-10-02T09:12:44.000Z",
"stale": false,
"holderScore": 78,
"riskLevel": "low",
"metrics": {
"limited": false,
"holdersTotal": 912345,
"holdersAnalyzed": 4000,
"profiled": 100,
"top10Pct": 21.4,
"devPct": 0,
"devBundlePct": 0.3,
"sniperCount": 2,
"sniperPct": 0.6,
"freshCount": 41,
"freshPct": 3.9,
"clusterPct": 4.2,
"smartCount": 7,
"smartPct": 2.1,
"poolPct": 3.4,
"burnPct": 0,
"avgPnlUsd": 1840.5,
"launchAt": "2022-12-25T11:04:12.000Z",
"launchSlot": 168410720,
"breakdown": [
{
"key": "top10",
"points": -0.7,
"value": 21.4
},
{
"key": "devBundle",
"points": -0.5,
"value": 0.3
},
{
"key": "snipers",
"points": -0.5,
"value": 0.6
},
{
"key": "clusters",
"points": -2.5,
"value": 4.2
},
{
"key": "fresh",
"points": -1.3,
"value": 3.9
},
{
"key": "authorities",
"points": 0,
"value": 0
},
{
"key": "devRugs",
"points": 0,
"value": 0
},
{
"key": "smartMoneyBonus",
"points": 10,
"value": 7
}
],
"mainReason": {
"key": "clusters",
"points": -2.5,
"value": 4.2
}
},
"clusters": [
{
"id": "c1",
"funder": "5tzFkiKscXHK5ZXCGbXZxdw7gTjjD1mBwuoFbhUvuAi9",
"funderLabel": null,
"members": [
"3Kv1…",
"8Zq4…",
"Fh2T…"
],
"sharePct": 1.8
}
],
"clustersCount": 3,
"devHistory": {
"creator": "9AhKqLR67hwapvG8SA2JFXaCshXc9nALJjpKaHZrsbkw",
"launches": 1,
"rugs": 0,
"avgLifespanSec": null,
"tokens": [],
"approximate": true
},
"devTeaser": {
"launches": 1,
"rugs": 0
},
"activity": {
"recent": [
{
"signature": "4Vt2…",
"time": 1790932360000,
"wallet": "7xKX…",
"side": "buy",
"amount": 152000000,
"valueUsd": 3244.1
}
],
"topTraders": [
{
"wallet": "2bQm…",
"boughtUsd": 41200,
"soldUsd": 78900,
"pnlUsd": 37700,
"trades": 18
}
]
},
"locked": []
}Status codes#
200Success
400validation — A parameter or the body is invalid; see
error.issues.401unauthorized — The API key is missing, malformed or revoked.
402
planRequired — Your plan doesn't include API access or this feature.429
rateLimited — Too many requests per minute, or the monthly quota is used up.Report status#
NONE | Never scanned. Start a scan with POST /scans. |
QUEUED | Waiting for a worker. |
RUNNING | Being analyzed; see step and progress. |
DONE | Finished; the report is complete. |
ERROR | The last scan failed; see errorMessage and try again. |
Good to know#
- Fields of features that your plan doesn't include are null or left out, and their keys are listed in locked.
- stale is true when the report is older than its cache lifetime; a new
POST /scansrefreshes it. LIGHTreports come from automatic scans of new pairs and have no wallet PnL until someone opens them; upgrading is true while that happens.- Shares are percentages of the total supply, including tokens held by pools.