---
title: "Multi-KOL coordination signals (PRO+)"
method: GET
path: "/kol/coordination"
tags: ["KOL"]
---

# Multi-KOL coordination signals (PRO+)

`GET /kol/coordination`

## Request

- Base URL: `https://madeonsol.com/api/v1`
- URL: `https://madeonsol.com/api/v1/kol/coordination`
- Auth: HTTP bearer

Detect tokens being traded by multiple KOLs within a window. **PRO+** — the live signal includes participating KOL wallet addresses. 3+ convergent KOLs is often a leading signal. Stablecoins / wSOL / LSTs are always filtered; established memecoins (WIF, BONK, POPCAT) are filtered by default — pass `include_majors=true` to see them. `peak_*` fields describe the densest buy cluster inside the period. Results are sorted by `coordination_score` over a fixed universe — the top 150 clusters by (kol_count DESC, net_sol_flow DESC) — and every filter runs inside it (see `universe`; since 2026-09-21 — previously only the first `limit` clusters, ×3 with filters, were scored).

## Query parameters

- `include` 'risk'
- `period` '1h' | '6h' | '24h' | '7d'
- `min_kols` integer
- `limit` integer
- `min_avg_winrate` number
- `unique_strategies` boolean
- `include_majors` boolean
- `window_minutes` integer
- `min_score` integer
- `min_mc_usd` number
- `max_mc_usd` number

## Response `200`

OK

- object
  - `coordination` CoordinationCluster[]
    - `token_mint` string
    - `token_symbol` string, nullable
    - `token_name` string, nullable
    - `kol_count` integer
    - `total_buys` integer
    - `total_sells` integer
    - `net_sol_flow` number
    - `signal` 'accumulating' | 'distributing'
    - `avg_winrate_7d` number, nullable: Mean 7d winrate across the cluster's KOLs
    - `entry_rank_avg` number, nullable: Avg early-entry percentile (lower = earlier in the trade)
    - `unique_strategies` integer: Count of distinct auto_strategy_tag values across the KOLs
    - `strategies` string[]
    - `first_buy_at` string, date-time, nullable
    - `last_buy_at` string, date-time, nullable
    - `time_to_consensus_sec` integer, nullable: Seconds between first and last KOL buy (full-period span)
    - `peak_window_start` string, date-time, nullable: Start of densest buy cluster (default 15-min window)
    - `peak_window_end` string, date-time, nullable
    - `peak_kols` integer, nullable: Distinct KOLs buying inside the peak window
    - `peak_buys` integer, nullable: Total buys inside the peak window
    - `exited_count` integer: KOLs in the cluster whose sell_sol > buy_sol (net-flow-negative)
    - `holders_count` integer: kol_count − exited_count (still net-long)
    - `coordination_score` integer: Composite 0-100 signal score. Weighting exposed via top-level score_version.
    - `market_cap_usd_at_first_buy` number, nullable: Market cap (USD) stamped on the cluster's chronologically-first KOL buy. Distinguishes coordinated accumulation at micro-cap from late-stage chasing.
    - `market_cap_usd` number, nullable: Current market cap (USD) of the token, sourced from token_prices. Compare against market_cap_usd_at_first_buy for the cluster's MC delta.
    - `last_price_usd` number, nullable: Current last-trade price (USD).
    - `mc_change_pct` object: Market-cap % change over each window (e.g. 12.4 = +12.4%). Sparse — only windows with enough mc-tracker history are present. Use to tell whether the cluster is firing into a moving token or before the move.
      - `5m` number, nullable
      - `15m` number, nullable
      - `1h` number, nullable
      - `2h` number, nullable
      - `4h` number, nullable
    - `volume_usd` object: Organic (non-MEV) USD volume over each window. Sparse — same gating as mc_change_pct.
      - `5m` number
      - `15m` number
      - `1h` number
      - `2h` number
      - `4h` number
    - `mev_volume_pct` object: MEV-share of total volume over each window (0-100). High value = bot-heavy / sandwich-heavy flow.
      - `5m` number, nullable
      - `15m` number, nullable
      - `1h` number, nullable
      - `2h` number, nullable
      - `4h` number, nullable
    - `history_age_seconds` integer, nullable: Seconds of mc-tracker history available for this token (capped at 4h05m). Tells you which windows can be trusted. Null when token is untracked.
    - `kols` unknown[]: BASIC: array of KOL names (first 3). PRO+: objects {name, wallet, buy_sol, sell_sol, exited} — full wallet addresses on every tier that can call the endpoint (BASIC gets 403 on /kol/coordination).
      - unknown
  - `period` string
  - `min_kols` integer: Echo of the applied min_kols.
  - `window_minutes` integer: Echo of the applied peak-density window (minutes).
  - `score_version` string: Bumps when score weights change; clients can pin logic to a known version.
  - `universe` object: The clusters the ranking was computed over (audit F09 follow-up, 2026-09-21): the top `max_size` by (kol_count DESC, net_sol_flow DESC) for the period/min_kols/window. Every filter (min_score, min_avg_winrate, unique_strategies, MC band) and the coordination_score sort run inside this universe, so a filtered result is always a subset of the unfiltered ranking. `truncated_at_max`=true means more clusters exist below the cap.
    - `kind` 'top_by_kol_count'
    - `order` string
    - `max_size` integer
    - `size` integer
    - `truncated_at_max` boolean

## Other responses

- `401`: Missing or invalid API key, or an expired free-tier key. Authentication-stage error: no `X-RateLimit-*` headers, no `_rid`.
- `403`: Forbidden. One of: the key's tier is below this endpoint's or parameter's gate (`tier_required` with an `upgrade` block); the public demo key used outside its allow-list (`demo_key_endpoint_not_allowed`); an invalid or revoked key; an origin-restricted key called from a disallowed origin (`code` `origin_not_allowed` / `origin_required`). `X-RateLimit-*` headers are present only on `tier_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`: 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)
