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

# Fetch normalized, Kairos-ingested trade history for a contract

> Returns normalized trade history for a single `(provider, contract_id)` from Kairos's own ingested trade store. Unlike `/trades/kalshi` and `/trades/polymarket`, this is not a live upstream proxy — it serves from data Kairos has already ingested, so coverage depends on how much history has been backfilled/streamed for that contract.

**Auth**: requires the `trade:read` scope (admin/JWT bypass the scope check; API keys need `trade:read`), plus API access to the requested provider being enabled for API-key callers — 403 if disabled.

**Data source / staleness**: reads ingested trade rows for the window `[before - window_seconds, before]` (or ending "now" if `before` is omitted). If `trigger_ingest=true` and the data is missing or stale, an ingestion job is kicked off for that contract and reported via the `indexing` flag in the response — the returned trades may still be incomplete for that call.




## OpenAPI

````yaml /openapi/data-api.yaml get /trades/history
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/history:
    get:
      tags:
        - Trades
      summary: Fetch normalized, Kairos-ingested trade history for a contract
      description: >
        Returns normalized trade history for a single `(provider, contract_id)`
        from Kairos's own ingested trade store. Unlike `/trades/kalshi` and
        `/trades/polymarket`, this is not a live upstream proxy — it serves from
        data Kairos has already ingested, so coverage depends on how much
        history has been backfilled/streamed for that contract.


        **Auth**: requires the `trade:read` scope (admin/JWT bypass the scope
        check; API keys need `trade:read`), plus API access to the requested
        provider being enabled for API-key callers — 403 if disabled.


        **Data source / staleness**: reads ingested trade rows for the window
        `[before - window_seconds, before]` (or ending "now" if `before` is
        omitted). If `trigger_ingest=true` and the data is missing or stale, an
        ingestion job is kicked off for that contract and reported via the
        `indexing` flag in the response — the returned trades may still be
        incomplete for that call.
      operationId: getTradeHistory
      parameters:
        - name: provider
          in: query
          required: true
          schema:
            type: string
          description: >-
            Venue identifier, matched case-insensitively against the live
            provider registry.
          example: kalshi
        - name: contract_id
          in: query
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 128
          description: >-
            Provider-specific contract identifier. Empty or >128 chars returns
            400.
        - name: window_seconds
          in: query
          required: false
          schema:
            type: integer
            minimum: 3600
            maximum: 86400
            default: 86400
          description: >-
            Lookback window in seconds, ending at `before` (or now). Clamped to
            [3600, 86400] (1 hour to 24 hours).
        - name: before
          in: query
          required: false
          schema:
            type: integer
            nullable: true
          description: >-
            Unix-seconds cursor — return trades at or before this timestamp.
            Omit to end the window at "now".
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 500
            nullable: true
          description: >-
            Max trades returned. If omitted, the service applies its own
            internal default.
        - name: trigger_ingest
          in: query
          required: false
          schema:
            type: boolean
            default: false
          description: >-
            If true, kicks off ingestion when data for this window is stale or
            missing, rather than just returning what's already stored.
      responses:
        '200':
          description: >-
            Normalized trade rows for the window plus pagination/coverage
            metadata.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TradesHistoryResponse'
        '400':
          description: >-
            Invalid trade history request (unknown provider, invalid
            contract_id, or a request the service itself rejected as malformed).
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
                    example: Invalid trade history request
        '401':
          $ref: '#/components/responses/DataUnauthorized'
        '403':
          description: >-
            API-key credential lacks the `trade:read` scope, or API access to
            the requested provider is currently disabled.
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
        '422':
          $ref: '#/components/responses/DataValidationError'
        '429':
          $ref: '#/components/responses/DataRateLimited'
        '500':
          description: Trade history fetch failed on the backend.
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
                    example: Trade history fetch failed
        '503':
          description: Per-venue API-access flag could not be read or validated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DataError'
components:
  schemas:
    TradesHistoryResponse:
      type: object
      required:
        - trades
        - has_more
        - source
        - coverage_hours
        - indexing
      properties:
        trades:
          type: array
          items:
            $ref: '#/components/schemas/TradesTrade'
        has_more:
          type: boolean
          description: >-
            True if more trades exist before the oldest trade in this response
            (pagination via `before`).
        oldest_available_ts:
          type: number
          nullable: true
          description: >-
            Unix timestamp (seconds) of the oldest trade Kairos has ingested for
            this contract, or null if unknown.
          example: 1750000000
        source:
          type: string
          description: >-
            Opaque internal marker indicating how the response was served. NOT a
            stable part of the contract — its value may change without notice;
            do not depend on or switch on it.
        coverage_hours:
          type: number
          description: >-
            Hours of trade history coverage available/considered for this
            response.
          example: 24
        indexing:
          type: boolean
          description: >-
            True if ingestion was triggered/in progress for this window (only
            meaningful with `trigger_ingest=true`).
          example: false
    DataError:
      type: object
      description: Handler error envelope (FastAPI HTTPException).
      required:
        - detail
      properties:
        detail:
          type: string
          description: Human-readable error message.
          example: Invalid provider
    TradesTrade:
      type: object
      description: >
        A single normalized trade, as returned by `/trades/history`. Includes
        legacy `yes_price`/`no_price`/`taker_side` fields derived from
        `price`/`outcome` for backward compatibility with older consumers.
      required:
        - trade_id
        - order_id
        - contract_id
        - size
        - price
        - outcome
        - timestamp
        - yes_price
        - no_price
        - taker_side
      properties:
        trade_id:
          type: string
          example: kalshi:KXPRESPOLAND-24-DT:9f2a1c
        order_id:
          type: string
          nullable: true
          description: >-
            Venue order identifier or hash shared by fills from the same order.
            Null when the source venue does not provide an order identifier.
            This is not a Kairos order UUID.
          example: 0x9f2a1c...7bd4
        contract_id:
          type: string
          example: KXPRESPOLAND-24-DT
        size:
          type: integer
          description: Traded size (contracts/shares).
          example: 50
        price:
          type: number
          description: Trade price of the traded outcome, 0-100 cents scale.
          example: 63
        outcome:
          type: string
          description: >-
            Outcome name/index the trade was executed against (e.g. "yes", "no",
            or a token-based outcome label).
          example: 'yes'
        timestamp:
          type: number
          description: Unix timestamp, seconds.
          example: 1753142400
        token_id:
          type: string
          description: Outcome token identifier, present only when applicable.
        metadata:
          type: string
          description: >-
            Provider-specific JSON blob serialized as a string, present only
            when available.
        taker_address:
          type: string
          description: >-
            Taker wallet address, present only for on-chain venues where it's
            known.
        maker_address:
          type: string
          description: >-
            Counterparty wallet/contract address; may be the canonical exchange
            contract on aggressor-summary rows or a real wallet on maker-fill
            legs. Present only when known.
        side:
          type: string
          enum:
            - BUY
            - SELL
          description: Trade direction (distinct from `outcome`), present only when known.
        yes_price:
          type: number
          description: >-
            Legacy field: price expressed on the 'yes' outcome, 0-100 scale,
            derived from `price`/`outcome`.
          example: 63
        no_price:
          type: number
          description: >-
            Legacy field: price expressed on the 'no' outcome, 0-100 scale,
            derived from `price`/`outcome`.
          example: 37
        taker_side:
          type: string
          description: Legacy alias, always equal to `outcome`.
          example: 'yes'
  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.