---
title: "Early-buyer quality on a Robinhood Chain token (BASIC+)"
method: GET
path: "/rhc/tokens/{address}/buyer-quality"
tags: ["Robinhood Chain"]
---

# Early-buyer quality on a Robinhood Chain token (BASIC+)

`GET /rhc/tokens/{address}/buyer-quality`

## Request

- Base URL: `https://madeonsol.com/api/v1`
- URL: `https://madeonsol.com/api/v1/rhc/tokens/{address}/buyer-quality`
- Auth: HTTP bearer

A 0–100 quality read on a token's earliest distinct buyer cohort (first 20), derived live from `rhc_trades` and enriched with `mv_rhc_alpha_wallets` history. Full parity with the Solana scorer: win-rate, KOL-presence, bot-domination and **bundle-buyer** legs (a bundled early buyer in the top 10 costs −5; a heavily bundled cohort of >10 costs −15), plus the **dump-cluster ensemble** — `dump_cluster_count` counts early buyers that repeatedly sit in launches that crashed off their own peak (rolling 42-day model, out-of-sample validated on RHC). Dump-cluster is **informational**: it flags the pattern but does not move the score. Tier: **BASIC** (any valid key).

## Path parameters

- `address` string, required

## Query parameters

- `include_balances` boolean

## Response `200`

OK. Neutral score (50) with `note` when the token has no buyer history yet.

- object
  - `chain` 'robinhood'
  - `token_address` string
  - `current_mc_usd` number, nullable
  - `cohort_selection` 'distinct_first_buy' | 'legacy_row_window': distinct_first_buy = the first 20 DISTINCT buyer EOAs by their first buy (block, tx index, log index), selected before the limit. legacy_row_window = pre-rhc/011 fallback (oldest 300 buy rows, deduped — a repeat buyer can crowd out later distinct buyers); served only until that migration is applied.
  - `dump_cluster_held_now` object: Only with include_balances=true (PRO+, 2026-10-15, TR-09): the early buyers counted in dump_cluster_count and what they hold NOW from balances. Totals only when every member was read.
    - `cohort_size` integer
    - `members` integer: Dump-cluster members among the early buyers (= dump_cluster_count).
    - `held_now` object: Same shape as the bundle held_now of this chain: source, checked_at, wallets, verified_wallets, holding_wallets, complete, incomplete_reason, tokens_held_raw, tokens_held, held_pct_of_supply (ratio), supply_basis.
    - `wallets` object[]
      - `wallet` string
      - `balance_now` object, nullable
    - `note` string
  - `quality` object
    - `score` integer
    - `confidence` 'insufficient_data' | 'low' | 'medium' | 'high': Confidence in the PREDICTIVE inputs: counts only buyers whose win rate fed the score (≥3 tokens of history, not bot-flagged, not zero-cost-dump dominated). insufficient_data = none did — the score is the neutral-50 default plus penalties. 1 → low, 5+ → medium, 11+ → high.
    - `signal` 'positive' | 'neutral' | 'negative'
    - `breakdown` object
      - `wallets_with_history` integer: Buyers with ≥3 tokens of history (cohort identification — not predictive)
      - `qualified_win_rate_wallets` integer: Buyers whose win rate fed the score — the basis of confidence
      - `early_buyers_analyzed` integer
      - `alpha_wallet_count` integer
      - `kol_count` integer
      - `bundle_buyer_count` integer: Early buyers flagged as part of a same-block launch bundle (mig 255).
      - `dump_cluster_count` integer: Early buyers on the rolling dump-cluster list (≥5 crashed-off-peak cohorts, 0 runner cohorts, trailing 42d, OOS-validated). Informational — high count = strong dump signal.
      - `recycled_early_buyer_count` integer: Early buyers with ≥5 recent early-buyer appearances of any kind (dump_cluster_count is a subset).
      - `avg_historical_win_rate` number, nullable: Percent (0–100), non-bot buyers with ≥3 tokens of history.
      - `bot_dominated` boolean
  - `coverage` object: Signal availability. Dump-cluster is available but informational (does not move the score).
    - `bundle_detection` 'available'
    - `dump_cluster_signal` 'available'
    - `note` string
    - `earliest_buyers_caveat` string: For launches before 2026-07-18 the earliest-buyers cohort is the earliest 20 ATTRIBUTED buyers (trader_eoa backfill pending), not necessarily the first 20 buyers.
  - `note` string: Present only when buyer data is insufficient.

## 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.
- `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/d9531a28d83b?raw)
