> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kairos.trade/llms.txt
> Use this file to discover all available pages before exploring further.

# Get top token holders for one or more markets

> Fetches the largest holders of each outcome token for the given market IDs from the provider-specific upstream source, including Polymarket's data-api and Predict.fun's public GraphQL API. `market` accepts a comma-separated list (up to 50 IDs, each capped at 128 chars); Predict.fun requires numeric market IDs. An empty or missing value is rejected with 400. Results are grouped per token/outcome and include public profile fields (username, verification badge, avatar) alongside the held `amount`. This is a live upstream read, not served from a local cache; a downstream 4xx/5xx from the provider surfaces as 404 (market/token not found) or 502 (provider error). **Auth**: accepts an admin secret (`X-Admin-Secret`), an API key (`X-Client-Id` + `X-Api-Key` + `X-Api-Secret`), or a first-party JWT (Authorization header or `turnkey_session_jwt` cookie). No API-key scope is required — any valid credential can read holders. Rate-limited by the `heavy` group at 10 requests/minute, the same budget the `/trader-stats` endpoints carry, because every call is a live upstream provider read.




## OpenAPI

````yaml /openapi/data-api.yaml get /top-holders
openapi: 3.1.0
info:
  title: Kairos Data API
  version: 1.0.0
  summary: >-
    The full Kairos data plane — markets, candles, trades, search, discover,
    sports, trader analytics, and PnL.
  description: |
    The Kairos Data API at `data.kairos.trade` is the platform's primary data
    plane: market metadata and prices, OHLCV candles, live venue trade proxies,
    normalized trade history, full-text search, discovery feeds, the sports
    catalog, public trader analytics, and account PnL.

    ## Authentication

    Most endpoints accept a Kairos **API key** (`X-Client-Id` + `X-Api-Key` +
    `X-Api-Secret`, all three) or a first-party session JWT. Endpoints tagged
    `public` (trader analytics, provider configs, several sports feeds) need
    no credentials at all. Some endpoints additionally require an API-key
    **scope** (`trade:read`, `position:read`) — stated per operation.

    For high-volume market-data consumption (candles/trades/metadata at
    scale), prefer the dedicated **Market Data API** at `md.kairos.trade` —
    it has higher budgets, ETag caching, and a binary candle format.

    ## Rate limits

    Rate limits use a sliding window keyed on the authenticated user (JWT
    `sub`) or, for anonymous callers, the trusted client IP. Routes belong to
    a named **bucket** (`x-kairos-bucket`) whose per-minute budget is shared
    by every route in it; routes with no bucket run under the service default
    of 100/minute. `x-kairos-rate-limit` states the bucket's compile-time
    default — operators can raise or lower a bucket at runtime, so treat the
    documented number as the baseline, not a contract. 429 responses carry
    `Retry-After` and `X-RateLimit-*`.

    ## Conventions

    - Prices are on the **0–100 cents scale** unless a field says otherwise
      (trader-analytics position/trade prices use the 0–1 scale; each field's
      description states its scale).
    - Errors: `{"detail": "<message>"}` for handler errors; FastAPI's
      standard validation envelope for 422s. Errors surfaced from a venue
      adapter instead use `{"error", "provider", "operation", "message"}` —
      see `DataProviderError`. Unhandled failures always return the generic
      500 body; internal details are logged, never returned.
    - Every request body is capped at 8 MiB service-wide (413).
  contact:
    name: Kairos
    url: https://app.kairos.trade/docs/api-reference
  termsOfService: https://kairos.trade/terms
servers:
  - url: https://data.kairos.trade
    description: Production
  - url: https://staging-data.kairos.trade
    description: Staging
security:
  - apiKeyClientId: []
    apiKeyKey: []
    apiKeySecret: []
paths:
  /top-holders:
    get:
      tags:
        - Trader Analytics
      summary: Get top token holders for one or more markets
      description: >
        Fetches the largest holders of each outcome token for the given market
        IDs from the provider-specific upstream source, including Polymarket's
        data-api and Predict.fun's public GraphQL API. `market` accepts a
        comma-separated list (up to 50 IDs, each capped at 128 chars);
        Predict.fun requires numeric market IDs. An empty or missing value is
        rejected with 400. Results are grouped per token/outcome and include
        public profile fields (username, verification badge, avatar) alongside
        the held `amount`. This is a live upstream read, not served from a local
        cache; a downstream 4xx/5xx from the provider surfaces as 404
        (market/token not found) or 502 (provider error). **Auth**: accepts an
        admin secret (`X-Admin-Secret`), an API key (`X-Client-Id` + `X-Api-Key`
        + `X-Api-Secret`), or a first-party JWT (Authorization header or
        `turnkey_session_jwt` cookie). No API-key scope is required — any valid
        credential can read holders. Rate-limited by the `heavy` group at 10
        requests/minute, the same budget the `/trader-stats` endpoints carry,
        because every call is a live upstream provider read.
      operationId: getTopHolders
      parameters:
        - name: market
          in: query
          required: true
          schema:
            type: string
          description: >-
            Comma-separated list of market/condition IDs (max 50 items, 128
            chars each).
          example: 0xabc123,0xdef456
        - name: provider
          in: query
          required: false
          schema:
            type: string
            default: polymarket
          description: >-
            Provider name, validated against the active provider registry.
            Examples include polymarket and predictfun.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 20
            default: 20
          description: Maximum number of holders to return per token.
        - name: minBalance
          in: query
          required: false
          schema:
            type: integer
            minimum: 0
            maximum: 999999
            default: 1
          description: Minimum token balance a holder must have to be included.
      responses:
        '200':
          description: Top holders per requested token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TraderTopHoldersResponse'
        '400':
          description: >
            Missing/empty `market`, too many market IDs, an oversized market ID,
            an invalid `provider`, or an invalid request accepted by the
            provider client.
        '401':
          $ref: '#/components/responses/DataUnauthorized'
        '403':
          $ref: '#/components/responses/DataForbidden'
        '404':
          description: Market or token not found by the upstream provider.
        '422':
          $ref: '#/components/responses/DataValidationError'
        '429':
          $ref: '#/components/responses/DataRateLimited'
        '502':
          description: Upstream provider error fetching top holders.
