---
title: "Search both markets and events with combined relevance scoring"
method: GET
path: "/search/markets-and-events"
tags: ["Search"]
---

# Search both markets and events with combined relevance scoring

`GET /search/markets-and-events`

## Request

- Base URL: `https://data.kairos.trade`
- URL: `https://data.kairos.trade/search/markets-and-events`
- Auth: API key in header `X-Client-Id` and API key in header `X-Api-Key` and API key in header `X-Api-Secret`

Runs a market search and/or event search depending on `type`, tags event rows with `"type": "event"`, merges both result sets, sorts by `relevance_score` descending, and truncates to `limit`. Same provider-visibility post-filter as `/search/markets`.

## Query parameters

- `q` string, required
- `limit` integer
- `provider` string
- `provider_id` string
- `type` 'market' | 'event' | 'both'
- `include_expired` boolean
- `statuses` string[]
- `categories` string[]
- `tags` string[]

## Response `200`

Combined market + event results, sorted by relevance descending.

- SearchMarketsAndEventsResponse
  - `results` SearchResult[], required: Merged market + event rows, sorted by relevance_score descending, truncated to limit.
    - `market_id` string, required
    - `provider_id` integer, required: Numeric provider id (1=kalshi, 2=polymarket, 3=opinion, 8=predictfun).
    - `provider` string, required
    - `event_id` string, nullable
    - `event_name` string, nullable
    - `name` string, nullable: Market title.
    - `symbol` string, nullable
    - `category` string, nullable
    - `status` string, nullable
    - `expires_at` string, date-time, nullable
    - `relevance_score` number, required: Composite final score = text_score + business_score - penalty.
    - `volume_24h` number
    - `outcome_label` string, nullable
    - `series_key` string, nullable: Polymarket seriesSlug or Kalshi series_ticker.
    - `series_title` string, nullable
    - `text_score` number: Text match score before the live/starting-soon boost.
    - `business_score` number
    - `penalty` number
    - `timing_boost` number: Live/starting-soon multiplier (1 to 3) applied to text_score in relevance_score.
    - `price` number, nullable
    - `volume_1h` number
    - `liquidity` number
    - `image` string, nullable
    - `icon` string, nullable
    - `token_id` string, nullable: 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` string, nullable: Venue condition id (Polymarket 0x… condition hash), when the venue has one.
    - `token_ids` string[]: 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` string[]: Outcome labels aligned positionally with `token_ids`.
    - `type` 'event', nullable: Only present (and only ever "event") on rows returned by /search/markets-and-events when type=event or both.
  - `meta` SearchMarketsAndEventsMeta, required
    - `query` string
    - `returned` integer
    - `requested` integer: The `limit` that was requested.
    - `search_type` 'market' | 'event' | 'both'
    - `include_expired` boolean
    - `provider_id` string, nullable

## Other responses

- `400`: Empty `q`, invalid provider, or `type` not one of market/event/both.
- `401`: No valid credential presented — missing/invalid API-key headers, or an invalid/expired session token.
- `403`: 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.
- `422`: Request failed FastAPI parameter validation.
- `429`: 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.
- `500`: Search backend query failed.

---

[API](https://skmtc.dev/kairos/apis/kairos-data-api.md) - [All operations](https://skmtc.dev/kairos/apis/kairos-data-api/llms.txt) - [OpenAPI document](https://skmtc.dev/kairos/apis/kairos-data-api/revisions/cf6b76079e38?raw)
