---
title: "Every coordinated buy cluster on a token, launch and later (PRO+)"
method: GET
path: "/tokens/{mint}/bundles"
tags: ["Tokens"]
---

# Every coordinated buy cluster on a token, launch and later (PRO+)

`GET /tokens/{mint}/bundles`

## Request

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

Every slot in the window where at least `min_wallets` distinct wallets bought the token, the launch bundle AND clusters that enter later (2026-10-15). `/tokens/{mint}/bundle` remains the launch-cohort view (first 20 early buyers). Per cluster: slot, time, `minutes_after_launch` + `phase`, `wallet_count`, `new_wallets` (no earlier buy of the token), `atomic_txs` (transactions carrying 3+ of them = definitively coordinated), SOL and token volume, wallets. `summary.baseline` gives the window's buys per active slot, because on very busy tokens unrelated buyers share slots: a cluster is evidence, not a verdict. Only STORED buys count (persistence floor 0.05 SOL / $3.50 stable leg; rows before 2026-06-17 have no slot). `include_balances=true` adds `held_now` (current balances from the chain) to the 3 most recent clusters.

## Path parameters

- `mint` string, required

## Query parameters

- `window` '1h' | '6h' | '24h'
- `min_wallets` integer
- `limit` integer
- `include_balances` boolean

## Response `200`

OK. An empty clusters array means no slot/block in the window had min_wallets distinct buyers.

- object
  - `mint` string
  - `window` string
  - `min_wallets` integer
  - `launch_at` string, date-time, nullable
  - `summary` object
    - `cluster_count` integer
    - `launch_clusters` integer
    - `later_clusters` integer
    - `latest_cluster_at` string, date-time, nullable
    - `largest_cluster_wallets` integer
    - `baseline` object, nullable: Window baseline (null when no cluster was found): active units, buys in window, buys per active unit. On busy tokens unrelated buyers share slots.
  - `clusters` object[]
    - `slot` integer
    - `atomic_txs` integer
    - `sol_volume` number, nullable
    - `token_volume` number, nullable
    - `at` string, date-time
    - `minutes_after_launch` number, nullable
    - `phase` 'launch' | 'later' | 'unknown': launch = within 5 minutes of launch_at.
    - `wallet_count` integer
    - `new_wallets` integer: Buyers with no earlier buy of this token.
    - `wallets` string[]: At most 50.
    - `held_now` object: Only with include_balances=true, on the 3 most recent clusters: same shape as the bundle held_now of this chain; totals only when every wallet was read.
    - `exit` object, nullable: What this cluster's wallets have SOLD of the token since the cluster (bundle-watch sell ledger, migration 503). null = not followed (only clusters bundle-watch announced: >= 3 wallets new to the token; followed 7 days after detection; first 50 wallets).
      - `cluster_id` integer
      - `followed_until` string, date-time
      - `wallets_tracked` integer
      - `wallets_sold` integer
      - `wallets_exited` integer: Sold >= 99 % of their cluster buy.
      - `bought_tokens` number
      - `sold_tokens` number
      - `sold_pct` number, nullable: Sum over wallets of min(sold, bought in the cluster) / bought in the cluster, 0..1.
      - `realized_sol` number: Known proceeds only (migration 511); see realized_status.
      - `realized_status` 'complete' | 'incomplete', nullable: Migration 511: incomplete when at least one recorded sell has unknown proceeds (Solana price_status proceeds_unattributed, or no quote amount); its tokens count in sold_pct, its proceeds are NOT in realized_sol (never booked as 0). null = not measured (ledger before migration 511).
      - `unknown_proceeds_sells` integer, nullable: Recorded sells with unknown proceeds (see realized_status).
      - `last_sell_at` string, date-time, nullable
  - `held_now_clusters` integer: Only with include_balances=true.
  - `exit_tracking` 'ok' | 'unavailable' | 'error': Whether the exit ledger could be read; the clusters are served either way (exit null when not ok).
  - `exit_note` string
  - `note` string

## Other responses

- `400`: Invalid address or query parameters
- `401`: Missing or invalid API key, or an expired free-tier key. Authentication-stage error: no `X-RateLimit-*` headers, no `_rid`.
- `403`: Tier gate - PRO required.
- `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`: bundle_clusters_unavailable (SQL function not applied) or bundle_clusters_temporarily_unavailable (timeout).

---

[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/d9531a28d83b?raw)