components:
  schemas:
    TraderTopHoldersResponse:
      type: array
      description: >
        Top holders grouped by outcome token, one entry per requested
        market/token combination returned by the provider. The endpoint returns
        this array directly as the response body (not wrapped in an object).
      items:
        $ref: '#/components/schemas/TraderTopHoldersToken'
    TraderTopHoldersToken:
      type: object
      description: Top holders for a single outcome token.
      required:
        - token
        - holders
      properties:
        token:
          type: string
          description: Outcome token id.
          example: 10723948572...4
        holders:
          type: array
          items:
            $ref: '#/components/schemas/TraderTopHolder'
    DataError:
      type: object
      description: Handler error envelope (FastAPI HTTPException).
      required:
        - detail
      properties:
        detail:
          type: string
          description: Human-readable error message.
          example: Invalid provider
    TraderTopHolder:
      type: object
      description: A single holder of a market's outcome token.
      required:
        - proxyWallet
        - amount
        - outcomeIndex
        - displayUsernamePublic
        - verified
      properties:
        proxyWallet:
          type: string
          description: Holder's wallet address.
          example: '0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b'
        amount:
          type: number
          format: double
          description: Token amount held.
          example: 15230.5
        outcomeIndex:
          type: integer
          description: >-
            Index of the outcome token held (0 = first outcome, 1 = second,
            ...).
          example: 0
        displayUsernamePublic:
          type: boolean
          description: Whether the holder has opted to publicly display their username.
        verified:
          type: boolean
          description: Whether the holder has a verified badge.
        name:
          type: string
          description: Present only when the provider returned a display name.
          example: whale_trader_99
        pseudonym:
          type: string
          example: SilentOwl-4821
        bio:
          type: string
          example: Prediction market degen.
        asset:
          type: string
          description: >-
            Underlying asset identifier for the held token, when the provider
            supplies one.
        profileImage:
          type: string
          example: https://cdn.polymarket.com/avatars/abc.png
        profileImageOptimized:
          type: string
          example: https://cdn.polymarket.com/avatars/abc-opt.png
  responses:
    DataUnauthorized:
      description: >
        No valid credential presented — missing/invalid API-key headers, or an
        invalid/expired session token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DataError'
          example:
            detail: Not authenticated
    DataForbidden:
      description: >
        Authenticated but not permitted. Three distinct causes: the session user
        is not invited

        (`Invite required`), the API key lacks the operation's scope, or API-key
        access to the

        requested venue is switched off (`API access is disabled for
        <provider>`). Admin and API-key

        callers bypass the invite check; session and admin callers bypass scope
        and venue checks.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DataError'
          example:
            detail: Invite required
    DataValidationError:
      description: Request failed FastAPI parameter validation.
      content:
        application/json:
          schema:
            type: object
            required:
              - detail
            properties:
              detail:
                type: array
                description: >-
                  One entry per failed field, with location, message, and error
                  type.
                items:
                  type: object
                  additionalProperties: true
    DataRateLimited:
      description: >
        Rate limit exceeded for this route's sliding window, keyed on the
        session `sub` when

        authenticated and on the trusted client IP otherwise. Honor
        `Retry-After`. A per-API-key

        data ceiling (set per credential) rejects with `{"detail": "API key data
        rate limit

        exceeded"}` instead of the `error` envelope below.
      headers:
        Retry-After:
          schema:
            type: integer
        X-RateLimit-Limit:
          schema:
            type: integer
        X-RateLimit-Remaining:
          schema:
            type: integer
        X-RateLimit-Reset:
          schema:
            type: integer
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: 'Rate limit exceeded: 100 per 1 minute'
  securitySchemes:
    apiKeyClientId:
      type: apiKey
      in: header
      name: X-Client-Id
      description: >-
        Credential client id (`kairos_ck_...`). Must be sent together with
        X-Api-Key and X-Api-Secret.
    apiKeyKey:
      type: apiKey
      in: header
      name: X-Api-Key
      description: 64-char hex API key.
    apiKeySecret:
      type: apiKey
      in: header
      name: X-Api-Secret
      description: 64-char hex API secret.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.