Discovery and markets API

Screen launchpad tokens by market cap, holders, top-10 %, curve and spam

Solana launchpad tokens matching ALL of: market cap, holders, top-10 %, curve %, age, no spam/manipulation. Read createdAtIso for the creation time rather than converting createdAtUnixTime.

GET/api/external/discovery/token-screen/{chain}

What it returns

Answers "which tokens match ALL of these criteria right now?" for launchpad tokens, either already bonded (stage=bonded: left the bonding curve for a regular pool) or still on the curve (stage=bonding). Omit stage when the question does not care which: both stages are screened into one list sorted by sortBy, stage echoes "all", every row says which it is in bonded and curvePct, and counts.byStage splits the counts. With no stage the liquidity floor and minLiquidityUsd apply to bonded rows only, and a row not bonded publishes liquidityUsd null: before bonding the figure counts the curve, not a tradeable pool, so it is neither shown nor checked. minCurvePct and maxCurvePct need stage=bonding; without it they are refused with a 400. Every criterion passed is checked against a value on the row, and every row carries the evidence it was checked on. A row is NEVER returned on a criterion that could not be checked: it is listed under unverified with the criteria it is missing instead. counts says how many candidates were read, checked, matched, dropped and left unverified. Market cap is read twice, from the candidate list and from the deepest pool, and the two can differ by a few percent; a market-cap bound passes only when every reading known passes it, so a row near a bound is left out rather than returned on the more favourable reading. A bonded row must also be physically possible: a pool holds at most twice the market cap in liquidity, so a bonded row listed with more than a set multiple of its market cap (2.2 by default) is re-read from its pools. Its liquidity becomes the pools' own total, and its market cap is kept only when the deepest pool confirms it within a set tolerance (10% by default); otherwise marketCapUsd is null, and the row is unverified with missing ["marketCapUsd"] whenever a market-cap bound or sortBy=marketCapUsd was asked for. excludeSpam=true keeps only rows whose spam is false: no mint authority, no freeze authority (on Solana the freeze authority is what makes a token unsellable) and not flagged rugged. Every row carries manipulationRisk: flagged with its reasons when the market cap of its pools outside the curve is far above their liquidity, nearly every trade is a buy, or supply is spread evenly across thousands of wallets. excludeManipulationRisk=true keeps only rows whose manipulationRisk.flagged is false. Bonded rows get a liquidity floor by default (echoed in appliedCriteria.minLiquidityUsd) because without one the bonded population in a market-cap band is dominated by farmed tokens with a few dollars of liquidity; pass minLiquidityUsd to change it, 0 to remove it. Results are sorted by sortBy (marketCapUsd, volume1hUsd or txns1h) in sortOrder, rows without the sort value last. The screen reads the leading candidates in that order, so a very narrow screen can return fewer rows than exist; unverified and counts show how much was read. ONLY SOL IS SERVED — every other chain 400s naming itself.

Chains

  • Solana SOL

Request

Send your key in the x-dex-data-key header. Replace each <placeholder> with a real value.

curl -H "x-dex-data-key: $DEXDATA_API_KEY" \
  "https://api.dexdata.io/api/external/discovery/token-screen/SOL"
Parameters
ParameterDescription
stage

query · string · optional

Optional. "bonded" (left the bonding curve; graduated, migrated) or "bonding" (still on the curve). Omit it to screen both stages at once, and set it only when the user says bonded/graduated or on the curve.bondedbonding
minMarketCapUsd

query · number · optional

Lowest USD market cap, inclusive; every reading known must pass it.
maxMarketCapUsd

query · number · optional

Highest USD market cap, inclusive; every reading known must pass it.
minHolders

query · integer · optional

Fewest holders, inclusive.
maxTop10HolderPct

query · number · optional

Highest share of supply in the ten largest wallets, 0-100, inclusive.
minCurvePct

query · number · optional

stage=bonding only; a 400 without it. Lowest curve completion, 0-100, inclusive.
maxCurvePct

