---
title: "Token bundle intelligence"
method: GET
path: "/tokens/{mint}/bundle"
tags: ["Tokens"]
---

# Token bundle intelligence

`GET /tokens/{mint}/bundle`

## Request

- Base URL: `https://madeonsol.com/api/v1`
- URL: `https://madeonsol.com/api/v1/tokens/{mint}/bundle`
- Auth: HTTP bearer

The token's **bundle cohort** — the same-slot wallets (≥3 buying in one slot, `is_bundle`) — and how much of supply they STILL hold, computed from confirmed on-chain trades (not a pre-execution shred feed). `held_pct_of_supply` (net held ÷ circulating supply) is the headline rug/insider signal; `bundle_kind` distinguishes a definitively-atomic single-tx bundle (`atomic_tx`) from a possibly-coincidental `same_slot` cohort. Field-gated on ALL tiers: BASIC gets the scalar `bundle` block; PRO adds the top-10 wallets (flags only); ULTRA adds the full cohort enriched with KOL/alpha identity. Caveats: `buy_volume` is cumulative buy volume (can exceed supply); `tokens_held` is a swap-derived net position, not a holder census. The `coverage` object (additive) separates 'no bundle cohort' from 'mint outside our launchpad trade capture'.

## Path parameters

- `mint` string, required

## Query parameters

- `include_balances` boolean

## Response `200`

OK

- TokenBundle
  - `mint` string
  - `bundle` object
    - `wallet_count` integer: Number of same-slot bundle wallets (is_bundle: ≥3 buying in one slot)
    - `bundle_kind` 'atomic_tx' | 'same_slot' | 'none': atomic_tx = ≥3 wallets share one buy tx (definitively atomic); same_slot = the ≥3-same-slot heuristic (possible coincidence); none = no cohort
    - `held_pct_of_supply` number, nullable: HEADLINE. Cohort net held ÷ circulating supply, 0–1 (clamped). null when supply is unknown
    - `held_ratio` number, nullable: Cohort net held ÷ buy_volume, 0–1. Churn-sensitive — secondary to held_pct_of_supply
    - `fully_exited` boolean
    - `buy_volume` number: Cumulative buy-side token volume — NOT distinct tokens; can exceed supply on round-tripping
    - `tokens_held` number: Swap-derived net position (Σbuys−Σsells) — a proxy for on-chain balance, not a holder census
    - `holdings_basis` 'swap_only' | 'swap_and_transfers': swap_only = token transfers are not applied: a member that transferred tokens out and sold elsewhere still reads as holding.
    - `bundle_detection` 'same_batch_block_time_second': How cohort membership is decided today: ≥3 wallets buying the mint in one ingest batch with the same block_time second (ingest wall-clock), not the same slot. A future value `same_slot` ships with BUNDLE_SLOT_DETECTION=on.
  - `wallets` object[]: BASIC: empty. PRO: top-10, flags only. ULTRA: full cohort + identity fields.
    - `rank` integer
    - `wallet` string
    - `held_ratio` number, nullable
    - `has_sold` boolean
    - `atomic` boolean: This wallet is part of an atomic single-tx bundle
    - `is_kol` boolean
    - `kol_name` string, nullable: ULTRA only
    - `win_rate` number, nullable: ULTRA only, 0–1
    - `bot_confidence` string, nullable: ULTRA only
    - `tokens_held` number: ULTRA only
    - `balance_now` object, nullable: Only with include_balances=true: this wallet's current balance of the mint (null when the cohort read failed).
      - `amount_raw` string
      - `decimals` integer, nullable
      - `amount` string
      - `holding` boolean
      - `token_accounts` integer
      - `slot` integer
  - `held_now` object: Only with include_balances=true (PRO+, 2026-10-15): the cohort's CURRENT balances, one owner read per wallet (every token account of the owner for the mint, either program). Totals only when every wallet was read; the bundle answer itself never fails on a balance read.
    - `source` 'solana_rpc_getTokenAccountsByOwner'
    - `checked_at` string, date-time
    - `wallets` integer
    - `verified_wallets` integer
    - `holding_wallets` integer
    - `complete` boolean
    - `incomplete_reason` string, nullable
    - `slot_min` integer, nullable
    - `slot_max` integer, nullable
    - `tokens_held_raw` string, nullable
    - `tokens_held` string, nullable
    - `held_pct_of_supply` number, nullable: RATIO in [0, 1] of circulating_supply_raw, like bundle.held_pct_of_supply.
    - `supply_basis` 'circulating_supply_raw' | 'null', nullable
  - `coverage` TradeCoverage: Coverage disclosure for endpoints backed by our persisted trade capture (`token_trades` / early-buyer data). Capture starts 2026-04-12 and persistence is gated to the launchpad pipeline (pump.fun, LaunchLab/bonk, bags) — it is NOT a full Solana trade history. Three separate answers (2026-09-21): `data_observed`/`in_scope` = at least one persisted row (presence, not completeness — a brand-new in-scope mint with no trades yet also reads false), `eligibility` = whether the CURRENT gate admits the subject, `completeness` = always `not_verified`. When no rows exist, zero/empty values mean 'not captured' (see eligibility for why), never 'no activity'.
    - `history_start` integer: Epoch seconds of the first persisted trade (2026-04-12).
    - `scope` string
    - `in_scope` boolean, nullable: Kept for compatibility — same value as data_observed: true = we hold ≥1 persisted trade for this subject · false = none persisted (see eligibility for why — a brand-new in-scope mint also reads false) · null = probe unavailable
    - `data_observed` boolean, nullable
    - `eligibility` 'eligible' | 'lapsed' | 'excluded' | 'unknown' | 'admitted_previously' | 'not_applicable' | 'null', nullable: Resolved against the EFFECTIVE production capture settings (refreshed every few minutes; if they cannot be confirmed the answer narrows, never widens). eligible = admitted by the current gate · lapsed = launched via our pipeline, capture window closed under the current settings · excluded = blacklisted · unknown = no evidence the gate admits it (most likely outside the launchpad pipeline; basis capture_state_unavailable = settings could not be confirmed, no claim either way) · admitted_previously = persisted rows prove past admission, current status not established · not_applicable = wallet subjects · null = lookup failed
    - `eligibility_basis` string, nullable: Evidence behind eligibility (e.g. unresolved_launch, recently_bonded, revived_curve, pipeline_known, launchlab_pool, bags_vanity_mint, launchpad_proven, resolved_launch, bonded_over_7d, revival_expired, blacklisted, persisted_rows, capture_state_unavailable, lookup_failed)
    - `completeness` 'not_verified'
    - `size_floor` object: Persistence size floor of the same write path (added 2026-09-30). Buys under 0.05 SOL (under $3.50 when paid in USDC/USDT) are not stored; sells that receive SOL are kept at any size. Live streams, prices and candles are not subject to it.
      - `min_sol` number
      - `min_stable_usd` number
      - `applies_to` string
    - `note` string: How to read the values (always present since 2026-09-21: eligibility-specific when no rows exist, a completeness caveat when they do).

