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

# Fast simple search for navbar/autocomplete overlay

> Primary search endpoint behind the web navbar overlay. Supports sort/offset/pagination and optional server-side event grouping (`group_results`), then applies provider-visibility filtering. When `group_results=true`, best-effort enrichment (never fails the request) adds `classifiedGroups`/`absorbedMarketIds` (interactive ladder groups) and `correlations` (a cross-venue similar-market rail, similarity above a threshold, capped at 4 counterparts per result market). When `group_results=false`, only `correlations` is attached.



## OpenAPI

````yaml /openapi/data-api.yaml get /search/simple
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:
  /search/simple:
    get:
      tags:
        - Search
      summary: Fast simple search for navbar/autocomplete overlay
      description: >-
        Primary search endpoint behind the web navbar overlay. Supports
        sort/offset/pagination and optional server-side event grouping
        (`group_results`), then applies provider-visibility filtering. When
        `group_results=true`, best-effort enrichment (never fails the request)
        adds `classifiedGroups`/`absorbedMarketIds` (interactive ladder groups)
        and `correlations` (a cross-venue similar-market rail, similarity above
        a threshold, capped at 4 counterparts per result market). When
        `group_results=false`, only `correlations` is attached.
      operationId: searchSimple
      parameters:
        - name: q
          in: query
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 200
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 1000
            default: 20
        - name: offset
          in: query
          schema:
            type: integer
            minimum: 0
            default: 0
        - name: provider
          in: query
          schema:
            type: string
        - name: provider_id
          in: query
          description: Legacy alias for `provider`.
          schema:
            type: string
        - name: tags
          in: query
          description: Repeatable platform-tag-slug filter.
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
        - name: statuses
          in: query
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
        - name: sort_by
          in: query
          schema:
            type: string
            enum:
              - relevance
              - volume_24h
              - newest
              - ending_soon
            default: relevance
        - name: sort_order
          in: query
          schema:
            type: string
            enum:
              - asc
              - desc
            default: desc
        - name: include_total
          in: query
          description: >-
            Include a best-effort `meta.total` (falls back to the filtered count
            if any rows were dropped by visibility filtering).
          schema:
            type: boolean
            default: false
        - name: include_expired
          in: query
          schema:
            type: boolean
            default: false
        - name: group_results
          in: query
          description: >-
            Group markets by event server-side, producing `groups`/`singles` in
            the response.
          schema:
            type: boolean
            default: true
      responses:
        '200':
          description: >-
            Simple-search result envelope, optionally grouped and enriched with
            classified ladders + cross-venue correlations.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchSimpleResponse'
        '400':
          description: Empty `q`, invalid provider, or invalid `sort_by`/`sort_order`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchBadRequestError'
        '422':
          $ref: '#/components/responses/DataValidationError'
        '429':
          $ref: '#/components/responses/DataRateLimited'
        '500':
          description: Search backend query failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DataError'
      security: []