query · number · optional

stage=bonding only; a 400 without it. Highest curve completion, 0-100, inclusive.
minLiquidityUsd

query · number · optional

Bonded rows only: stage=bonded, or no stage (curve rows are not checked on it); a 400 on stage=bonding. Lowest USD liquidity, inclusive. Defaults to the deployment floor; 0 removes it.
createdWithinHours

query · number · optional

Created in the last N hours, above 0 and at most 720. Not with createdAfterUnixTime.
createdAfterUnixTime

query · integer · optional

Created at or after this Unix time, seconds. Not with createdWithinHours.
excludeSpam

query · boolean · optional

Keep only rows whose spam is false. Default false.
excludeManipulationRisk

query · boolean · optional

Keep only rows whose manipulationRisk.flagged is false. Default false.
sortBy

query · string · optional

marketCapUsd (default), volume1hUsd or txns1h (1-hour activity).marketCapUsdvolume1hUsdtxns1h
sortOrder

query · string · optional

desc (default) or asc.ascdesc
limit

query · integer · optional

Rows to return, 1-50. Default 20. limit ≤ 30 keeps the answer under 32 KB.
chain

path · string · required

Only SOL answers this endpoint — every other chain 400s naming itself rather than returning a blank not-found.

Response fields

A JSON response. Every field is always present; null means the value could not be established, never zero.

