Skip to content

API docs

Bundle checks for your bot, terminal or dashboard. One JSON call says how much of a Solana token was bundled at launch, and by whom, seconds after any launch on pump.fun, Meteora or Bonk.

Base URL
https://bundled.wtf/api/v1
Auth
API key
Try it
Free, on this page
Batch
100 per call
On this page
Get started

Quickstart

Try any token free in the box below, no key needed. From your own code, it's three steps.

  1. 1

    Get an API key

    Burn bundled.wtf tokens for one, below. No sign-up and nothing to connect.
  2. 2

    Ask about a token

    Send its mint to /api/v1/token/, with the key in the x-api-key header. A bonding curve or pool address works too.
  3. 3

    Read the verdict

    status is the one word: bundled, no_bundle, proxima and a few more. bundledPct is 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.

Request
curl https://bundled.wtf/api/v1/token/B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump \
  -H "x-api-key: $BUNDLED_KEY"
200 OK
{
  "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 retryAfter in seconds, and a Retry-After header
Caching
Answers are cached for 15 seconds, so asking more often than that gains nothing
401 without a key
{
  "error": "api_key_required",
  "docs": "https://bundled.wtf/docs#api-key"
}
Waiting out a 429
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

Burn

Burn 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.

Endpoints

One token

GET/api/v1/token/{address}

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

mint
string
The token's mint, whichever address you asked with.
name, symbol
string | null
As set at launch.
launchpad
string | null
Where it launched: pump.fun, Meteora DBC, Bonk or LaunchLab.
launchedAt
number | null
Unix seconds.
dev
string | null
The creator's wallet.
nsfw
boolean
Its art, name or ticker is explicit. We check every launch's art with an image model, so you can hide it.

The verdict

status
string
One word for the launch. See Statuses.
bundledPct
number | null
Share of supply bought in bundles at launch: the creator's own bundle plus other bundles. The headline number.
creatorBundlePct
number | null
Bought in the creator's bundle, by wallets other than the creator. A creator who launched alone counts 0.
otherBundlesPct
number | null
Bought in other bundles in the launch block.
firstSecondPct
number | null
Bought in the first second, bundled or not.
devBoughtPct
number | null
The creator's own buy at launch.
bundleWallets
number | null
Wallets in the creator's bundle, creator excluded.
estimate
boolean
true while a launch is seconds old and Jito hasn't confirmed its bundle yet. Ask again in a minute.

The creator

devLaunches7d, devBundled7d
number | null
The creator's launches in the 7 days up to this one, and how many were bundled.

Tools

madeWithProxima
boolean
Bought through Proxima's router at launch.
proximaAfterLaunch
boolean
Proxima's router used later, not at launch.
madeWithSumo, madeWithUxento
boolean | null
Launched with those tools. null when it couldn't be told.

From a full report

risk
string | null
low, medium, high or extreme. 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.
insidersHoldPct
number | null
Share still held by the creator, its bundle and Proxima buyers.
flaggedHoldPct
number | null
Share still held by every flagged wallet.
fundedTogether, throwawayFunded, wokenWallets
number | null
Insiders funded from one source, through throwaway wallets, or idle wallets funded just before launch.
reportAt
number | null
When that report was built, in unix seconds.

Links

report
string
The token's page on bundled.wtf. Link to it when you show this data.
migration
object | 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, like risk; null otherwise.
Request
curl https://bundled.wtf/api/v1/token/B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump \
  -H "x-api-key: $BUNDLED_KEY"
200 OK
{
  "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

GETPOST/api/v1/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

mints
string[]
POST, as JSON: {"mints": [...]}. Or GET, comma-separated: ?mints=A,B.
Request
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"
200 OK
{
  "tokens": [
    { "mint": "B3uyxsQ7GzpN6TWwXkg6kGpJD5yhGi3R4ppiMfzXpump", "status": "bundled", "bundledPct": 21.7, … },
    { "mint": "2CQaTyBy3NNratRNaJp7U7ruADF8mYB353pGmUasYELL", "status": "no_bundle", "bundledPct": 0.0, … }
  ]
}

Wallets

GETPOST/api/v1/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

wallets
string[]
Full or shortened addresses. POST as JSON, or GET comma-separated: ?wallets=A,B.
mint
string, optional
A token, for each wallet's roles on it. A curve or pool works too.

Each wallet

query
string
What you sent, as you sent it.
address
string | null
The full address. null when a shortened one matched no wallet, or more than one.
known
boolean
We've seen it in a launch before.
roles
string[]
Its roles on mint, most telling first. See Wallet roles. Empty without mint.
bundlerLaunches, proximaLaunches, sumoLaunches, snipedLaunches
number
Other launches it bundled, bought through Proxima or Sumo, or sniped. mint itself isn't counted.
lastSeen
number | null
Its latest launch, in unix seconds.
pnlSol
number | null
Realized profit in SOL. null until its trades have been read.
page
string | null
The wallet's page on bundled.wtf.
Request
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"]}'
200 OK
{
  "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"
    }
  ]
}
Reference

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.

400invalid_mintThe address isn't a Solana address.
400no_mintsNo mints sent to /tokens.
400no_walletsNo wallets sent to /wallets.
401api_key_requiredNo x-api-key header. Every call needs one, except from the Try it box on this page.
401invalid_api_keyThe x-api-key header names no key, or one that was replaced.
429rate_limitedOver the limit. retryAfter, also sent as the Retry-After header, says how many seconds to wait.
500internalOur fault. Try again shortly.

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.