> ## 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.

# Proxy Kalshi's public trade-history API for one market

> Thin proxy over Kalshi's `GET /trade-api/v2/markets/trades`, with a short-lived cache and Kairos-computed metrics appended.

**Auth**: requires the `trade:read` scope. Admin-secret and first-party JWT callers are always allowed through with no scope check. API-key callers must have `trade:read` in their credential's `scopes` array, or this returns 403 (`API key missing required scope: trade:read`). API-key callers are additionally gated by the `kalshi` platform's API access being enabled — if it's disabled, this returns 403 regardless of scope.

**Cache / data source**: responses are cached briefly to de-duplicate bursts of identical requests, then fall through to the live Kalshi API at `https://api.elections.kalshi.com/trade-api/v2/markets/trades`. A Kalshi HTTP error (non-2xx or network failure) returns 502.

**Response shape**: the raw Kalshi API response object is returned unmodified except for an injected `metrics` field, computed over the *locally time-filtered* trades (filtering by `min_ts`/`max_ts` is done client-side against each trade's `created_time`, since Kalshi's API does not filter server-side beyond `min_ts`/`max_ts` passthrough). The metrics window is fixed at 24 hours regardless of the requested `min_ts`/`max_ts` span.




## OpenAPI

````yaml /openapi/data-api.yaml get /trades/kalshi
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:
  /trades/kalshi:
    get:
      tags:
        - Trades
      summary: Proxy Kalshi's public trade-history API for one market
      description: >
        Thin proxy over Kalshi's `GET /trade-api/v2/markets/trades`, with a
        short-lived cache and Kairos-computed metrics appended.


        **Auth**: requires the `trade:read` scope. Admin-secret and first-party
        JWT callers are always allowed through with no scope check. API-key
        callers must have `trade:read` in their credential's `scopes` array, or
        this returns 403 (`API key missing required scope: trade:read`). API-key
        callers are additionally gated by the `kalshi` platform's API access
        being enabled — if it's disabled, this returns 403 regardless of scope.


        **Cache / data source**: responses are cached briefly to de-duplicate
        bursts of identical requests, then fall through to the live Kalshi API
        at `https://api.elections.kalshi.com/trade-api/v2/markets/trades`. A
        Kalshi HTTP error (non-2xx or network failure) returns 502.


        **Response shape**: the raw Kalshi API response object is returned
        unmodified except for an injected `metrics` field, computed over the
        *locally time-filtered* trades (filtering by `min_ts`/`max_ts` is done
        client-side against each trade's `created_time`, since Kalshi's API does
        not filter server-side beyond `min_ts`/`max_ts` passthrough). The
        metrics window is fixed at 24 hours regardless of the requested
        `min_ts`/`max_ts` span.
      operationId: getKalshiTrades
      parameters:
        - name: ticker
          in: query
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 128
          description: Kalshi market ticker. Empty or >128 chars returns 400.
          example: KXPRESPOLAND-24-DT
        - name: min_ts
          in: query
          required: false
          schema:
            type: integer
            nullable: true
          description: >-
            Inclusive lower bound, Unix seconds, applied both to the upstream
            request and to client-side filtering by `created_time`.
        - name: max_ts
          in: query
          required: false
          schema:
            type: integer
            nullable: true
          description: >-
            Inclusive upper bound, Unix seconds, applied both to the upstream
            request and to client-side filtering by `created_time`.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 100
          description: Max trades returned, passed through to the upstream Kalshi API.
        - name: cursor
          in: query
          required: false
          schema:
            type: string
            maxLength: 512
            nullable: true
          description: >-
            Upstream pagination cursor from a previous response. Blank strings
            are treated as absent; >512 chars returns 400.
      responses:
        '200':
          description: Raw Kalshi trade-history payload plus a computed `metrics` object.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TradesKalshiResponse'
        '400':
          description: Missing/empty `ticker`, or `cursor` too long.
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
        '401':
          $ref: '#/components/responses/DataUnauthorized'
        '403':
          description: >-
            API-key credential lacks the `trade:read` scope, or API access to
            the `kalshi` platform is currently disabled.
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
                    example: 'API key missing required scope: trade:read'
        '422':
          $ref: '#/components/responses/DataValidationError'
        '429':
          $ref: '#/components/responses/DataRateLimited'
        '502':
          description: >-
            Kalshi's upstream trade-history API returned an error or was
            unreachable.
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
                    example: Kalshi API error
        '503':
          description: Per-venue API-access flag could not be read or validated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DataError'