components:
  schemas:
    SearchSimpleResponse:
      type: object
      description: >-
        Shared envelope for /search/simple and /search/resolve-url. Both always
        include results/meta; groups/singles appear only when the underlying
        search was grouped (always true for /search/simple with
        group_results=true, and for /search/resolve-url on an event URL).
        classifiedGroups/absorbedMarketIds are only ever attached by
        /search/simple (group_results=true); /search/resolve-url never sets
        them. correlations is attached by both, best-effort, and absent if no
        counterpart markets were found.
      required:
        - results
        - meta
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/SearchResult'
        groups:
          type: array
          items:
            $ref: '#/components/schemas/SearchEventGroup'
        singles:
          type: array
          items:
            $ref: '#/components/schemas/SearchResult'
        meta:
          $ref: '#/components/schemas/SearchSimpleMeta'
        classifiedGroups:
          type: array
          items:
            $ref: '#/components/schemas/SearchMarketGroup'
        absorbedMarketIds:
          type: array
          items:
            type: string
          description: >-
            Market/outcome ids already rendered inside classifiedGroups — the
            overlay should not also render them as standalone rows.
        correlations:
          type: object
          description: >-
            Map of result market_id -> up to 4 similar cross-venue counterpart
            markets, sorted by similarity descending.
          additionalProperties:
            type: array
            items:
              $ref: '#/components/schemas/SearchCorrelationCounterpart'
    SearchBadRequestError:
      type: object
      description: FastAPI `HTTPException(400)` body shape used across the search router.
      required:
        - detail
      properties:
        detail:
          type: string
          example: 'Invalid provider: acme'
    DataError:
      type: object
      description: Handler error envelope (FastAPI HTTPException).
      required:
        - detail
      properties:
        detail:
          type: string
          description: Human-readable error message.
          example: Invalid provider
    SearchResult:
      type: object
      description: >-
        One market or event row from search results, post provider-visibility
        filtering.
      required:
        - market_id
        - provider_id
        - provider
        - relevance_score
      properties:
        market_id:
          type: string
          example: KXPRES-28-DJT
        provider_id:
          type: integer
          description: >-
            Numeric provider id (1=kalshi, 2=polymarket, 3=opinion,
            8=predictfun).
          example: 1
        provider:
          type: string
          example: kalshi
        event_id:
          type: string
          nullable: true
        event_name:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
          description: Market title.
        symbol:
          type: string
          nullable: true
        category:
          type: string
          nullable: true
        status:
          type: string
          nullable: true
          example: open
        expires_at:
          type: string
          format: date-time
          nullable: true
        relevance_score:
          type: number
          description: Composite final score = text_score + business_score - penalty.
        volume_24h:
          type: number
          default: 0
        outcome_label:
          type: string
          nullable: true
        series_key:
          type: string
          nullable: true
          description: Polymarket seriesSlug or Kalshi series_ticker.
        series_title:
          type: string
          nullable: true
        text_score:
          type: number
          default: 0
        business_score:
          type: number
          default: 0
        penalty:
          type: number
          default: 0
          minimum: 0
        price:
          type: number
          nullable: true
        volume_1h:
          type: number
          default: 0
        liquidity:
          type: number
          default: 0
        image:
          type: string
          nullable: true
        icon:
          type: string
          nullable: true
        token_id:
          type: string
          nullable: true
          description: >-
            First outcome's on-chain token id (legacy singular field). For a
            market with more than one outcome use `token_ids`/`outcomes`
            instead.
        condition_id:
          type: string
          nullable: true
          description: >-
            Venue condition id (Polymarket 0x… condition hash), when the venue
            has one.
        token_ids:
          type: array
          items:
            type: string
          description: >-
            Full on-chain outcome token roster, aligned with `outcomes`. Feed
            these to `/v1/synthetics` legs and `/v1/candles` without a second
            resolve call. Empty when the market has no on-chain tokens.
        outcomes:
          type: array
          items:
            type: string
          description: Outcome labels aligned positionally with `token_ids`.
        type:
          type: string
          enum:
            - event
          nullable: true
          description: >-
            Only present (and only ever "event") on rows returned by
            /search/markets-and-events when type=event or both.
    SearchEventGroup:
      type: object
      description: One event's outcome markets, grouped server-side.
      required:
        - event_id
        - market_count
        - markets
      properties:
        event_id:
          type: string
        event_name:
          type: string
          nullable: true
        market_count:
          type: integer
          description: Count of markets kept after provider-visibility filtering.
        representative:
          allOf:
            - $ref: '#/components/schemas/SearchResult'
          nullable: true
          description: >-
            Falls back to the first remaining market if the original
            representative's provider was filtered out.
        markets:
          type: array
          items:
            $ref: '#/components/schemas/SearchResult'
    SearchSimpleMeta:
      type: object
      properties:
        query:
          type: string
        returned:
          type: integer
          description: Count of results after provider-visibility filtering.
        query_time_ms:
          type: number
        total:
          type: integer
          nullable: true
          description: >-
            Present only when include_total=true. Best-effort: the upstream
            total if no rows were filtered by visibility, else the filtered
            count.
    SearchMarketGroup:
      type: object
      description: >-
        An "interactive ladder" grouping of related markets (e.g. a set of
        over/under threshold markets on one axis), pre-computed by a background
        job and served from cache at search time.
      required:
        - type
        - groupKey
        - provider
        - outcomes
      properties:
        type:
          type: string
          enum:
            - group
        groupKey:
          type: string
        provider:
          type: string
        title:
          type: string
          nullable: true
        kind:
          type: string
          nullable: true
          description: Classification kind, e.g. threshold ladder.
        axisLabel:
          type: string
          nullable: true
        unit:
          type: string
          nullable: true
        direction:
          type: string
          nullable: true
        confidence:
          type: number
          description: Rounded to 3 decimal places.
        marketCount:
          type: integer
        category:
          type: string
          nullable: true
        image:
          type: string
          nullable: true
        icon:
          type: string
          nullable: true
        eventId:
          type: string
          nullable: true
        eventTitle:
          type: string
          nullable: true
        outcomes:
          type: array
          items:
            $ref: '#/components/schemas/SearchOutcomeRef'
    SearchCorrelationCounterpart:
      type: object
      description: >-
        A cross-venue market judged similar (similarity at or above a threshold)
        to the keyed result market_id. Enrichment fields
        (title/ticker/image/icon/expires_at) are only present when the
        counterpart market's metadata is available; otherwise they're absent.
      required:
        - provider_id
        - market_id
        - similarity
        - method
      properties:
        provider_id:
          type: integer
        market_id:
          type: string
        similarity:
          type: number
          minimum: 0
          maximum: 1
        method:
          type: string
          description: How the correlation was derived, e.g. embedding/manual.
        title:
          type: string
        ticker:
          type: string
        image:
          type: string
          nullable: true
        icon:
          type: string
          nullable: true
        expires_at:
          type: string
          format: date-time
          nullable: true
    SearchOutcomeRef:
      type: object
      description: One outcome within a classified MarketGroup (interactive ladder).
      properties:
        id:
          type: string
        provider:
          type: string
        title:
          type: string
          nullable: true
        outcomeLabel:
          type: string
          nullable: true
        tokenId:
          type: string
          nullable: true
        price:
          type: number
          nullable: true
        op:
          type: string
          nullable: true
          description: >-
            Comparison operator this outcome represents on the group's axis,
            e.g. '>=', '<'.
        value:
          type: number
          nullable: true
          description: Threshold value on the group's axis.
        hi:
          type: number
          nullable: true
          description: Upper bound, for range-shaped outcomes.
  responses:
    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.