## Other responses

- `401`: Missing or invalid API key, or an expired free-tier key. Authentication-stage error: no `X-RateLimit-*` headers, no `_rid`.
- `403`: include_balances=true needs PRO.
- `404`: Token not found or not tracked
- `429`: Too many requests. Every 429 carries `Retry-After`. A quota 429 (`rate_limit_exceeded`, with `X-RateLimit-*`), a heavy-query concurrency 429 (`error_kind` `concurrency`/`capacity`), or the per-IP authentication-failure block (30 failed auths/min; plain `error` + `retry_after_seconds`, no `X-RateLimit-*`).
- `500`: Unexpected server error from the route (`Internal server error`, with `_rid`). Safe to retry with backoff. A failed API-key lookup is a 503 `auth_backend_unavailable`, never a 500.
- `503`: Temporarily unavailable — a Postgres statement timeout while the dataset is under load or maintenance (`statement_timeout`, with `X-RateLimit-*` and `_rid`), or the API-key lookup itself unavailable (`auth_backend_unavailable`, authentication stage: no `X-RateLimit-*`, no `_rid`, not counted as a failed authentication). Always carries `Retry-After`; honour it.

---

[API](https://skmtc.dev/madeonsol/apis/madeonsol-api.md) · [All operations](https://skmtc.dev/madeonsol/apis/madeonsol-api/llms.txt) · [OpenAPI document](https://skmtc.dev/madeonsol/apis/madeonsol-api/revisions/96ce84657f55?raw)