components:
  schemas:
    TradesKalshiResponse:
      type: object
      description: >
        The raw Kalshi API response object, spread as-is, with a `metrics` field
        injected by Kairos. Any other fields Kalshi returns (e.g. a pagination
        `cursor`) pass through unchanged.
      additionalProperties: true
      required:
        - trades
        - metrics
      properties:
        trades:
          type: array
          items:
            $ref: '#/components/schemas/TradesKalshiRawTrade'
        cursor:
          type: string
          description: Upstream pagination cursor, passed through when present.
        metrics:
          $ref: '#/components/schemas/TradesMetrics'
    DataError:
      type: object
      description: Handler error envelope (FastAPI HTTPException).
      required:
        - detail
      properties:
        detail:
          type: string
          description: Human-readable error message.
          example: Invalid provider
    TradesKalshiRawTrade:
      type: object
      description: >
        Raw trade object as returned by Kalshi's `GET
        /trade-api/v2/markets/trades`, passed through unmodified. Fields shown
        are the ones Kalshi documents/observed in practice; the API does not
        restrict or re-type them.
      additionalProperties: true
      properties:
        trade_id:
          type: string
        ticker:
          type: string
        count:
          type: integer
          description: Contracts traded.
        created_time:
          type: string
          format: date-time
        yes_price:
          type: integer
          description: 0-100 cents scale.
        no_price:
          type: integer
          description: 0-100 cents scale.
        taker_side:
          type: string
          enum:
            - true
            - false
    TradesMetrics:
      type: object
      description: >
        Aggregate volume/pressure metrics. Split by outcome (outcome_0 vs
        outcome_1), not by buy/sell direction — trade direction is not reliably
        derivable from every provider's exchange data.
      required:
        - volume_usd
        - outcome_0_volume_usd
        - outcome_1_volume_usd
        - outcome_0_pressure_pct
        - trade_count
        - window_seconds
        - coverage_pct
        - source
        - indexing
      properties:
        volume_usd:
          type: number
          description: Total notional volume in the window, in USD.
          example: 154320.55
        outcome_0_volume_usd:
          type: number
          description: >-
            Notional volume attributed to the first/primary outcome (e.g.
            "yes").
          example: 98210.1
        outcome_1_volume_usd:
          type: number
          description: Notional volume attributed to the second outcome (e.g. "no").
          example: 56110.45
        outcome_0_pressure_pct:
          type: number
          description: >-
            Share of total volume_usd attributed to outcome_0, as a percentage
            (0-100).
          example: 63.65
        trade_count:
          type: integer
          description: Number of trades included in the aggregation.
          example: 842
        window_seconds:
          type: integer
          description: Window width the metrics were computed over, in seconds.
          example: 86400
        coverage_pct:
          type: number
          description: >-
            Estimated data coverage for the window as a percentage (0-100); 100
            for live upstream proxies (Kalshi/Polymarket) and for fully-ingested
            windows.
          example: 100
        source:
          type: string
          description: >-
            Opaque internal marker indicating how the response was produced. NOT
            a stable part of the contract — its value may change without notice;
            do not depend on or switch on it.
        indexing:
          type: boolean
          description: >-
            True if an ingestion/backfill job was triggered or is in progress
            for this window (only meaningful when the caller passed
            `trigger_ingest=true`); coverage may be incomplete when true.
          example: false
  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
    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.