---
title: "Full resolution lifecycle timeline for one market"
method: GET
path: "/v1/markets/{provider}/{market_id}/resolution/events"
tags: ["Resolutions"]
---

# Full resolution lifecycle timeline for one market

`GET /v1/markets/{provider}/{market_id}/resolution/events`

## Request

- Base URL: `https://md.kairos.trade`
- URL: `https://md.kairos.trade/v1/markets/{provider}/{market_id}/resolution/events`
- Auth: one of:
  - none
  - API key in header `X-Client-Id` and API key in header `X-Api-Key` and API key in header `X-Api-Secret`

Returns the append-only event timeline (proposed, disputed, reset, settled, etc.) for a market's resolution, oldest first, capped at 200 events, keyed the same way as `.../resolution` (kalshi ticker identifies the market directly; CTF venues resolve market_id to its on-chain condition id first). Duplicate ingestion events are de-duplicated before ordering chronologically. Rate-limit bucket: LIGHT.

Cache lifetime matches the resolution-status endpoint: a `Cache-Control` header with a strong ETag (304 on matching `If-None-Match`).

## Path parameters

- `provider` 'kalshi' | 'polymarket' | 'opinion' | 'predictfun' | 'hyperliquid' | 'kalshi_offchain' | 'dome', required
- `market_id` string, required

## Response `200`

Resolution event timeline (possibly empty if the market has resolution state but no recorded events yet).

- ResolutionEventsResponse
  - `provider` string, required
  - `market_id` string, required: Echoes the requested market_id.
  - `market_key` string, required: The key events were actually queried by — equals market_id for kalshi; equals the resolved condition_id for CTF venues.
  - `events` ResolutionEvent[], required: Chronological, oldest first. Capped at 200 events.
    - `event_type` string, required: e.g. proposed, disputed, reset, settled_offchain.
    - `source` string, required: Origin of the event, e.g. polygon (on-chain UMA) or kalshi_api.
    - `event_ts` string, required: ISO8601 UTC.
    - `price_norm` number: Normalized price associated with this event, when present.
    - `too_early` boolean: Only present (and true) when the UMA "too early" flag was set.
    - `payout_numerators` integer[]: Only present when non-empty.
    - `proposer` string
    - `disputer` string
    - `bond` string: Raw on-chain bond amount (base-unit decimal string, not float — avoids precision loss).
    - `reward` string: Raw on-chain reward amount (base-unit decimal string).
    - `expiration_ts` string: ISO8601 UTC.
    - `request_timestamp` string: ISO8601 UTC.
    - `tx_hash` string
    - `block_number` integer: Only present when non-zero.

## Other responses

- `304`: Not Modified — `If-None-Match` matched the current ETag.
- `400`: Unknown provider.
- `401`: No valid credential presented. Every path returns `code: unauthorized`; the triggers differ: - An `Authorization` header on a deployment where bearer auth is not enabled (`bearer authentication is not enabled`). - A bearer token that fails verification (`invalid or expired session`), or whose token/session has been revoked (`session has been revoked`). - An incomplete or wrong API-key header set. Sending *any* of `X-Client-Id`, `X-Api-Key`, `X-Api-Secret` commits the request to the API-key path, so a partial set is rejected rather than silently degrading to anonymous limits (`valid X-Client-Id, X-Api-Key, and X-Api-Secret headers are required`). - No credential material at all while the anonymous free tier is unavailable — switched off for the deployment, forced off through the runtime kill switch, or not yet resolvable on a replica that has never read the flag (it fails closed).
- `403`: API key presented from a source IP not in that credential's whitelist.
- `404`: No resolution state for this market — for CTF venues this means no condition_id mapping was found (events cannot be looked up without one).
- `429`: Two different gates return this status, both with `code: rate_limited`: - **Per-credential (or per-IP, when anonymous) weighted budget exhausted.** The message is `rate limit exceeded`, or, for anonymous callers, `anonymous rate limit exceeded — request an API key for higher limits (…)`. `Retry-After` is the whole number of seconds until the current one-minute window rolls over, floored at 1. All four `X-RateLimit-*` headers are present. - **Per-IP admission gate.** An in-process, pre-authentication guard that keeps a flood off the shared credential cache and database. The message is `too many requests from this address` and `Retry-After` is a flat `60`. Because this fires *before* authentication, the response carries **no** `X-RateLimit-*` headers at all.
- `500`: The resolution events query failed.
- `503`: The rate limiter is unreachable. Fails CLOSED — the request is rejected rather than let through unmetered.

---

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