---
title: "List curated cohorts"
method: GET
path: "/v1/cohorts"
tags: ["Cohorts"]
---

# List curated cohorts

`GET /v1/cohorts`

## Request

- Base URL: `https://crowdintel.xyz/api`
- URL: `https://crowdintel.xyz/api/v1/cohorts`
- Auth: HTTP bearer

**Min tier: `free` (any valid key).** The cohort registry — every curated wallet cohort with its exact membership floor, default ranking, accepted sort keys and pagination depth cap. Hits no database, so it is the cheap discovery call to make before spending a `terminal` call on `/v1/cohorts/{slug}`.

A cohort is not a saved list: membership is recomputed on read from the pre-aggregated wallet rollups, so a wallet that stops clearing the floor leaves the cohort. Ranking is PnL-first — `pnl` is Polymarket's own reported figure when present, else CrowdIntel's on-chain ledger figure.

Seven cohorts are currently enabled (`profit-leaders`, `six-figure-club`, `deep-sample-winners`, `high-confidence-sharps`, `whale-class`, `fresh-faces-90d`, `market-maker-bots`). The six category cohorts (`best-sports-traders`, `best-politics-traders`, `best-crypto-traders`, `best-economics-traders`, `best-culture-traders`, `best-breaking-news-traders`) are returned WITH `enabled: false` and a public `disabled_reason` rather than hidden — requesting one from `/v1/cohorts/{slug}` returns `400 bad_request` quoting that reason. Code against `enabled`, not against a hardcoded slug list.

Note: unrelated to the `cohort` field on `/v1/status/parity`, which names a parity **sampling** cohort (`random` | `top`), not a curated wallet cohort.

Takes no parameters and is not paginated: `next_cursor` is always `null`.

## Response `200`

The full cohort registry, enabled and disabled entries alike. Not paginated — `next_cursor` is always `null`.

- object
  - `data` CohortDefinition[]
    - `slug` string: Stable public id and path segment. Never renamed.
    - `title` string
    - `thesis` string: One sentence saying what the cohort selects for.
    - `group` 'standing' | 'rotating' | 'machines': `standing` = durable; `rotating` = windowed, so a small member count means the window rather than breakage; `machines` = bots, useful to model or to exclude, not a skill board.
    - `order` integer: Editorial order within the group — not a ranking of quality and not a member count.
    - `source` 'wallet_stats' | 'wallet_category_stats': Which pre-aggregated rollup the cohort reads.
    - `order_by` 'pnl' | 'volume' | 'resolved_bets' | 'win_rate': Default sort key when `?sort=` is omitted.
    - `sortable` string[]: Sort keys this cohort accepts. Anything else returns `400`.
    - `max_rows` integer: Pagination depth cap. A cursor past this returns `400 bad_request`.
    - `enabled` boolean: False when the underlying data cannot support the claim. Disabled cohorts are still listed here, and requesting one from `/v1/cohorts/{slug}` returns `400`.
    - `disabled_reason` string, nullable: Public explanation when `enabled` is false; `null` otherwise. Quote it rather than reporting the cohort as empty.
    - `floors` CohortFloors: The machine-readable membership floor. A wallet must clear EVERY populated field to be a member; the query layer applies these verbatim and `floor_lines` is the same object rendered as copy. Absent fields are not enforced. No cohort has a raw win-rate floor.
      - `min_resolved_bets` integer: Minimum resolved bets. Always ≥ 1.
      - `min_pnl` number: Minimum PnL in USD. `0` means strictly positive PnL.
      - `min_bayesian_win_rate` number: Minimum sample-size-shrunk win rate (0–1). Never the raw per-fill `win_rate`.
      - `min_confidence` number: Minimum win-rate confidence (0–1).
      - `exclude_machines` boolean: Drop market-maker bots and classified bots.
      - `wallet_class` 'whale' | 'mm_bot': Restrict to one wallet class.
      - `first_seen_within_days` integer: Wallet first appeared on-chain within this many days.
      - `category` string: Market category the cohort scores within. Only the (currently disabled) category cohorts set this.
    - `floor_lines` string[]: `floors` rendered as public copy, derived from the same object the query enforces. Display these strings instead of retyping a threshold.
  - `next_cursor` string, nullable: Always `null` — the registry is returned whole.

## Other responses

- `401`: Missing, invalid, or revoked API key. Returned before the rate limiter runs, so it carries no `X-RateLimit-*` headers.
- `429`: Hourly or monthly rate limit exceeded.
- `500`: Unhandled server error. The wrapper logs the detail server-side keyed by `request_id` and returns a generic message.

---

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