Quickstart
Try any token free in the box below, no key needed. From your own code, it's three steps.
- 1
Get an API key
Burn bundled.wtf tokens for one, below. No sign-up and nothing to connect. - 2
Ask about a token
Send its mint to/api/v1/token/, with the key in thex-api-keyheader. A bonding curve or pool address works too. - 3
Read the verdict
statusis the one word:bundled,no_bundle,proximaand a few more.bundledPctis how much of the supply was bought in bundles at launch. Every number is a percentage of total supply.
Watching many tokens? Send up to 100 at once to /tokens, and check wallets with /wallets.
curl https://bundled.wtf/api/v1/token/B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump \ -H "x-api-key: $BUNDLED_KEY"
{
"mint": "B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump",
"status": "bundled",
"bundledPct": 21.7,
"bundleWallets": 3,
"firstSecondPct": 21.7,
"devBundled7d": 1,
"report": "https://bundled.wtf/B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump"
…
}Try it
Paste any mint, curve or pool and see the live answer. Free here, up to 200 a day; from your own code, the API needs a key.
Keys and limits
Every call needs an API key, sent in the x-api-key header. A key gets 15 requests a second, and a batch call counts once, whatever it holds. Keep it on your server: anyone holding it uses your limit.
Without a key, the API answers only the Try it box on this page.
Only the /api/v1 paths are the API. The site's other endpoints change without notice, can't be called from other websites' pages, and are limited per visitor, so build on v1.
- API key
- 15 a second, per key
- Without a key
- Only Try it on this page: 20 a minute, 200 a day
- Over the limit
- HTTP 429 with
retryAfterin seconds, and aRetry-Afterheader - Caching
- Answers are cached for 15 seconds, so asking more often than that gains nothing
{
"error": "api_key_required",
"docs": "https://bundled.wtf/docs#api-key"
}async function get(url) { const res = await fetch(url, { headers: { "x-api-key": process.env.BUNDLED_KEY } }); if (res.status === 429) { // Wait as long as the API says, then try again. const { retryAfter } = await res.json(); await new Promise((r) => setTimeout(r, retryAfter * 1000)); return get(url); } return res.json(); }
Get an API key
BurnBurn 1,000,000 bundled.wtf tokens for an API key. There's no wallet to connect and nothing to sign: the burn's last decimals are your claim number, and this page holds the secret that unlocks the key.
One token
Everything we know about one launch. address is the mint, or its bonding curve or pool. A token we haven't seen still answers 200, with status: "unscanned" and every number null.
The token
- mintstring
- The token's mint, whichever address you asked with.
- name, symbolstring | null
- As set at launch.
- launchpadstring | null
- Where it launched:
pump.fun,Meteora DBC,BonkorLaunchLab. - launchedAtnumber | null
- Unix seconds.
- devstring | null
- The creator's wallet.
- nsfwboolean
- Its art, name or ticker is explicit. We check every launch's art with an image model, so you can hide it.
The verdict
- statusstring
- One word for the launch. See Statuses.
- bundledPctnumber | null
- Share of supply bought in bundles at launch: the creator's own bundle plus other bundles. The headline number.
- creatorBundlePctnumber | null
- Bought in the creator's bundle, by wallets other than the creator. A creator who launched alone counts 0.
- otherBundlesPctnumber | null
- Bought in other bundles in the launch block.
- firstSecondPctnumber | null
- Bought in the first second, bundled or not.
- devBoughtPctnumber | null
- The creator's own buy at launch.
- bundleWalletsnumber | null
- Wallets in the creator's bundle, creator excluded.
- estimateboolean
- true while a launch is seconds old and Jito hasn't confirmed its bundle yet. Ask again in a minute.
The creator
- devLaunches7d, devBundled7dnumber | null
- The creator's launches in the 7 days up to this one, and how many were bundled.
Tools
- madeWithProximaboolean
- Bought through Proxima's router at launch.
- proximaAfterLaunchboolean
- Proxima's router used later, not at launch.
- madeWithSumo, madeWithUxentoboolean | null
- Launched with those tools. null when it couldn't be told.
From a full report
- riskstring | null
low,medium,highorextreme. Set when someone opened the token's page in the last 6 hours, which builds a full report; null otherwise. The other fields here work the same way.- insidersHoldPctnumber | null
- Share still held by the creator, its bundle and Proxima buyers.
- flaggedHoldPctnumber | null
- Share still held by every flagged wallet.
- fundedTogether, throwawayFunded, wokenWalletsnumber | null
- Insiders funded from one source, through throwaway wallets, or idle wallets funded just before launch.
- reportAtnumber | null
- When that report was built, in unix seconds.
Links
- reportstring
- The token's page on bundled.wtf. Link to it when you show this data.
- migrationobject | null
- A token moved over from an old one:
{"platform": "migrate.fun", "vaultPct": 88.2, "leftPct": 53.6}, the share its claim vault took for the old token's holders and what's still waiting there. It isn't a bundle. From a recent full report, likerisk; null otherwise.
curl https://bundled.wtf/api/v1/token/B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump \ -H "x-api-key: $BUNDLED_KEY"
{
"mint": "B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump",
"status": "bundled",
"name": "TSM",
"symbol": "TSM",
"launchpad": "pump.fun",
"launchedAt": 1792048679,
"nsfw": false,
"bundledPct": 21.7,
"creatorBundlePct": 21.7,
"otherBundlesPct": 0.0,
"firstSecondPct": 21.7,
"devBoughtPct": 0.0,
"bundleWallets": 3,
"dev": "9UmpSL2GxeLz9qTBNC65ARSVhA6BqXyP8pdeZjhHw2dk",
"devLaunches7d": 1,
"devBundled7d": 1,
"madeWithProxima": false,
"proximaAfterLaunch": false,
"madeWithSumo": false,
"madeWithUxento": false,
"estimate": false,
"risk": null,
"insidersHoldPct": null,
"flaggedHoldPct": null,
"fundedTogether": null,
"throwawayFunded": null,
"wokenWallets": null,
"reportAt": null,
"migration": null,
"report": "https://bundled.wtf/B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump"
}Many tokens
Up to 100 tokens in one call, answered in the order you sent them. Each one is the same object as One token. Past 100, the rest are left out.
Parameters
- mintsstring[]
- POST, as JSON:
{"mints": [...]}. Or GET, comma-separated:?mints=A,B.
curl -X POST https://bundled.wtf/api/v1/tokens \ -H "x-api-key: $BUNDLED_KEY" \ -H "content-type: application/json" \ -d '{"mints": ["B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump", "2CQaTyBy3NNratRNaJp7U7ruADF8mYB353pGmUasYELL"]}' # Or as a query, comma-separated curl "https://bundled.wtf/api/v1/tokens?mints=B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump,2CQaTyBy3NNratRNaJp7U7ruADF8mYB353pGmUasYELL" \ -H "x-api-key: $BUNDLED_KEY"
{
"tokens": [
{ "mint": "B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump", "status": "bundled", "bundledPct": 21.7, … },
{ "mint": "2CQaTyBy3NNratRNaJp7U7ruADF8mYB353pGmUasYELL", "status": "no_bundle", "bundledPct": 0.0, … }
]
}Wallets
Up to 100 wallets: what they did on a token, and their record on others. Shortened addresses as terminals show them, B8JMDN...ARvnVU or B8JMDN…ARvnVU, are matched against every wallet we've seen.
Parameters
- walletsstring[]
- Full or shortened addresses. POST as JSON, or GET comma-separated:
?wallets=A,B. - mintstring, optional
- A token, for each wallet's roles on it. A curve or pool works too.
Each wallet
- querystring
- What you sent, as you sent it.
- addressstring | null
- The full address. null when a shortened one matched no wallet, or more than one.
- knownboolean
- We've seen it in a launch before.
- rolesstring[]
- Its roles on
mint, most telling first. See Wallet roles. Empty withoutmint. - bundlerLaunches, proximaLaunches, sumoLaunches, snipedLaunchesnumber
- Other launches it bundled, bought through Proxima or Sumo, or sniped.
mintitself isn't counted. - lastSeennumber | null
- Its latest launch, in unix seconds.
- pnlSolnumber | null
- Realized profit in SOL. null until its trades have been read.
- pagestring | null
- The wallet's page on bundled.wtf.
curl -X POST https://bundled.wtf/api/v1/wallets \ -H "x-api-key: $BUNDLED_KEY" \ -H "content-type: application/json" \ -d '{"mint": "B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump", "wallets": ["B8JMDN...ARvnVU"]}'
{
"mint": "B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump",
"wallets": [
{
"query": "B8JMDN...ARvnVU",
"address": "B8JMDNsTNnRa5QfiodHgqxfES4yfK2D2iNAdNhARvnVU",
"known": true,
"roles": ["bundle"],
"bundlerLaunches": 11,
"proximaLaunches": 0,
"sumoLaunches": 0,
"snipedLaunches": 0,
"lastSeen": 1792048820,
"pnlSol": 61.3,
"page": "https://bundled.wtf/B8JMDNsTNnRa5QfiodHgqxfES4yfK2D2iNAdNhARvnVU"
}
]
}Statuses
status sums up a launch in one word. When more than one fits, the first one here wins.
- proxima
- Bought through Proxima's router at launch: a bundle made to look like separate buyers.
- sumo
- Launched with Sumo, a bundling tool.
- proxima_after_launch
- Proxima's router used after launch, not in the launch block.
- bundled
- Supply bought in a Jito bundle with the creation.
- no_bundle
- Nothing bundled: the creator launched alone, or with their own buy only.
- unscanned
- We haven't seen this token. Every number is null.
Wallet roles
What a wallet did on a token, as /wallets lists them, most telling first. The first three are insiders.
- creator
- Created the token.
- bundle
- Bought in the creator's bundle.
- proxima
- Bought through Proxima's router.
- sumo
- Bought with Sumo.
- handoff
- Bought back what an insider had just sold, seconds later.
- got_tokens
- Was sent tokens by an insider.
- linked
- Got its SOL from a flagged wallet.
- first_second
- Bought in the first second.
- sniper
- A sniper bot: bought right behind the creation.
Errors
Errors come back as JSON with an error code, so you can branch on it rather than on the message.
Terms
Free to use. When you show this data to people, link to the token's page on bundled.wtf: it's the report field. These are on-chain signals, not financial advice.