Response fields of Screen launchpad tokens by market cap, holders, top-10 %, curve and spam
FieldTypeDescription
stagestringEchoes the requested stage, or "all" when none was given and both were screened.
sortBystring
sortOrderstring
appliedCriteriaobjectThe criteria applied, defaults included; null means not applied. A query parameter this endpoint does not declare is refused with a 400 that names it, so a misspelled criterion never goes unapplied.
appliedCriteria.minMarketCapUsdnumber | null
appliedCriteria.maxMarketCapUsdnumber | null
appliedCriteria.minLiquidityUsdnumber | nullThe liquidity floor applied to bonded rows, the caller's or the default: every row on stage=bonded, only the bonded rows when no stage was given. null on stage=bonding.
appliedCriteria.minHoldersnumber | null
appliedCriteria.maxTop10HolderPctnumber | null
appliedCriteria.minCurvePctnumber | null
appliedCriteria.maxCurvePctnumber | null
appliedCriteria.createdAfterUnixTimenumber | nullUnix seconds; createdWithinHours resolved against the time the screen ran.
appliedCriteria.excludeSpamboolean
appliedCriteria.excludeManipulationRiskboolean
appliedCriteria.limitnumber
resultsobject[]Rows that passed EVERY criterion on a known value, in sort order.
results[].addressstringThe token mint. Identify rows by address, never by symbol.
results[].namestring | nullThe token name, or null when none was reported.
results[].symbolstring | nullThe ticker, or null when none was reported.
results[].bondedboolean | nullWhether the token has left its launchpad bonding curve for a regular pool. null when unknown, or when two independent readings disagree.
results[].curvePctnumber | nullBonding-curve completion, 0-100, while still on the curve; null once bonded or when unknown.
results[].marketCapUsdnumber | nullUSD market capitalisation, or null when unknown; the figure rows are sorted on. A market-cap bound is also checked on a second reading taken from the deepest pool, and a row passes only when both do. null on a bonded row whose figures were implausible and the pool did not confirm the market cap.
results[].liquidityUsdnumber | nullPooled USD liquidity, or null when unknown. On stage=bonding it counts the curve, not a tradeable pool; with no stage it is null on every row that is not bonded, for the same reason. On a bonded row whose figures were implausible it is the pools' own total, or null when that is implausible too.
results[].holdersnumber | nullWallets holding the token, or null when unknown.
results[].top10HolderPctnumber | nullShare of supply held by the ten largest wallets, 0-100, with pools and burn addresses excluded — the same figure GET /token-analysis/distribution publishes as top10Pct. null when unknown.
results[].spamboolean | nulltrue when any spamReasons applies; false only when mint authority, freeze authority and the rugged flag are all known and clear; null otherwise.
results[].spamReasonsstring[]Why spam is true: "mint-authority-active" (the deployer can still create supply), "freeze-authority-active" (the deployer can freeze any holder's account, which makes the token unsellable), "rugged" (its liquidity was pulled). Empty when none applies.
results[].mintAuthorityActiveboolean | nullWhether a mint authority is still set. null when unknown.
results[].freezeAuthorityActiveboolean | nullWhether a freeze authority is still set. null when unknown.
results[].ruggedboolean | nullWhether the token is flagged as rugged (liquidity pulled). null when unknown.
results[].createdAtUnixTimenumber | nullUnix seconds of the token's creation, or null when unknown.
results[].createdAtIsostring | nullThe same instant as createdAtUnixTime, as ISO 8601 UTC, e.g. 2026-09-20T09:16:16Z. null exactly when createdAtUnixTime is null.
results[].volume1hUsdnumber | nullUSD traded in the last hour, or null when unknown.
results[].txns1hnumber | nullTrades in the last hour, or null when unknown.
results[].manipulationRiskobjectWhether the token's market looks manufactured (bot-driven buying into thin liquidity) rather than traded. Read from the same evidence as the other fields, never from top-10 concentration alone: a supply spread evenly across thousands of fresh wallets shows a tiny top-10 share.
results[].manipulationRisk.flaggedboolean | nulltrue when any reason applies; false when every check could be made and none applies; null otherwise.
results[].manipulationRisk.reasonsobject[]Why flagged is true, each with the figure measured and the threshold it crossed. Empty when none applies.
results[].manipulationRisk.reasons[].reasonstring"market-cap-far-above-liquidity": the market cap of the token's pools outside the bonding curve is at least threshold times their liquidity, so the price could not absorb a sale. "one-sided-buying": buys are at least threshold of all trades (0-1). "even-holder-spread": the top-10 share is at most threshold times what an even split across every holder gives ten wallets.
results[].manipulationRisk.reasons[].valuenumberThe figure measured, in the same unit as threshold.
results[].manipulationRisk.reasons[].thresholdnumberThe threshold it crossed.
results[].manipulationRisk.reasons[].evidenceobjectThe readings value was computed from: marketCapUsd and liquidityUsd, buys and sells (trade counts), or holders and top10HolderPct.
unverifiedobject[]Rows that failed no criterion but could not be checked on at least one (at most 50 listed; counts.unverified has the total). Never treat these as matches.
unverified[].addressstring
unverified[].missingstring[]The criteria that could not be checked.
countsobject
counts.candidatesnumberCandidates read in sort order after their listed values were checked.
counts.checkednumberCandidates whose full evidence was fetched.
counts.matchednumberRows returned in results.
counts.droppednumberChecked candidates that failed a criterion.
counts.unverifiednumberChecked candidates missing a value for some criterion.
counts.manipulationRiskFlaggednumberChecked candidates whose manipulationRisk.flagged is true, whether or not they were excluded.
counts.byStageobjectOnly when no stage was given: the same five counts for each stage, by the list the candidate was read from. A token read in both counts once, as bonded.
counts.byStage.bondedobject
counts.byStage.bonded.candidatesnumber
counts.byStage.bonded.checkednumber
counts.byStage.bonded.matchednumber
counts.byStage.bonded.droppednumber
counts.byStage.bonded.unverifiednumber
counts.byStage.bondingobject
counts.byStage.bonding.candidatesnumber
counts.byStage.bonding.checkednumber
counts.byStage.bonding.matchednumber
counts.byStage.bonding.droppednumber
counts.byStage.bonding.unverifiednumber

Start building with DexData today

Sign in, create a key and make your first call in a minute. Free credits every month, and you only pay for calls that succeed.

Get a free API key