---
title: "Cohort members"
method: GET
path: "/v1/cohorts/{slug}"
tags: ["Cohorts"]
---

# Cohort members

`GET /v1/cohorts/{slug}`

## Request

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

**Min tier: `free`.** The ranked members of one curated cohort. Every row satisfies every line of the cohort's floor, so the page needs no further filtering. `free` keys see the top 25 with no pagination; `terminal`+ paginate to the cohort's own `max_rows` cap (500 for every cohort today). Cursor-paginated.

Reads the pre-aggregated wallet rollups only — never a raw `trades` scan. Those aggregates lag real time, so the response reports `data_as_of` (the freshest underlying rollup timestamp across the page, `null` on an empty page) instead of implying "now". `member_count` is how many wallets clear the cohort's own floor in total; it is unaffected by `min_bets` and by paging.

Ranking is PnL-first: `pnl` is Polymarket's reported figure when present, else the on-chain ledger's. `sort=win_rate` ranks on the sample-shrunk `bayesian_win_rate` — the raw per-fill `win_rate` column is contaminated and is never a sort key or a floor. No cohort gates on win rate.

Errors are loud rather than silent: an unknown slug returns `400 bad_request` listing the valid slugs (not `404`); a disabled cohort returns `400 bad_request` quoting its `disabled_reason` (not a `200` with an empty page); a `cursor` past `max_rows` returns `400 bad_request` naming the cap.

## Path parameters

- `slug` string, required

## Query parameters

- `sort` 'pnl' | 'volume' | 'resolved_bets' | 'win_rate'
- `sort_dir` 'asc' | 'desc'
- `limit` integer
- `min_bets` integer
- `cursor` string

## Response `200`

Cursor-paginated cohort members, with the cohort's own context as siblings of `data`.

- object
  - `slug` string
  - `title` string
  - `thesis` string: One sentence saying what this cohort selects for.
  - `member_count` integer: Wallets currently clearing the cohort's own floor. Unaffected by `min_bets`, `limit` or paging. Membership drifts as the rollups are rewritten — treat it as approximate, not a guarantee.
  - `data_as_of` string, date-time, nullable: Freshest underlying rollup timestamp across the returned page; `null` on an empty page. These aggregates lag real time — never present them as live.
  - `floor_lines` string[]: The cohort's floor rendered as public copy, derived from the same object the query enforces (e.g. `"≥ 500 resolved bets"`, `"positive PnL"`). Display these strings rather than retyping a threshold.
  - `sort` 'pnl' | 'volume' | 'resolved_bets' | 'win_rate': Sort key actually applied.
  - `sort_dir` 'asc' | 'desc'
  - `min_bets` integer: Resolved-bet floor actually applied, after clamping the request up to the cohort's own floor.
  - `data` CohortMember[]
    - `address` string
    - `polymarket_name` string, nullable
    - `polymarket_avatar` string, nullable
    - `wallet_type` string, nullable: Legacy classification label.
    - `wallet_class` string, nullable: Wallet class (e.g. `whale`, `mm_bot`); `null` reads as retail.
    - `resolved_bets` integer
    - `win_rate` number, nullable: Raw per-fill win rate, carried for continuity only. It is contaminated and is never a sort key or a floor — use `bayesian_win_rate`.
    - `bayesian_win_rate` number, nullable: Sample-size-shrunk win rate (0–1). What `sort=win_rate` ranks on.
    - `confidence` number, nullable: Confidence in the win-rate estimate (0–1), driven by sample size.
    - `total_volume` number
    - `pnl` number: Ranked PnL: Polymarket's own reported figure when present, else CrowdIntel's on-chain ledger figure.
    - `polymarket_pnl` number, nullable: Polymarket's reported figure, or `null` when it has never been synced for this wallet.
    - `ledger_pnl` number: CrowdIntel's on-chain ledger figure.
    - `markets_traded` integer
    - `first_seen_at` string, date-time, nullable: First on-chain appearance. Populated only for windowed cohorts (those with a `first_seen_within_days` floor); `null` elsewhere.
    - `pnl_synced_at` string, date-time, nullable: When `polymarket_pnl` was last refreshed. Feeds the page's `data_as_of`.
    - `last_updated` string, date-time, nullable: When this rollup row was last written. Feeds the page's `data_as_of`.
  - `next_cursor` string, nullable: `null` on the last page, when the cohort's `max_rows` cap is reached, and always for `free` keys.

## Other responses

- `400`: Malformed parameters or a rejected guardrail (e.g. unfiltered trades query, cluster blowup, window > 90 days).
- `401`: Missing, invalid, or revoked API key. Returned before the rate limiter runs, so it carries no `X-RateLimit-*` headers.
- `403`: Key valid but its tier is below this endpoint's minimum. 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)
