# Adjacent API

> Prediction market data API: markets, indices, events, reference rates, and semantic search from Kalshi and Polymarket

This file contains the full content of all documentation pages. For a compact index, see [llms.txt](https://docs.adjacent.markets/llms.txt). To download all pages as a zip, use [docs.zip](https://docs.adjacent.markets/docs.zip).

---
title: Adjacent API
url: "https://docs.adjacent.markets/index.md"
description: "Use prediction market data, indices, reference rates, and news in your own tools."
---

Adjacent gives you one place to work with prediction-market data from Kalshi
and Polymarket. Use it to build research tools, track markets, compare prices,
or give an AI agent reliable market data.

You can start with delayed public data or use an API key for realtime data and
the full catalog.

<CardGroup cols={2}>
  <Card title="Start with the API reference" icon="code" href="/api/get-api-v1-public-markets">
    Browse every endpoint with schemas, examples, and a live cURL request.
  </Card>

  <Card title="Pricing" icon="tag" href="/pricing">
    Compare data access, quotas, and plan limits.
  </Card>
</CardGroup>

## Choose what you need

**Market data.** Find markets and events, then read prices, trades, quotes,
and candles. Start with [Market data](/explore/market-data).

**Indices.** Use an index when you need a single measure built from many
prediction markets. Start with [Indices](/explore/indices).

**Reference rates.** Compare the same market across venues or across rolling
contracts with one price series. Start with
[Reference rates](/explore/reference-rates).

**News.** Find stored articles and connect them to markets, indices, and
filings. Start with [News](/explore/news).

**Filings.** Browse CFTC industry filings and follow status changes,
attachments, and related markets. Start with [Filings](/explore/filings).

**AI agents.** Connect an agent through MCP instead of teaching it every REST
endpoint. Start with [MCP server](/explore/mcp).

## Base URL

```
https://api.adjacent.markets
```

All endpoints use the `/api/v1/` prefix.

## Authentication

The anonymous `/api/v1/public/*` tier needs no token and returns data delayed by
15 minutes.

Realtime endpoints require a bearer token. Use a session token from the app or
an **API key** with the read scope for the resource you are calling.

```bash
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://api.adjacent.markets/api/v1/rates
```

### API keys

Create and manage keys in the app under **Settings → API keys**. Choose scopes
that your account can grant, then copy the secret because it appears only once.

Send the key as a bearer token:

```bash
curl -H "Authorization: Bearer ak_your_key" \
  https://api.adjacent.markets/api/v1/rates
```

…or as an `api_key` query parameter:

```bash
curl "https://api.adjacent.markets/api/v1/rates?api_key=ak_your_key"
```

A key can reach only the endpoints covered by its scopes. Other requests return
`403`.

## Need help choosing?

Start with the public tier if you are exploring the data or building a
prototype. Use an API key when you need realtime values, deeper history, news,
or higher request limits. If you are not sure which endpoint fits your use
case, [contact support](mailto:lucas@adjacentresearch.xyz).


---
title: Explore the API
url: "https://docs.adjacent.markets/explore.md"
description: "Find the right Adjacent data for your research, product, or AI agent."
---

Start with the question you are trying to answer. This guide points you to the
right data and shows the requests that come next.

## A typical first request

Most projects follow the same path:

1. Find an event, market, index, or rate.
2. Save its id from the response.
3. Request the detail or price history for that id.
4. Use the returned data in your chart, report, alert, or agent.

The API returns stable ids. Pass them from one request into the next instead of
guessing a ticker or rebuilding a venue-specific identifier.

<CardGroup cols={2}>
  <Card title="Market data" icon="chart-candlestick" href="/explore/market-data">
    Find markets and events, then read prices, trades, quotes, and candles.
  </Card>

  <Card title="Indices" icon="chart-line" href="/explore/indices">
    Track a value built from many prediction markets.
  </Card>

  <Card title="Reference rates" icon="percent" href="/explore/reference-rates">
    Combine prices across venues or across contracts that roll over time.
  </Card>

  <Card title="News" icon="newspaper" href="/explore/news">
    Find articles and connect them to markets, indices, and filings.
  </Card>

  <Card title="Filings" icon="file-text" href="/explore/filings">
    Browse CFTC industry filings, changes, attachments, and related records.
  </Card>

  <Card title="MCP server" icon="bot" href="/explore/mcp">
    Let an AI agent find and read Adjacent data through four focused tools.
  </Card>
</CardGroup>

## Pick a starting point

**You are exploring a topic.** Start with [Market data](/explore/market-data).
Search for an event, inspect its markets, and follow the price history.

**You need a broader signal.** Start with [Indices](/explore/indices). An index
combines many markets into one value and provides its composition and weights.

**You need market context.** Start with [News](/explore/news). Search stored
articles, read the source record, and find related markets.

**You need regulatory context.** Start with [Filings](/explore/filings). Browse
CFTC filings and connect them to the markets and articles they relate to.

**You are comparing venues.** Start with
[Reference rates](/explore/reference-rates). A rate puts prices for the same
underlying market into one series.

**You are connecting an AI agent.** Start with [MCP server](/explore/mcp). The
agent can search by topic and use the returned id for detail or price history.

**You need verified on-chain data.** Start with [Oracles](/explore/oracles).
The SEDA proxy provides signed responses for supported index data.

## Choose your data access

Use the public tier to try the API without an account. It returns a
15-minute-delayed snapshot of core market, event, index, and rate data.

Use an API key for realtime data, deeper history, news, semantic search, and
MCP access. The key also gives you higher request limits and access to the full
market and filing catalogs.

## What you can build

Use market data for a research notebook, market monitor, or search experience.
Use indices and rates when your product needs one series instead of a list of
markets. Use MCP when an AI agent needs to choose its next lookup.

The public tier is a good place to test an idea. It requires no token and
returns data delayed by 15 minutes. Add an API key when you need realtime
values, deeper history, news, or higher request limits.

## Go deeper

* [Authentication](/#authentication) explains tokens and API keys.
* [Pricing](/pricing) shows data access and request limits.
* [Rate limits](/rate-limits) explains quotas, headers, and concurrency.
* [API reference](/api/get-api-v1-public-markets) lists every endpoint and schema.


---
title: Market data
url: "https://docs.adjacent.markets/explore/market-data.md"
description: Pull live and historical prediction-market data from Kalshi and Polymarket through one API.
---

Use this guide when you need the underlying market data rather than a derived
index or rate. Adjacent returns markets, events, trades, quotes, and candles
from Kalshi and Polymarket in one schema.

Every `market_id` and `event_id` is globally unique and prefixed with its
platform (`kalshi:` / `polymarket:`). That prefix lets you pass an id from a
list response directly into a detail or history request.

Set `ADJ_TOKEN` to an API key before running these examples; see
[Authentication](/#authentication).

## A simple market workflow

Start with a filtered market list when you know the venue or category but not
the exact market id. Pick an id from the response, then request the market
detail to confirm its question, status, and close date.

Once you have the right market, choose the history that matches your question:

* Use prices to chart how the implied probability changed.
* Use trades to inspect individual executions.
* Use quotes to inspect the bid and ask at a point in time.
* Use candles to work with open, high, low, and close values.

## Find markets

Filter by platform, category, probability, or volume. Results are paginated, so
you can browse a large catalog without loading it all at once.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/markets?platform=kalshi&category=Politics&probability_min=50&sort_dir=desc&per_page=10"
```

The response includes a `data` array and a `meta` object. Save the `market_id`
from the market you want to inspect.

## Follow one market

Use the saved id to fetch the market record. Then choose the history endpoint
that matches your question.

```bash
MARKET_ID="kalshi:KXPRESPARTY-2028-R"

curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/markets/$MARKET_ID"

curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/markets/$MARKET_ID/prices?interval=1hour&per_page=24"
```

Use the market record for labels and status. Use price history for charts. Use
trades and quotes when you need to explain a price change.

## Read a market

Market prices use a 0-100 scale. A price of `75` means an implied probability
of 75%.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/markets/kalshi:KXPRESPARTY-2028-R"
```

## Follow a market over time

Use price history to chart a market, trades to see executions, quotes to inspect
the latest bid and ask, and candles to work with OHLC data.

```bash
# Bucketed price history
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/markets/kalshi:KXPRESPARTY-2028-R/prices?interval=1hour&per_page=24"

# Recent trades
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/markets/kalshi:KXPRESPARTY-2028-R/trades?per_page=20"

# Raw top-of-book bid/ask snapshots
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/markets/kalshi:KXPRESPARTY-2028-R/quotes?per_page=20"

# OHLC candles (interval is the period length in minutes)
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/markets/kalshi:KXPRESPARTY-2028-R/candles?interval=60"
```

## Find similar markets

Use this when you know one market but want related markets. Results are ranked
by embedding cosine similarity.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/markets/kalshi:KXPRESPARTY-2028-R/similar?per_page=5&min_similarity=0.7"
```

## Browse events

Events group markets that resolve together, such as the markets for an
election. Use an event when you want the full set of related markets.

```bash
# List events in a category
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/events?category=Politics&per_page=10"

# Event detail with its markets
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/events/kalshi:KXPRESPARTY-2028"
```

See the [API reference](/api/get-api-v1-markets) for full schemas.


---
title: Indices
url: "https://docs.adjacent.markets/explore/indices.md"
description: "Track index values, composition, weights, price history, and constituent returns."
---

Use an index when a single market is too narrow. Adjacent combines many
prediction markets into a value that you can track over time.

The catalog includes political examples such as `red` and `blue`, along with
`red_tr` (`RED-TR`), a total-return index, and NFL team indices
(`methodology` `nti`). Other index methodologies can use the same endpoints.

## What an index helps you answer

Use an index when you want to follow a group of markets without choosing one
market at a time. The index detail gives you its current level and recent
change. The constituents endpoint shows which markets contribute to that level
and how much each one weighs.

Use price history to chart the index. Use the export endpoints when you want
to work with the series in a spreadsheet or analysis script.

## Read an index value

The RED, BLUE, and UPFI political indices use a 50–150 scale. They do not use a
0–100 probability scale or a dollar price. The formula is
`value = 50 + (the index party's aggregate win-probability, in percent)`.
The scale runs from `50` (0%) through `100` (an even 50/50) to `150` (100%).
Subtract `50` from the value to get the implied win probability. For example,
`95` ≈ 45%, `109` ≈ 59%, and `130` ≈ 80%.

For the political examples, `red` above `100` means Republicans are favored
across its races and `blue` above `100` means Democrats are favored. Other
indices can use a different scale, so check the index's methodology before
comparing values. A constituent market's price is a 0–100% Yes
probability, which is different from the index scale.

Set `ADJ_TOKEN` to an API key before running these examples. See
[Authentication](/#authentication).

## Find an index

Start by listing indices if you do not know which index id to use.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/indices"
```

## Read an index

The response includes the latest price and 1-day and 7-day changes.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/indices/red"
```

The index response gives you the current value and recent changes. Use the
`constituents` link when you need to explain what moved the index.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/indices/red/constituents"
```

## Understand an index's composition

Each constituent carries a `kind` (`market` for leaf markets, `index` for a
composite's child sub-indices) alongside its computed weight.

The current political catalog defines two composites:

| Composite | Ticker | Child sub-indices and fixed weights                                                                                                                   |
| --------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `red`     | `RED`  | `presr_kalshi` / `PRESR` 40%, `senater_kalshi` / `SENR` 30%, `houser_kalshi` / `HOUSER` 20%, `govr_kalshi` / `GOVR` 8%, `mayorr_kalshi` / `MAYORR` 2% |
| `blue`    | `BLUE` | `presd_kalshi` / `PRESD` 40%, `senated_kalshi` / `SEND` 30%, `housed_kalshi` / `HOUSED` 20%, `govd_kalshi` / `GOVD` 8%, `mayord_kalshi` / `MAYORD` 2% |

Sub-index market weights use the UPFI methodology factors. Presidential and
Senate weights use lifetime cumulative contract or share count and
time-to-resolution. House, Governor, and Mayoral weights use jurisdiction
population. House and Governor use state population. Mayoral uses city
population. There is no impact factor.

RED and BLUE publish a trailing 1-hour SMA of the raw composite value.
Sub-indices publish their raw per-cycle value.

`red_tr` / `RED-TR` does not use the 50–150 scale. It is a path-dependent
total-return index over RED's eligible constituents: `100` is its base value,
`125` is a cumulative return of 25%, and the value is not SMA-smoothed.

NFL team indices (`methodology` `nti`, `quote_convention` `points`) also skip
the 50-150 scale. Each index tracks one team across four sleeves (Super Bowl,
conference, division, next game). An active sleeve holds a constant 25
contracts; the level starts at `1000` and adds each sleeve's dollar P\&L,
`NTI_t = NTI_{t-1} + Σ 25 × (P_t - P_prev)`, floored at zero. Index detail
returns those holdings as `sleeves` and the latest official daily print as
`official_daily_value`. Read the official daily series and recent sleeve
admissions or settlements on the family-specific routes (other families
return an empty list):

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/indices/{id}/daily-values"

curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/indices/{id}/membership-events"
```

## Track an index over time

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/indices/red/prices?interval=1hour&per_page=24"
```

## Download the data

You can download index listings and price history as CSV or TSV for offline
analysis.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/export/indices/csv"

curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/export/indices/red/prices.csv?interval=1hour"
```

See the [API reference](/api/get-api-v1-indices) for full schemas.


---
title: Reference rates
url: "https://docs.adjacent.markets/explore/reference-rates.md"
description: Cross-platform benchmark rates and rolling-contract chains for the same underlying market.
---

Use a reference rate when the same underlying market appears on more than one
venue or rolls from one contract into the next. Adjacent combines those source
prices into one series and reports the `spread` between them.

Rates use the same 0-100 percent scale as market prices. They give you one
series to chart, compare, and pass to another system.

## What the rate tells you

The rate is the combined value of its source markets. Its `spread` shows how
far those source prices are apart. A small spread means the sources are close.
A large spread tells you to inspect the individual markets before treating the
rate as a single signal.

The source list includes each market's contribution and weight. Use it to
explain the rate or compare the venues behind it.

For `volume_weighted_average`, each source's effective weight is its configured
or roll weight multiplied by its cumulative contract or share count:
`Σ(price_i · weight_i · count_i) / Σ(weight_i · count_i)`. Other supported
methods are `simple_average` and `median`.

Choose `volume_weighted_average` when trading volume should affect the result.
Choose `simple_average` when each source should count equally. Choose `median`
when you want the middle source price and less sensitivity to an outlier.

Set `ADJ_TOKEN` to an API key before running these examples. See
[Authentication](/#authentication).

## Find a rate

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/rates"
```

## Read a rate

The response includes the source markets, their weights, and recent price
changes.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/rates/adj_redp"
```

## Track a rate over time

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/rates/adj_redp/prices?interval=1hour&per_page=24"
```

## Keep a series across contract rolls

Chains join successive contracts, such as the 2024 and 2028 presidential
contracts, so a benchmark continues after an expiry. The `roll_schedule`
blends adjacent contracts during the roll window.

A chain-backed rate uses the same endpoints as any other rate. Pass
`sources=true` with price history to see the roll weight for each contract at
each point.

```bash
# Rolling rate price history, with per-leg roll weights
curl -H "Authorization: Bearer $ADJ_TOKEN" "https://api.adjacent.markets/api/v1/rates/adj_redp/prices?interval=1hour&per_page=24&sources=true"
```

See the [API reference](/api/get-api-v1-rates) for full schemas.


---
title: News
url: "https://docs.adjacent.markets/explore/news.md"
description: "Find stored articles and connect them to prediction markets, indices, and filings."
---

Use the news API when you want articles beside market data. Adjacent stores
article metadata, source information, and extracted text, then links articles
to related markets, indices, and filings.

## What you can do

* Browse the latest articles with page-based pagination.
* Filter the stored catalog by source or language.
* Read one article with its description and stored body.
* Find markets or filings related to an article.
* Find articles related to a market, index, rate, or filing.

News search and related-content endpoints require an API key. The public tier
includes a small, delayed set of related articles on market, index, and rate
pages.

Set `ADJ_TOKEN` to an API key before running these examples. See
[Authentication](/#authentication).

## Get the latest articles

Use the latest endpoint when you are building a feed or want the newest
available articles. It uses page-based pagination.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/news/latest?per_page=20"
```

## Filter the catalog

Use the catalog endpoint when you want to page through stored articles or
filter by a known source or language.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/news?source=SOURCE_ID&language=en"
```

Use the filters endpoint to discover source ids and language codes before
building filter controls.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/news/filters"
```

The list response places articles in `data` and pagination values in `meta`.
Each article summary includes an `id`, `title`, `url`, `source`,
`published_date`, and `language`.

## Read an article

Pass an article id from a list response to get its full stored record, including
the description and truncated body.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/news/ARTICLE_ID"
```

The detail response adds the article `author`, `description`, and truncated
`content`. Keep the article `url` when you show a link back to the publisher.

## Find related markets

Use the related-markets endpoint to find markets connected to an article.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/news/ARTICLE_ID/markets?per_page=10"
```

The reverse lookup is also available. Use a market, index, rate, or filing
endpoint when you already know the record and want its related articles.

Related results are ranked matches, not proof that an article caused a market
move. Use the article timestamp and the market price history together when you
are building a timeline.

See the [API reference](/api/get-api-v1-news) for full schemas.


---
title: Filings
url: "https://docs.adjacent.markets/explore/filings.md"
description: Browse CFTC industry filings and connect them to markets and news.
---

Use the filings API to track CFTC industry submissions, certifications, and
rule changes. Adjacent stores each filing, its status history, attachment text,
and links to related markets and news.

## What you can do

* Browse the full filing catalog with filters and relevance-ranked search.
* Use the public tier to browse filings from the last 90 days.
* Follow new filings, status changes, and added attachments.
* Read the action history for one filing.
* Read extracted markdown from stored attachments.
* Find related markets, news, and similar filings.

The public tier covers filings whose status date is in the last 90 days. Use an
API key with the `org:filings:read` scope for the full catalog, historical
filings, change events, and related-record endpoints.

Set `ADJ_TOKEN` to an API key before running these examples. See
[Authentication](/#authentication).

## Browse recent filings

Start with the public list when you want recent filings without authentication.
It includes the same core filing shape and returns the newest status dates first.

```bash
curl "https://api.adjacent.markets/api/v1/public/filings?per_page=20"
```

Use the filters endpoint to populate feed, organization, and status filters.

```bash
curl "https://api.adjacent.markets/api/v1/public/filings/filters"
```

Each filing has an `id`, `title`, `feed`, `org_code`, `status`,
`status_date`, and `doc_count`. The `feed` tells you which CFTC registry
provided the row.

## Search the full catalog

Use the authenticated list for historical filings and relevance-ranked search.
Search checks the organization, description, product name and type, affected
products, and filing id.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/filings?search=bitcoin&per_page=20"
```

## Follow filing changes

The change feed lets you keep a local record current. Save the highest `seq`
from each response, then pass it as `since_seq` on the next request.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/filings/events?since_seq=100"
```

The feed reports first sightings, status changes, and later attachments.

Use the event `kind` to decide what to refresh. A status change updates the
filing record. A documents-added event means you can request the attachment
text again.

## Read a filing and its history

Use the filing id from a list or event response to fetch the filing, its action
history, or the text extracted from its attachments.

```bash
curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/filings/FILING_ID"

curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/filings/FILING_ID/actions"

curl -H "Authorization: Bearer $ADJ_TOKEN" \
  "https://api.adjacent.markets/api/v1/filings/FILING_ID/markdown"
```

The actions endpoint returns the filing's history in oldest-first order. The
markdown endpoint returns the filing and the extracted text for its stored
attachments.

## Connect filings to other data

Use the related endpoints to move between a filing and the markets, articles,
or similar filings connected to it.

See the [API reference](/api/get-api-v1-filings) for full schemas.


---
title: Oracles
url: "https://docs.adjacent.markets/explore/oracles.md"
description: "Bring Adjacent data on-chain through the SEDA data oracle network with signed, verifiable responses."
---

Use the SEDA proxy when another system must verify Adjacent data before using it
on-chain.

Adjacent publishes data to the
[SEDA oracle network](https://github.com/sedaprotocol/seda-data-proxy) through a
SEDA data proxy. The proxy signs each response with a registered keypair.
Overlay nodes verify that the payload came from Adjacent before settling it
on-chain.

The testnet needs no key and returns delayed data. Mainnet responses require
SEDA proof verification and are not generally available.

## Endpoints

|           | Testnet                           | Mainnet                       |
| --------- | --------------------------------- | ----------------------------- |
| Host      | `oracle.testnet.adjacent.markets` | `oracle.api.adjacent.markets` |
| Data tier | 15-min delayed                    | Real-time                     |
| Access    | Ungated                           | SEDA proof verification       |
| Status    | Live                              | Not generally available       |

## Health

```bash
curl "https://oracle.testnet.adjacent.markets/status/health"
```

## Read index data

The proxy exposes the same index listings and price history as the REST API
under the `/proxy` route group. Testnet needs no API key.

```bash
# List indices
curl "https://oracle.testnet.adjacent.markets/proxy/indices"

# Index price history (public tier allows interval=1hour|1d)
curl "https://oracle.testnet.adjacent.markets/proxy/indices/red/prices?interval=1hour&per_page=24"
```

See [Indices](/explore/indices) and [Reference rates](/explore/reference-rates)
for the underlying benchmarks, and the
[API reference](/api/get-api-v1-indices) for full schemas.


---
title: MCP server
url: "https://docs.adjacent.markets/explore/mcp.md"
description: Connect AI agents to Adjacent prediction-market data over the Model Context Protocol.
---

Use MCP when an AI agent needs to search Adjacent data without knowing the REST
API. The Adjacent MCP server exposes prediction-market data through the
[Model Context Protocol](https://modelcontextprotocol.io).

The server has four tools. An agent can pass an id from `list` or `find` to
`get` or `price`.

## A typical agent workflow

An agent can:

1. Use `find` when the user gives a topic, such as a race or policy question.
2. Use `get` to inspect the matching market, event, index, or rate.
3. Use `price` when the user asks how that value changed over time.
4. Use the returned ids to continue the conversation without another search.

The public endpoint supports basic discovery. Add an API key when the agent
needs realtime data, news, similar markets, or historical lookups.

For example, an agent can turn "What is the current price for the 2028
presidential market?" into a `find` call, pass the returned market id to `get`,
and then call `price` if the user asks for a chart or recent change.

## Connect to MCP

```
https://mcp.adjacent.markets/mcp
```

Public (no key) traffic uses the **15-minute-delayed** snapshot tier. For
**realtime** data, append your Adjacent API key as `apiKey`. REST uses the
`api_key` query parameter or a Bearer token. MCP uses `apiKey` on the URL:

```
https://mcp.adjacent.markets/mcp?apiKey=YOUR_KEY
```

Create and manage keys in **Settings** on [adjacent.markets](https://adjacent.markets).

## Add MCP to an agent

Most agent hosts accept a single URL under a "remote MCP" or "Streamable HTTP"
option. Config file paths vary by host. Use one of these configurations:

**Cursor / Claude (remote Streamable HTTP)**

```json
{
  "mcpServers": {
    "adjacent": {
      "url": "https://mcp.adjacent.markets/mcp"
    }
  }
}
```

**With an API key (realtime tier)**

```json
{
  "mcpServers": {
    "adjacent": {
      "url": "https://mcp.adjacent.markets/mcp?apiKey=YOUR_KEY"
    }
  }
}
```

## Choose a tool

| Tool    | When to use it                                                                                                                                                                                                                                                                                                                                                                                       |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list`  | Browse tradable events (default), markets, indices, rates, or news. News requires an API key. Search is all-words AND. For a historical market catalog, use an API key and pass `include_resolved` with `created_before` / `as_of`.                                                                                                                                                                  |
| `find`  | Discover an entity by topic when you don't have an id. Optional `type` (`index`, `rate`, `event`, `market`, `news`, `similar`). News and similar-market queries require an API key. Same historical flags as `list`. An empty search returns `SEARCH_NO_MATCH`.                                                                                                                                      |
| `get`   | Full detail by id. Indices include constituents. Index, rate, and market reads accept `as_of` for a historical snapshot (`price_at_as_of`); live `probability` is omitted. Event historical reads return `BAD_REQUEST` because the API does not store historical membership.                                                                                                                         |
| `price` | Price history. Live: a human timeframe (`24h`, `7d`, `30d`, `90d`). Index, rate, and market historical reads accept `end` or `as_of` (RFC3339 or `YYYY-MM-DD`); the default interval is `1d`. Compact mode returns the last bucket at or before the cutoff. Event historical reads return `BAD_REQUEST` because the API does not store historical membership. No such bucket is `NO_PRICE_AT_AS_OF`. |

Ids from `list` or `find` chain into `get` or `price`. Markets use
`<platform>:<raw>`, such as `kalshi:KXPRESPARTY-2028-R`. Indices and rates use
slugs such as `red` or `pres`.

Do not use a live timeframe (`30d`, `90d`) as a substitute for `end` on a
past question. Failures set `isError` and a stable `code` (`RATE_LIMITED`,
`FORBIDDEN`, `NOT_FOUND`, `SEARCH_NO_MATCH`, `NO_PRICE_AT_AS_OF`,
`CREATED_AFTER_AS_OF`, `BAD_REQUEST`).

## Learn more

* [API reference](/api/get-api-v1-indices): the underlying REST endpoints
* [Rate limits](/rate-limits): caller-visible quotas for authenticated traffic


---
title: Pricing
url: "https://docs.adjacent.markets/pricing.md"
description: API plans for realtime Adjacent data
---

| Plan    |      Price | Data                                                         | Seats | Organization limits                       | Adjacent Press                |
| ------- | ---------: | ------------------------------------------------------------ | ----: | ----------------------------------------- | ----------------------------- |
| Free    |         $0 | Public API and MCP, 15-minute delayed                        |     — | 50 requests / 10 seconds / IP at the edge | Free content                  |
| Pro     |  $50/month | Realtime indices, rates, markets, history, research, and MCP |     5 | 30 requests/minute; 20,000/day            | Complimentary for seat emails |
| Premium | $250/month | Everything in Pro with higher throughput                     |    10 | 180 requests/minute; 150,000/day          | Complimentary for seat emails |

Free price endpoints serve hourly history for the previous 30 days or daily
history for the previous 90 days. Finer intervals and deeper history are paid.

Pro is for interactive research and light automation. Premium is for teams
that need more throughput. Neither plan permits redistribution or use in a
financial product. WebSockets, the index builder, and ratings data are not
included in these v1 plans.

Paid limits are organization-wide and reset at 00:00 UTC. See
[Rate limits](/rate-limits) for response headers and over-limit behavior.
Manage a plan and see live usage in **Settings → Billing & usage**. For a
custom use case, [contact us](mailto:lucas@adjacentresearch.xyz).


---
title: Rate limits
url: "https://docs.adjacent.markets/rate-limits.md"
description: Organization-wide request ceilings for Adjacent API plans
---

| Plan    | Applies to                 |             Minute limit | Daily limit | Keyed by              |
| ------- | -------------------------- | -----------------------: | ----------: | --------------------- |
| Free    | `/api/v1/public/*`         | 50 requests / 10 seconds |           — | Client IP at the edge |
| Pro     | Authenticated realtime API |       30 requests/minute |  20,000/day | Organization          |
| Premium | Authenticated realtime API |      180 requests/minute | 150,000/day | Organization          |

Paid limits are **organization-wide**. Every API key and authenticated session
in an organization draws from the same budgets. Creating more keys does not
increase throughput. The daily budget resets at 00:00 UTC.

Public requests are limited and cached at the Cloudflare edge and are not
double-counted by the application limiter.

Realtime reads from an organization with no paid plan are refused with `403`
(see [No plan at all](#no-plan-at-all)). They are not billed against a minute
or daily budget, so they carry none of the headers below.

## Response headers

Paid (Pro and Premium) responses carry both budgets:

| Header                      | Meaning                                  |
| --------------------------- | ---------------------------------------- |
| `RateLimit-Limit`           | Plan requests per minute.                |
| `RateLimit-Remaining`       | Requests left in the current minute.     |
| `RateLimit-Reset`           | Seconds until the minute counter resets. |
| `RateLimit-Daily-Limit`     | Plan requests per UTC day.               |
| `RateLimit-Daily-Remaining` | Requests left today.                     |
| `RateLimit-Daily-Reset`     | Seconds until 00:00 UTC.                 |

An over-limit request returns `429 Too Many Requests`. It includes the same
headers, sets the exhausted remaining value to zero, and includes `Retry-After`
for the budget that blocked the request:

```json
{
  "error": "rate_limited",
  "limit": "rpm",
  "message": "Organization rpm request limit exceeded; retry after 18s.",
  "upgrade_url": "https://adjacent.markets/subscribe"
}
```

Back off for at least `Retry-After` seconds. `upgrade_url` points to the plan
catalog. It is omitted when no plan is available to buy.

The live minute and daily meters are under **Settings → Billing & usage**.

## Concurrent requests

Beyond the per-minute and daily budgets, each organization can run up to 4
requests at the same time. This capacity is dedicated to your organization,
not shared with other callers. A request over the limit waits up to 2 seconds
for a slot. If no slot frees up, it returns `429 Too Many Requests` with
`Retry-After` and the body above with `"limit": "concurrency"`.

The public tier (`/api/v1/public/*`) shares one pool of capacity across all
anonymous callers and can return `429` with `Retry-After` under load:

```json
{
  "error": "too_many_requests",
  "message": "The public API is at its concurrent request limit. Retry after 2s."
}
```

Issue requests sequentially, or keep parallelism within the limit, and back off
for `Retry-After` seconds on a concurrency 429.

## No plan at all

A 429 means a plan's budget ran out. A request from an organization with no paid
plan is refused up front instead, with `403 Forbidden`:

```json
{
  "error": "Insufficient scope: a Pro or Premium API plan is required",
  "status": 403,
  "upgrade_url": "https://adjacent.markets/subscribe"
}
```

`upgrade_url` carries the same meaning as on a 429 and is likewise omitted when
no plan is available to buy. Unlike a 429, retrying does not help: nothing
resets until the organization holds a plan.


---
title: List API keys
url: "https://docs.adjacent.markets/api/get-api-v1-api-keys.md"
description: "Returns the API keys owned by the caller's organization."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/api-keys" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "keys": [
        {
          "id": "key_a1b2c3",
          "name": "production-readonly",
          "scopes": [
            "org:events:read",
            "org:rates:read"
          ],
          "created_at": 1750000000000
        }
      ]
    }
    ```

    ```json title="401 — default" lines=false
    {
      "error": "Missing or invalid Authorization header",
      "status": 401
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "forbidden",
      "message": "an organization is required to manage API keys"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/api-keys","summary":"List API keys","description":"Returns the API keys owned by the caller's organization.","parameters":[],"responses":[{"status":"200","description":"The organization's API keys","schema":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"created_at":{"type":"integer","description":"Creation time as a Unix epoch timestamp in milliseconds."}}}}}},"example":{"keys":[{"id":"key_a1b2c3","name":"production-readonly","scopes":["org:events:read","org:rates:read"],"created_at":1750000000000}]},"examples":[{"name":"default","value":{"keys":[{"id":"key_a1b2c3","name":"production-readonly","scopes":["org:events:read","org:rates:read"],"created_at":1750000000000}]}}]},{"status":"401","description":"Unauthorized","schema":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable reason the request was not authenticated or authorized, for example a missing or malformed `Authorization` header, an invalid token, or a token lacking the required scope. This is free text whose wording can change, so branch on `status` (or the HTTP status code) instead of on this string."},"status":{"type":"integer","description":"The HTTP status code repeated in the body."}}},"example":{"error":"Missing or invalid Authorization header","status":401},"examples":[{"name":"default","value":{"error":"Missing or invalid Authorization header","status":401}}]},{"status":"403","description":"The caller has no active organization, or cannot manage API keys","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"forbidden","message":"an organization is required to manage API keys"},"examples":[{"name":"default","value":{"error":"forbidden","message":"an organization is required to manage API keys"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Create API key
url: "https://docs.adjacent.markets/api/post-api-v1-api-keys.md"
description: "Creates a new API key for the caller's organization."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X POST "https://api.adjacent.markets/api/v1/api-keys" \
      -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -d '{
      "name": "string",
      "scopes": [
        "string"
      ]
    }'
    ```

    ```json title="default" lines=false
    {
      "name": "production-readonly",
      "scopes": [
        "org:events:read",
        "org:rates:read"
      ]
    }
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="201 — default" lines=false
    {
      "id": "key_a1b2c3",
      "name": "production-readonly",
      "scopes": [
        "org:events:read",
        "org:rates:read"
      ],
      "secret": "ak_live_9f8e7d6c5b4a39281706f5e4d3c2b1a0",
      "created_at": 1750000000000
    }
    ```

    ```json title="400 — default" lines=false
    {
      "error": "bad_request",
      "message": "name and scopes are required"
    }
    ```

    ```json title="401 — default" lines=false
    {
      "error": "Missing or invalid Authorization header",
      "status": 401
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "forbidden",
      "message": "an organization is required to manage API keys"
    }
    ```

    ```json title="409 — default" lines=false
    {
      "error": "conflict",
      "message": "Key creation hit a name collision. Retry the request; the same display name may be reused."
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"post","path":"/api/v1/api-keys","summary":"Create API key","description":"Creates a new API key for the caller's organization.","parameters":[],"requestBody":{"required":true,"contentType":"application/json","schema":{"type":"object","required":["name","scopes"],"properties":{"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}}}},"examples":[{"name":"default","value":{"name":"production-readonly","scopes":["org:events:read","org:rates:read"]}}]},"responses":[{"status":"201","description":"The created API key, including its secret (returned only once).","schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"secret":{"type":"string","description":"The API key secret. Returned only once, on creation."},"created_at":{"type":"integer","description":"Creation time as a Unix epoch timestamp in milliseconds."}}},"example":{"id":"key_a1b2c3","name":"production-readonly","scopes":["org:events:read","org:rates:read"],"secret":"ak_live_9f8e7d6c5b4a39281706f5e4d3c2b1a0","created_at":1750000000000},"examples":[{"name":"default","value":{"id":"key_a1b2c3","name":"production-readonly","scopes":["org:events:read","org:rates:read"],"secret":"ak_live_9f8e7d6c5b4a39281706f5e4d3c2b1a0","created_at":1750000000000}}]},{"status":"400","description":"Invalid request body (empty name or scopes)","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"bad_request","message":"name and scopes are required"},"examples":[{"name":"default","value":{"error":"bad_request","message":"name and scopes are required"}}]},{"status":"401","description":"Unauthorized","schema":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable reason the request was not authenticated or authorized, for example a missing or malformed `Authorization` header, an invalid token, or a token lacking the required scope. This is free text whose wording can change, so branch on `status` (or the HTTP status code) instead of on this string."},"status":{"type":"integer","description":"The HTTP status code repeated in the body."}}},"example":{"error":"Missing or invalid Authorization header","status":401},"examples":[{"name":"default","value":{"error":"Missing or invalid Authorization header","status":401}}]},{"status":"403","description":"The caller has no active organization, cannot manage API keys, or requested a scope they cannot grant","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"forbidden","message":"an organization is required to manage API keys"},"examples":[{"name":"default","value":{"error":"forbidden","message":"an organization is required to manage API keys"}}]},{"status":"409","description":"A rare name collision.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"conflict","message":"Key creation hit a name collision. Retry the request; the same display name may be reused."},"examples":[{"name":"default","value":{"error":"conflict","message":"Key creation hit a name collision. Retry the request; the same display name may be reused."}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List grantable scopes
url: "https://docs.adjacent.markets/api/get-api-v1-api-keys-grantable-scopes.md"
description: "Returns the permission scopes the caller may grant when creating an API key, the permissions held by their organization role, excluding org:apikeys:manage (a key cannot manage keys)."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/api-keys/grantable-scopes" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "scopes": [
        "org:events:read",
        "org:rates:read",
        "org:indices:read",
        "org:news:read"
      ]
    }
    ```

    ```json title="401 — default" lines=false
    {
      "error": "Missing or invalid Authorization header",
      "status": 401
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "forbidden",
      "message": "an organization is required to manage API keys"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/api-keys/grantable-scopes","summary":"List grantable scopes","description":"Returns the permission scopes the caller may grant when creating an API key, the permissions held by their organization role, excluding org:apikeys:manage (a key cannot manage keys).","parameters":[],"responses":[{"status":"200","description":"Grantable permission scopes","schema":{"type":"object","properties":{"scopes":{"type":"array","items":{"type":"string","description":"A permission string, e.g. org:rates:read."}}}},"example":{"scopes":["org:events:read","org:rates:read","org:indices:read","org:news:read"]},"examples":[{"name":"default","value":{"scopes":["org:events:read","org:rates:read","org:indices:read","org:news:read"]}}]},{"status":"401","description":"Unauthorized","schema":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable reason the request was not authenticated or authorized, for example a missing or malformed `Authorization` header, an invalid token, or a token lacking the required scope. This is free text whose wording can change, so branch on `status` (or the HTTP status code) instead of on this string."},"status":{"type":"integer","description":"The HTTP status code repeated in the body."}}},"example":{"error":"Missing or invalid Authorization header","status":401},"examples":[{"name":"default","value":{"error":"Missing or invalid Authorization header","status":401}}]},{"status":"403","description":"The caller has no active organization, or cannot manage API keys","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"forbidden","message":"an organization is required to manage API keys"},"examples":[{"name":"default","value":{"error":"forbidden","message":"an organization is required to manage API keys"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Revoke API key
url: "https://docs.adjacent.markets/api/delete-api-v1-api-keys-id.md"
description: Revokes the API key with the given ID.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X DELETE "https://api.adjacent.markets/api/v1/api-keys/<id>" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "revoked": true
    }
    ```

    ```json title="401 — default" lines=false
    {
      "error": "Missing or invalid Authorization header",
      "status": 401
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "forbidden",
      "message": "an organization is required to manage API keys"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "API key not found or not owned by the caller"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"delete","path":"/api/v1/api-keys/{id}","summary":"Revoke API key","description":"Revokes the API key with the given ID.","parameters":[{"name":"id","in":"path","required":true,"description":"API key ID.","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Revocation result","schema":{"type":"object","properties":{"revoked":{"type":"boolean"}}},"example":{"revoked":true},"examples":[{"name":"default","value":{"revoked":true}}]},{"status":"401","description":"Unauthorized","schema":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable reason the request was not authenticated or authorized, for example a missing or malformed `Authorization` header, an invalid token, or a token lacking the required scope. This is free text whose wording can change, so branch on `status` (or the HTTP status code) instead of on this string."},"status":{"type":"integer","description":"The HTTP status code repeated in the body."}}},"example":{"error":"Missing or invalid Authorization header","status":401},"examples":[{"name":"default","value":{"error":"Missing or invalid Authorization header","status":401}}]},{"status":"403","description":"The caller has no active organization, or cannot manage API keys","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"forbidden","message":"an organization is required to manage API keys"},"examples":[{"name":"default","value":{"error":"forbidden","message":"an organization is required to manage API keys"}}]},{"status":"404","description":"API key not found or not owned by the caller","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"API key not found or not owned by the caller"},"examples":[{"name":"default","value":{"error":"not_found","message":"API key not found or not owned by the caller"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List events
url: "https://docs.adjacent.markets/api/get-api-v1-events.md"
description: "List all events, filterable by category, region, venue, and a resolution-date window (expiresafter / expiresbefore)."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/events" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "event_id": "kalshi:CONTROLH-2028",
          "name": "2028 House winner",
          "category": "Elections",
          "region": "US",
          "election_date": "2028-11-07",
          "description": "In 2028",
          "created_at": "2026-06-02T16:28:27.350946Z",
          "updated_at": "2026-06-02T16:29:39.257577Z",
          "market_count": 2
        },
        {
          "event_id": "kalshi:CONTROLS-2028",
          "name": "2028 Senate winner",
          "category": "Elections",
          "region": "US",
          "election_date": "2028-11-07",
          "description": "In 2028",
          "created_at": "2026-06-02T16:28:24.146031Z",
          "updated_at": "2026-06-02T16:29:34.765363Z",
          "market_count": 2
        }
      ],
      "meta": {
        "total": 204963,
        "page": 1,
        "per_page": 20,
        "total_pages": 10249,
        "has_next": true,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/events","summary":"List events","description":"List all events, filterable by category, region, venue, and a resolution-date window (`expires_after` / `expires_before`).","parameters":[{"name":"category","in":"query","description":"Filter by category","schema":{"type":"string"}},{"name":"region","in":"query","description":"Filter by region: a two-letter US state code for a state-level race, or `US` for a federal one.","schema":{"type":"string"}},{"name":"search","in":"query","description":"Case-insensitive word match over an event's member markets (question, description, series title, market ID, and market slug) plus the event name and ID.","schema":{"type":"string"}},{"name":"venue","in":"query","description":"Filter by venue: a comma-separated list of platforms (`kalshi`, `polymarket`).","schema":{"type":"string"}},{"name":"platform","in":"query","description":"Alias for `venue`.","schema":{"type":"string"}},{"name":"expires_before","in":"query","description":"ISO date/datetime inclusive upper bound on a market's `end_date` (a bare date snaps to end-of-day).","schema":{"type":"string"}},{"name":"expires_after","in":"query","description":"ISO date/datetime inclusive lower bound on a market's `end_date` (a bare date snaps to start-of-day).","schema":{"type":"string"}},{"name":"created_since","in":"query","description":"Filters events first listed on this platform at or after this ISO date or datetime.","schema":{"type":"string"}},{"name":"created_until","in":"query","description":"Filters events first listed on this platform at or before this ISO date or datetime.","schema":{"type":"string"}},{"name":"start","in":"query","deprecated":true,"description":"Deprecated.","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","deprecated":true,"description":"Deprecated.","schema":{"type":"string","format":"date-time"}},{"name":"sort","in":"query","description":"Sort key.","schema":{"type":"string","enum":["created","election_date","title","volume","open_interest","market_count"],"default":"created"}},{"name":"sort_dir","in":"query","description":"Sort direction, `asc` or `desc` (default `desc`).","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"maximum":500}}],"responses":[{"status":"200","description":"List of events","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"event_id":{"type":"string","description":"Stable identifier for the event, formed as `<venue>:<venue event ticker>` (for example `kalshi:KXPRESPARTY-2028`). Use it to fetch the event's detail and to group markets by their parent event."},"name":{"type":"string","description":"The event's title as published by its venue, intended for display."},"category":{"type":"string","description":"The event's category, folded into a fixed cross-venue taxonomy (`Politics`, `Elections`, `Economics`, `Crypto`, `Sports` and similar, with `Other` as the catch-all). Every market under the event inherits this value."},"region":{"type":["string","null"],"description":"Geographic scope of the event: a two-letter US state code for state-level races, or `US` for federal ones. Null whenever the event carries no geographic anchor, which covers non-election events and all Polymarket events."},"election_date":{"type":["string","null"],"format":"date","description":"The election day this event resolves against, derived from the event's identifier for election markets and null for everything else. Pass `sort=election_date` to order the events list by it (undated events last)."},"description":{"type":["string","null"],"description":"Longer description of the event as published by its venue. Omitted when the venue supplies none."},"created_at":{"type":["string","null"],"format":"date-time","description":"When this event was first recorded by the API. It is a first-seen timestamp on our side, not a venue publication date."},"updated_at":{"type":["string","null"],"format":"date-time","description":"When this event's record was last written. The record is rewritten every time the event is re-read from its venue, so this advances even when no field actually changed."},"market_count":{"type":"integer","description":"Total number of markets under this event, counted with no status or filter restriction, so settled and closed markets are included. The public events list reports a `market_count` covering only the markets that match that request's filters, so the two can legitimately differ for the same event."},"volume":{"type":["number","null"],"description":"Summed all-time contract/share volume across the event's markets, not dollars. Unit is in `volume_unit`. Omitted when no market reports volume."},"volume_unit":{"description":"Wire unit for `volume`, from the event's venue (every market shares the event's venue). See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"open_interest":{"type":["number","null"],"description":"Summed open interest across the event's markets. Unit is in `open_interest_unit`. Omitted when no market reports open interest."},"open_interest_unit":{"description":"Wire unit for `open_interest`, from the event's venue. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"event_id":"kalshi:CONTROLH-2028","name":"2028 House winner","category":"Elections","region":"US","election_date":"2028-11-07","description":"In 2028","created_at":"2026-06-02T16:28:27.350946Z","updated_at":"2026-06-02T16:29:39.257577Z","market_count":2},{"event_id":"kalshi:CONTROLS-2028","name":"2028 Senate winner","category":"Elections","region":"US","election_date":"2028-11-07","description":"In 2028","created_at":"2026-06-02T16:28:24.146031Z","updated_at":"2026-06-02T16:29:34.765363Z","market_count":2}],"meta":{"total":204963,"page":1,"per_page":20,"total_pages":10249,"has_next":true,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"event_id":"kalshi:CONTROLH-2028","name":"2028 House winner","category":"Elections","region":"US","election_date":"2028-11-07","description":"In 2028","created_at":"2026-06-02T16:28:27.350946Z","updated_at":"2026-06-02T16:29:39.257577Z","market_count":2},{"event_id":"kalshi:CONTROLS-2028","name":"2028 Senate winner","category":"Elections","region":"US","election_date":"2028-11-07","description":"In 2028","created_at":"2026-06-02T16:28:24.146031Z","updated_at":"2026-06-02T16:29:34.765363Z","market_count":2}],"meta":{"total":204963,"page":1,"per_page":20,"total_pages":10249,"has_next":true,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get event details
url: "https://docs.adjacent.markets/api/get-api-v1-events-id.md"
description: Get event with all linked markets
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/events/<id>" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "event_id": "kalshi:CONTROLH-2028",
      "name": "2028 House winner",
      "description": "In 2028",
      "category": "Elections",
      "markets": [
        {
          "market_id": "kalshi:CONTROLH-2028-D",
          "display_ticker": "CONTROLH-2028-D",
          "platform": "kalshi",
          "question": "Will Democrats win control of the House in 2028?",
          "probability": 65,
          "tape_mid_1m": 64.8,
          "volume": 1850000,
          "volume_unit": "contracts"
        },
        {
          "market_id": "kalshi:CONTROLH-2028-R",
          "display_ticker": "CONTROLH-2028-R",
          "platform": "kalshi",
          "question": "Will Republicans win control of the House in 2028?",
          "probability": 36,
          "tape_mid_1m": 36.2,
          "volume": 1420000,
          "volume_unit": "contracts"
        }
      ]
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Event not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/events/{id}","summary":"Get event details","description":"Get event with all linked markets","parameters":[{"name":"id","in":"path","required":true,"description":"Event ID","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Event details","schema":{"type":"object","properties":{"event_id":{"type":"string","description":"Stable identifier for the event, formed as `<venue>:<venue event ticker>` (for example `kalshi:KXPRESPARTY-2028`)."},"name":{"type":"string","description":"The event's title as published by its venue, intended for display."},"description":{"type":["string","null"],"description":"Longer description of the event as published by its venue. Null when the venue supplies none."},"category":{"type":"string","description":"The event's category, folded into a fixed cross-venue taxonomy (`Politics`, `Elections`, `Economics`, `Crypto`, `Sports` and similar, with `Other` as the catch-all)."},"markets":{"type":"array","description":"Every market under this event, with no status filter applied, so settled and closed markets appear alongside open ones. Ordered by market identifier, and each entry carries that market's latest price, freshest tape mid, and all-time volume.","items":{"type":"object","required":["market_id","display_ticker","platform"],"properties":{"market_id":{"type":"string","description":"Canonical identifier for this child market, formed as `<platform>:<venue ticker>` (for example `kalshi:KXPRESPARTY-2028-R`). This is the id every other endpoint accepts."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"The venue that lists this market: `kalshi` or `polymarket`. It is also the prefix of `market_id`, and it determines what `volume` is counted in (see `volume_unit`)."},"question":{"type":["string","null"],"description":"Market question text (same field as MarketSummary.question)."},"probability":{"type":["number","null"],"format":"float","description":"Yes-side probability on the 0-100 cents scale, from the market's last traded price. Same projection as MarketSummary.probability."},"tape_mid_1m":{"type":["number","null"],"description":"Most recent 1-minute average of yes-side trade prices within the trailing 7 days, on the 0-100 cents scale. Distinct from probability, which is the single last traded price. This is the newest minute that had trades, not necessarily the minute just past. Null when the market has not traded in the last 7 days."},"volume":{"type":["number","null"],"format":"float","description":"All-time traded volume as a contract/share count, the same number the markets list serves for this market (MarketSummary.volume), so the two surfaces agree. Unit is in `volume_unit`."},"volume_unit":{"description":"Unit for volume: `contracts` for Kalshi and `shares` for Polymarket. Without it the volume column mixes two different quantities.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true}}}}}},"example":{"event_id":"kalshi:CONTROLH-2028","name":"2028 House winner","description":"In 2028","category":"Elections","markets":[{"market_id":"kalshi:CONTROLH-2028-D","display_ticker":"CONTROLH-2028-D","platform":"kalshi","question":"Will Democrats win control of the House in 2028?","probability":65,"tape_mid_1m":64.8,"volume":1850000,"volume_unit":"contracts"},{"market_id":"kalshi:CONTROLH-2028-R","display_ticker":"CONTROLH-2028-R","platform":"kalshi","question":"Will Republicans win control of the House in 2028?","probability":36,"tape_mid_1m":36.2,"volume":1420000,"volume_unit":"contracts"}]},"examples":[{"name":"default","value":{"event_id":"kalshi:CONTROLH-2028","name":"2028 House winner","description":"In 2028","category":"Elections","markets":[{"market_id":"kalshi:CONTROLH-2028-D","display_ticker":"CONTROLH-2028-D","platform":"kalshi","question":"Will Democrats win control of the House in 2028?","probability":65,"tape_mid_1m":64.8,"volume":1850000,"volume_unit":"contracts"},{"market_id":"kalshi:CONTROLH-2028-R","display_ticker":"CONTROLH-2028-R","platform":"kalshi","question":"Will Republicans win control of the House in 2028?","probability":36,"tape_mid_1m":36.2,"volume":1420000,"volume_unit":"contracts"}]}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Event not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Event not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Event not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Export events list
url: "https://docs.adjacent.markets/api/get-api-v1-export-events-ext.md"
description: Export a filtered list of events as a CSV or TSV file download.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/export/events/csv" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="400 — default" lines=false
    {
      "error": "bad_request",
      "message": "Invalid format: xml"
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/export/events/{ext}","summary":"Export events list","description":"Export a filtered list of events as a CSV or TSV file download.","parameters":[{"name":"ext","in":"path","required":true,"description":"Export file format","schema":{"type":"string","enum":["csv","tsv"]}},{"name":"category","in":"query","description":"Filter by category","schema":{"type":"string"}},{"name":"region","in":"query","description":"Filter by region: a two-letter US state code for a state-level race, or `US` for a federal one.","schema":{"type":"string"}},{"name":"search","in":"query","description":"Case-insensitive word match over an event's member markets, name, and ID.","schema":{"type":"string"}},{"name":"venue","in":"query","description":"Filter by venue: a comma-separated list of platforms (`kalshi`, `polymarket`).","schema":{"type":"string"}},{"name":"platform","in":"query","description":"Alias for `venue`.","schema":{"type":"string"}},{"name":"expires_before","in":"query","description":"ISO date/datetime inclusive upper bound on a market's `end_date` (a bare date snaps to end-of-day).","schema":{"type":"string"}},{"name":"expires_after","in":"query","description":"ISO date/datetime inclusive lower bound on a market's `end_date` (a bare date snaps to start-of-day).","schema":{"type":"string"}},{"name":"created_since","in":"query","description":"Filters events first listed on this platform at or after this ISO date or datetime.","schema":{"type":"string"}},{"name":"created_until","in":"query","description":"Filters events first listed on this platform at or before this ISO date or datetime.","schema":{"type":"string"}},{"name":"start","in":"query","deprecated":true,"description":"Deprecated.","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","deprecated":true,"description":"Deprecated.","schema":{"type":"string","format":"date-time"}},{"name":"sort","in":"query","description":"Sort key.","schema":{"type":"string","enum":["created","election_date","title","volume","open_interest","market_count"],"default":"created"}},{"name":"sort_dir","in":"query","description":"Sort direction, `asc` or `desc` (default `desc`).","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}],"responses":[{"status":"200","description":"CSV/TSV file of events (up to 10,000 rows)","examples":[]},{"status":"400","description":"Invalid format (ext must be csv or tsv)","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"bad_request","message":"Invalid format: xml"},"examples":[{"name":"default","value":{"error":"bad_request","message":"Invalid format: xml"}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Export event markets
url: "https://docs.adjacent.markets/api/get-api-v1-export-events-id-marketsext.md"
description: Export all markets belonging to an event as a CSV or TSV file download.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/export/events/<id>/markets.csv" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="400 — default" lines=false
    {
      "error": "bad_request",
      "message": "Invalid format: xml"
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Resource not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/export/events/{id}/markets.{ext}","summary":"Export event markets","description":"Export all markets belonging to an event as a CSV or TSV file download.","parameters":[{"name":"id","in":"path","required":true,"description":"Event ID","schema":{"type":"string"}},{"name":"ext","in":"path","required":true,"description":"Export file format","schema":{"type":"string","enum":["csv","tsv"]}}],"responses":[{"status":"200","description":"CSV/TSV file of the event's markets","examples":[]},{"status":"400","description":"Invalid format (ext must be csv or tsv)","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"bad_request","message":"Invalid format: xml"},"examples":[{"name":"default","value":{"error":"bad_request","message":"Invalid format: xml"}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Event not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Resource not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Resource not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Export indices list
url: "https://docs.adjacent.markets/api/get-api-v1-export-indices-ext.md"
description: Export the list of indices as a CSV or TSV file download.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/export/indices/csv" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="400 — default" lines=false
    {
      "error": "bad_request",
      "message": "Invalid format: xml"
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/export/indices/{ext}","summary":"Export indices list","description":"Export the list of indices as a CSV or TSV file download.","parameters":[{"name":"ext","in":"path","required":true,"description":"Export file format","schema":{"type":"string","enum":["csv","tsv"]}}],"responses":[{"status":"200","description":"CSV/TSV file of indices","examples":[]},{"status":"400","description":"Invalid format (ext must be csv or tsv)","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"bad_request","message":"Invalid format: xml"},"examples":[{"name":"default","value":{"error":"bad_request","message":"Invalid format: xml"}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Export index price history
url: "https://docs.adjacent.markets/api/get-api-v1-export-indices-id-pricesext.md"
description: Export historical index values as a CSV or TSV file download.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/export/indices/<id>/prices.csv" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="400 — default" lines=false
    {
      "error": "bad_request",
      "message": "Invalid format: xml"
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/export/indices/{id}/prices.{ext}","summary":"Export index price history","description":"Export historical index values as a CSV or TSV file download.","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g.","schema":{"type":"string"}},{"name":"ext","in":"path","required":true,"description":"Export file format","schema":{"type":"string","enum":["csv","tsv"]}},{"name":"per_page","in":"query","description":"Points per page (1-10000).","schema":{"type":"integer","default":100,"minimum":1,"maximum":10000}},{"name":"start","in":"query","description":"Start time","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","description":"End time","schema":{"type":"string","format":"date-time"}},{"name":"interval","in":"query","description":"Time bucket interval (daily, 1day also accepted as aliases for 1d)","schema":{"type":"string","enum":["1min","5min","1hour","1d"],"default":"5min"}},{"name":"order","in":"query","description":"Sort direction by timestamp","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","default":1,"minimum":1}}],"responses":[{"status":"200","description":"CSV/TSV file of index price history","examples":[]},{"status":"400","description":"Invalid format or interval","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"bad_request","message":"Invalid format: xml"},"examples":[{"name":"default","value":{"error":"bad_request","message":"Invalid format: xml"}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Export markets list
url: "https://docs.adjacent.markets/api/get-api-v1-export-markets-ext.md"
description: Export a filtered list of markets as a CSV or TSV file download.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/export/markets/csv" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="400 — default" lines=false
    {
      "error": "bad_request",
      "message": "Invalid format: xml"
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/export/markets/{ext}","summary":"Export markets list","description":"Export a filtered list of markets as a CSV or TSV file download.","parameters":[{"name":"ext","in":"path","required":true,"description":"Export file format","schema":{"type":"string","enum":["csv","tsv"]}},{"name":"platform","in":"query","description":"Filter by platform (kalshi, polymarket)","schema":{"type":"string"}},{"name":"category","in":"query","description":"Filter by category","schema":{"type":"string"}},{"name":"search","in":"query","description":"Case-insensitive word match over the market's question, description, series title, market ID (e.g. kalshi:KXPRESPARTY-2028-R), and market slug.","schema":{"type":"string"}},{"name":"tag","in":"query","description":"Case-sensitive substring match against the market's raw metadata document (not a discrete tag field), so short values match broadly.","schema":{"type":"string"}},{"name":"start","in":"query","description":"Filter by creation date (after)","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","description":"Filter by creation date (before)","schema":{"type":"string","format":"date-time"}},{"name":"end_date_after","in":"query","description":"Filter markets ending after this date","schema":{"type":"string","format":"date-time"}},{"name":"end_date_before","in":"query","description":"Filter markets ending before this date","schema":{"type":"string","format":"date-time"}},{"name":"probability_min","in":"query","description":"Minimum probability (0-100)","schema":{"type":"number"}},{"name":"probability_max","in":"query","description":"Maximum probability (0-100)","schema":{"type":"number"}},{"name":"volume_min","in":"query","description":"Minimum volume","schema":{"type":"number"}},{"name":"volume_max","in":"query","description":"Maximum volume","schema":{"type":"number"}},{"name":"include_closed","in":"query","description":"Include closed markets","schema":{"type":"boolean","default":false}},{"name":"include_resolved","in":"query","description":"Include resolved markets","schema":{"type":"boolean","default":false}},{"name":"status","in":"query","description":"Filter by exact market status.","schema":{"type":"string"}},{"name":"state_code","in":"query","description":"Filter by assigned US state abbreviation (case-insensitive)","schema":{"type":"string"}},{"name":"sort","in":"query","description":"Sort key.","schema":{"type":"string","enum":["volume","ticker","price","open_interest","expiration"],"default":"volume"}},{"name":"sort_dir","in":"query","description":"Sort direction","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}],"responses":[{"status":"200","description":"CSV/TSV file of markets (up to 10,000 rows)","examples":[]},{"status":"400","description":"Invalid format (ext must be csv or tsv)","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"bad_request","message":"Invalid format: xml"},"examples":[{"name":"default","value":{"error":"bad_request","message":"Invalid format: xml"}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Export market price history
url: "https://docs.adjacent.markets/api/get-api-v1-export-markets-id-pricesext.md"
description: Export historical price data for a market as a CSV or TSV file download.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/export/markets/<id>/prices.csv" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="400 — default" lines=false
    {
      "error": "bad_request",
      "message": "Invalid format: xml"
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Resource not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/export/markets/{id}/prices.{ext}","summary":"Export market price history","description":"Export historical price data for a market as a CSV or TSV file download.","parameters":[{"name":"id","in":"path","required":true,"description":"Market ID","schema":{"type":"string"}},{"name":"ext","in":"path","required":true,"description":"Export file format","schema":{"type":"string","enum":["csv","tsv"]}},{"name":"per_page","in":"query","description":"Points per page (1-10000).","schema":{"type":"integer","default":100,"minimum":1,"maximum":10000}},{"name":"start","in":"query","description":"Start time","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","description":"End time","schema":{"type":"string","format":"date-time"}},{"name":"interval","in":"query","description":"Time bucket interval (daily, 1day also accepted as aliases for 1d)","schema":{"type":"string","enum":["1min","5min","1hour","1d"],"default":"5min"}},{"name":"order","in":"query","description":"Sort direction by timestamp","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","default":1,"minimum":1}}],"responses":[{"status":"200","description":"CSV/TSV file of market price history","examples":[]},{"status":"400","description":"Invalid format or interval","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"bad_request","message":"Invalid format: xml"},"examples":[{"name":"default","value":{"error":"bad_request","message":"Invalid format: xml"}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Market not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Resource not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Resource not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Export market trades
url: "https://docs.adjacent.markets/api/get-api-v1-export-markets-id-tradesext.md"
description: "Export trade history for a market as a CSV or TSV file download, newest first."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/export/markets/<id>/trades.csv" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="400 — default" lines=false
    {
      "error": "bad_request",
      "message": "Invalid format: xml"
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Resource not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/export/markets/{id}/trades.{ext}","summary":"Export market trades","description":"Export trade history for a market as a CSV or TSV file download, newest first.","parameters":[{"name":"id","in":"path","required":true,"description":"Market ID","schema":{"type":"string"}},{"name":"ext","in":"path","required":true,"description":"Export file format","schema":{"type":"string","enum":["csv","tsv"]}},{"name":"per_page","in":"query","description":"Trades per page (1-10000).","schema":{"type":"integer","default":100,"minimum":1,"maximum":10000}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","default":1,"minimum":1}},{"name":"from","in":"query","required":false,"description":"Lower bound on trade `created_time` (ISO-8601).","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"description":"Upper bound on trade `created_time` (ISO-8601, exclusive).","schema":{"type":"string","format":"date-time"}}],"responses":[{"status":"200","description":"CSV/TSV file of market trades","examples":[]},{"status":"400","description":"Invalid format (ext must be csv or tsv)","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"bad_request","message":"Invalid format: xml"},"examples":[{"name":"default","value":{"error":"bad_request","message":"Invalid format: xml"}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Market not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Resource not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Resource not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Export reference rates list
url: "https://docs.adjacent.markets/api/get-api-v1-export-rates-ext.md"
description: Export the list of reference rates as a CSV or TSV file download.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/export/rates/csv" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="400 — default" lines=false
    {
      "error": "bad_request",
      "message": "Invalid format: xml"
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/export/rates/{ext}","summary":"Export reference rates list","description":"Export the list of reference rates as a CSV or TSV file download.","parameters":[{"name":"ext","in":"path","required":true,"description":"Export file format","schema":{"type":"string","enum":["csv","tsv"]}},{"name":"start","in":"query","description":"Only consider rate prices at or after this time when selecting the latest price/spread. Defaults to seven days before now; omit to use that window.","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","description":"Only consider rate prices at or before this time when selecting the latest price/spread","schema":{"type":"string","format":"date-time"}}],"responses":[{"status":"200","description":"CSV/TSV file of reference rates","examples":[]},{"status":"400","description":"Invalid format (ext must be csv or tsv)","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"bad_request","message":"Invalid format: xml"},"examples":[{"name":"default","value":{"error":"bad_request","message":"Invalid format: xml"}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Export reference rate price history
url: "https://docs.adjacent.markets/api/get-api-v1-export-rates-id-pricesext.md"
description: "Export historical reference rate values as a CSV or TSV file download, newest first."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/export/rates/<id>/prices.csv" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="400 — default" lines=false
    {
      "error": "bad_request",
      "message": "Invalid format: xml"
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/export/rates/{id}/prices.{ext}","summary":"Export reference rate price history","description":"Export historical reference rate values as a CSV or TSV file download, newest first.","parameters":[{"name":"id","in":"path","required":true,"description":"Rate ID","schema":{"type":"string"}},{"name":"ext","in":"path","required":true,"description":"Export file format","schema":{"type":"string","enum":["csv","tsv"]}},{"name":"per_page","in":"query","description":"Points per page (1-10000).","schema":{"type":"integer","default":100,"minimum":1,"maximum":10000}},{"name":"start","in":"query","description":"Start time","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","description":"End time","schema":{"type":"string","format":"date-time"}},{"name":"interval","in":"query","description":"Time bucket interval (daily, 1day also accepted as aliases for 1d)","schema":{"type":"string","enum":["1min","5min","1hour","1d"],"default":"5min"}},{"name":"order","in":"query","description":"Sort direction by timestamp","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","default":1,"minimum":1}}],"responses":[{"status":"200","description":"CSV/TSV file of reference rate price history","examples":[]},{"status":"400","description":"Invalid format or interval","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"bad_request","message":"Invalid format: xml"},"examples":[{"name":"default","value":{"error":"bad_request","message":"Invalid format: xml"}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List indices
url: "https://docs.adjacent.markets/api/get-api-v1-indices.md"
description: Get all available indices
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/indices" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "index_id": "red",
          "name": "Republican Political Future Index",
          "ticker": "RED",
          "description": "Composite of Republican party-line contests across all levels of office in the United States",
          "constituents_count": 5,
          "latest_price": 91.3069,
          "updated_at": "2026-06-20T19:16:06.844983Z",
          "methodology": "upfi",
          "created_at": "2026-06-02T14:20:24.299003Z",
          "display_order": 1,
          "halted": false
        },
        {
          "index_id": "blue",
          "name": "Democratic Political Future Index",
          "ticker": "BLUE",
          "description": "Composite of Democratic party-line contests across all levels of office in the United States",
          "constituents_count": 5,
          "latest_price": 108.5114,
          "updated_at": "2026-06-20T19:16:06.740650Z",
          "methodology": "upfi",
          "created_at": "2026-06-02T14:20:24.587181Z",
          "display_order": 2,
          "halted": false
        }
      ],
      "meta": {
        "total": 12,
        "page": 1,
        "per_page": 20,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/indices","summary":"List indices","description":"Get all available indices","parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"maximum":500}}],"responses":[{"status":"200","description":"List of indices","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","required":["index_id","name","ticker","description","constituents_count","is_composite","office_category"],"properties":{"index_id":{"type":"string","description":"Stable identifier for the index (for example `red`). Use it as the `{id}` path parameter on the index detail, constituents, and price endpoints."},"name":{"type":"string","description":"Full display name of the index."},"ticker":{"type":"string","description":"Short uppercase symbol for the index (for example `RED`). The detail endpoint accepts either this ticker (case-insensitively) or `index_id` as its path parameter."},"description":{"type":"string","description":"One-line description of what the index tracks, suitable for a listing card."},"constituents_count":{"type":"integer","description":"Number of constituents in the index: member markets for a market-basket index, or child sub-indices for a composite. A derived index that inherits its book from a base index reports 0 and names that base in `base_index_id`."},"is_composite":{"type":"boolean","description":"True for a composite index (its constituents are other indices and its price blends child sub-index values); false for a market-basket index (its constituents are exchange markets). Always present, so a client can branch on index kind even when the index has no constituents yet."},"office_category":{"type":["string","null"],"description":"The index's declared office category (lowercase, e.g. \"senate\"), the input to methodology weighting and composite child-weight derivation. Null for composites and uncategorized indices; always present."},"latest_price":{"type":["number","null"],"description":"Most recent index level, on the base-100 index scale (100 is neutral; for the probability-based families each point above or below 100 is one percentage point of the blended win probability). Omitted when the index has no computed value yet."},"previous_close_1d":{"type":["number","null"],"description":"The index level at the previous daily close, meaning the most recent completed daily close before the current day in US Eastern time, not a rolling 24-hour window. Baseline for change_1d."},"change_1d":{"type":["number","null"],"description":"Trailing percent change from the previous completed ET daily close (`previous_close_1d`) to the live tip. Omitted when there is no prior daily close."},"price_change_1d":{"type":["number","null"],"description":"Absolute 1-day change in index points (latest_price minus previous_close_1d), measured against the same previous ET daily close as change_1d. Omitted when there is no prior daily close."},"price_change_7d":{"type":["number","null"],"description":"Absolute 7-day change in index points (latest_price minus previous_close_7d), measured against the same daily-close baseline as change_7d. Omitted when there is no daily close that far back."},"price_change_30d":{"type":["number","null"],"description":"Absolute 30-day change in index points (latest_price minus previous_close_30d), measured against the same daily-close baseline as change_30d. Omitted when there is no daily close that far back."},"price_change_90d":{"type":["number","null"],"description":"Absolute 90-day change in index points (latest_price minus previous_close_90d), measured against the same daily-close baseline as change_90d. Omitted when there is no daily close that far back."},"change_7d":{"type":["number","null"],"description":"Trailing percent change from the index value 7 days ago to the live tip, from the daily close series. Omitted when there is no daily close that far back."},"change_30d":{"type":["number","null"],"description":"Trailing percent change over the last 30 days. Omitted when there is no daily close that far back."},"change_90d":{"type":["number","null"],"description":"Trailing percent change over the last 90 days. Omitted when there is no daily close that far back."},"previous_close_7d":{"type":["number","null"],"description":"The index value (daily close) 7 days before the snapshot, the baseline change_7d is measured against, so a client can show the absolute change on the same baseline. Omitted when there is no daily close that far back."},"previous_close_30d":{"type":["number","null"],"description":"The index value (daily close) 30 days before the snapshot."},"previous_close_90d":{"type":["number","null"],"description":"The index value (daily close) 90 days before the snapshot."},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp of `latest_price`. Omitted when the index has no computed value yet."},"methodology":{"type":["string","null"],"description":"Key of the methodology family that defines this index's constituent weighting and level calculation, for example `upfi`, `battleground`, or `total_return`. Null for an index with no methodology recorded."},"quote_convention":{"type":"string","description":"The unit this index quotes trailing performance in. `percent`: render the `change_*` fields. `points`: render the `price_change_*` fields, because the level is a point sum and a percent of it carries no meaning.","enum":["percent","points"]},"base_index_id":{"type":["string","null"],"description":"For a total_return index, the composite index it derives its book from; null for every curated family."},"created_at":{"type":"string","format":"date-time","description":"When the index was created in this API. Returned by the authenticated indices list only."},"display_order":{"type":["integer","null"],"description":"Presentation ordering; lower values sort first, null sorts last."},"halted":{"type":"boolean","description":"True when the latest index value was carried forward because the index fell below its constituent floor."},"halt_valid_constituents":{"type":["integer","null"],"description":"When halted, the valid (priced, guardrail-passing) constituents at the most recent halt cycle. Omitted when not halted."},"halt_min_constituents":{"type":["integer","null"],"description":"When halted, the category constituent floor the index fell below. Omitted when not halted."},"halt_reason":{"type":["string","null"],"description":"When halted, a human-readable explanation of the halt, composed from the constituent halt counts. Omitted when not halted."},"party_side":{"type":["string","null"],"description":"Which party line the basket is priced on, or null for a non-party index. Drives composition.state_exposure.party_lean (the Dem/Rep axis the state map colors on). Always present so a client can render the side an index carries rather than inferring it.","enum":["republican","democrat"]},"visibility":{"type":"string","description":"Access level of the index. `public` is visible to everyone; `organization` is visible to members of listed organizations. Other reserved values may appear on authenticated responses. Omitted on the anonymous public tier, which returns only public indices.","enum":["public","superuser","organization"]}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"index_id":"red","name":"Republican Political Future Index","ticker":"RED","description":"Composite of Republican party-line contests across all levels of office in the United States","constituents_count":5,"latest_price":91.3069,"updated_at":"2026-06-20T19:16:06.844983Z","methodology":"upfi","created_at":"2026-06-02T14:20:24.299003Z","display_order":1,"halted":false},{"index_id":"blue","name":"Democratic Political Future Index","ticker":"BLUE","description":"Composite of Democratic party-line contests across all levels of office in the United States","constituents_count":5,"latest_price":108.5114,"updated_at":"2026-06-20T19:16:06.740650Z","methodology":"upfi","created_at":"2026-06-02T14:20:24.587181Z","display_order":2,"halted":false}],"meta":{"total":12,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"index_id":"red","name":"Republican Political Future Index","ticker":"RED","description":"Composite of Republican party-line contests across all levels of office in the United States","constituents_count":5,"latest_price":91.3069,"updated_at":"2026-06-20T19:16:06.844983Z","methodology":"upfi","created_at":"2026-06-02T14:20:24.299003Z","display_order":1,"halted":false},{"index_id":"blue","name":"Democratic Political Future Index","ticker":"BLUE","description":"Composite of Democratic party-line contests across all levels of office in the United States","constituents_count":5,"latest_price":108.5114,"updated_at":"2026-06-20T19:16:06.740650Z","methodology":"upfi","created_at":"2026-06-02T14:20:24.587181Z","display_order":2,"halted":false}],"meta":{"total":12,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get index details
url: "https://docs.adjacent.markets/api/get-api-v1-indices-id.md"
description: Get detailed information about a specific index
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/indices/<id>" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "index_id": "red",
      "name": "Republican Political Future Index",
      "ticker": "RED",
      "description": "Composite of Republican party-line contests across all levels of office in the United States",
      "constituents_count": 5,
      "latest_price": 91.3069,
      "price_change_1d": 0.2663,
      "price_change_7d": -0.3112,
      "halted": false
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Index not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/indices/{id}","summary":"Get index details","description":"Get detailed information about a specific index","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g.","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Index details","schema":{"type":"object","required":["index_id","name","ticker","description","constituents_count","is_composite","office_category"],"properties":{"index_id":{"type":"string","description":"Stable identifier for the index (for example `red`). Use it as the `{id}` path parameter on the index detail, constituents, and price endpoints."},"name":{"type":"string","description":"Full display name of the index."},"ticker":{"type":"string","description":"Short uppercase symbol for the index (for example `RED`). This endpoint accepts either this ticker (case-insensitively) or `index_id` as its path parameter."},"description":{"type":["string","null"],"description":"Free-text description of what the index tracks."},"methodology":{"type":["string","null"],"description":"Registered methodology key used to compute the index. Omitted only when no methodology is stored."},"quote_convention":{"type":"string","description":"The unit this index quotes trailing performance in. `percent`: render the `change_*` fields. `points`: render the `price_change_*` fields, because the level is a point sum and a percent of it carries no meaning.","enum":["percent","points"]},"constituents_count":{"type":"integer","description":"Number of constituents in the index: member markets for a market-basket index, or child sub-indices for a composite. A derived index that inherits its book from a base index reports 0 and names that base in `base_index_id`."},"is_composite":{"type":"boolean","description":"True for a composite index (its constituents are other indices and its price blends child sub-index values); false for a market-basket index (its constituents are exchange markets). Always present, so a client can branch on index kind even when the index has no constituents yet."},"office_category":{"type":["string","null"],"description":"The index's declared office category (lowercase, e.g. \"senate\"), the input to methodology weighting and composite child-weight derivation. Null for composites and uncategorized indices; always present."},"base_index_id":{"type":["string","null"],"description":"For a derived total_return index, the composite index it compounds the returns of; null for the curated families, which have no base. The detail page shows this in place of the constituent count a derived index lacks."},"latest_price":{"type":["number","null"],"description":"Most recent index level, on the base-100 index scale (100 is neutral). See `level_interpretation` for how this index's methodology frames the level, since a probability family and a total-return family read the same number differently."},"level_interpretation":{"type":"array","description":"Methodology-resolved rows explaining what latest_price means, formatted server-side (the curated families frame it as a composite probability, total_return as a compounding return). The client renders them verbatim; omitted when the level or the methodology is unavailable.","items":{"type":"object","required":["label","value"],"properties":{"label":{"type":"string"},"value":{"type":"string"}}}},"price_change_1d":{"type":["number","null"],"description":"Absolute change in index points (not a percent) from the previous daily close to `latest_price`. The baseline is the last completed daily close before the current day in US Eastern time, so this is a change against a settled value rather than a rolling 24-hour window."},"price_change_7d":{"type":["number","null"],"description":"Absolute change in index points (not a percent) from the daily close seven days before the current day in US Eastern time to `latest_price`. Null when the index has no daily close that far back."},"previous_close_1d":{"type":["number","null"],"description":"The index level at the previous daily close, meaning the last completed daily close before the current day in US Eastern time, not a rolling 24-hour window. Returned by `GET /api/v1/public/indices/{id}`; omitted on `GET /api/v1/indices/{id}`."},"previous_close_7d":{"type":["number","null"],"description":"The index level at the daily close seven days before the current day in US Eastern time, the baseline `price_change_7d` is measured against. Returned by `GET /api/v1/public/indices/{id}`; omitted on `GET /api/v1/indices/{id}`."},"stats":{"description":"Trailing returns and risk statistics computed from the index's daily close series over roughly the trailing 400 days. Returned by both index detail endpoints; the values are null individually when the series is too short for that window.","allOf":[{"type":"object","properties":{"trailing_returns":{"type":"array","description":"Percent price change over each of six fixed trailing windows: 1D, 1W, 1M, 3M, YTD, and 1Y.","items":{"type":"object","required":["label"],"properties":{"label":{"type":"string","description":"The trailing window this return covers: `1D`, `1W`, `1M`, `3M`, `YTD`, or `1Y`."},"value":{"type":["number","null"],"description":"Percent change from the value at the start of the window to the latest value in the series. Null when the series has no data point close enough to the start of that window."},"point_change":{"type":["number","null"],"description":"Absolute change in the level's own units over the same window. Point-quoted indices (quote_convention `points`) express trailing performance with this figure; omitted when no comparable historical point exists."}}}},"risk":{"type":"object","description":"Volatility, range, and period return computed over the most recent 31 points of the daily series. The window counts data points, so a series with gaps spans more than 31 calendar days.","properties":{"volatility":{"type":["number","null"],"description":"Annualized volatility in percent, from the daily returns across the most recent 31 daily data points, annualized over 365 days because these markets trade every calendar day. Null when the daily series has fewer than 3 points."},"daily_vol":{"type":["number","null"],"description":"Standard deviation of the daily returns across the most recent 31 daily data points, in percent and not annualized. Null when the daily series has fewer than 3 points."},"range_high":{"type":["number","null"],"description":"Highest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"range_low":{"type":["number","null"],"description":"Lowest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"return_pct":{"type":["number","null"],"description":"Percent change from the first to the last of the most recent 31 daily data points. Null when the daily series has fewer than 3 points."}}}}}],"nullable":true},"composition":{"description":"Breakdown of the index over its flattened constituents: per-state exposure and a maturity profile of when those constituents expire.","allOf":[{"type":"object","properties":{"state_exposure":{"type":"array","description":"Per-state breakdown of the index, alphabetical by state code. Only constituents that map to a US state are represented, so a national contest contributes to none of these entries.","items":{"type":"object","properties":{"state_code":{"type":"string","description":"Two-letter US state code. Entries are ordered alphabetically, and only constituents that map to a state appear, so national contests are absent."},"probability":{"type":"number","description":"Weight-blended probability for the state, 0-100, across the markets listed in `markets`. Falls back to a plain average of those markets when none of them carry weight."},"party_lean":{"type":"number","description":"Weight-blended Republican lean for map coloring (0 = Dem favored, 100 = Rep favored). Derived from probability and the index's party_side (democrat inverts; republican or unset passes through). Heatmap color uses this field only."},"weight":{"type":"number","description":"Combined index weight of this state's markets, as a fraction rather than a percent."},"count":{"type":"integer","description":"Number of constituent markets contributing to this state."},"markets":{"type":"array","description":"The individual constituent markets behind this state's blended probability and weight.","items":{"type":"object","required":["ticker","display_ticker","price","weight"],"properties":{"ticker":{"type":"string","description":"Raw exchange ticker of the market. Use `display_ticker` for a label."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"name":{"type":["string","null"],"description":"The market's question text. Absent when the market has no question on record."},"price":{"type":"number","description":"The market's probability, 0-100, as it entered the index calculation. A market with no usable price is reported as 0."},"weight":{"type":"number","description":"The market's effective weight in the index, as a fraction rather than a percent."}}}}}}},"maturity":{"type":"object","description":"When the index's constituents expire: future expirations bucketed by date, plus a count of constituents that have already expired.","properties":{"buckets":{"type":"array","description":"Future expiration dates in ascending order, one entry per date on which at least one constituent expires. Constituents with no expiration date on record appear neither here nor in `expired`.","items":{"type":"object","properties":{"date":{"type":"string","description":"ISO date YYYY-MM-DD."},"count":{"type":"integer","description":"Number of constituent markets expiring on this date."},"total_weight":{"type":"number","description":"Combined index weight of the markets expiring on this date, as a fraction rather than a percent."}}}},"expired":{"type":"integer","description":"Number of constituents whose expiration has already passed. They are counted here only and are excluded from `buckets`."}}},"attribution":{"type":"array","description":"Per-leaf-market contribution to the index level (weight times price/100), with weight and price computed together server-side (the price is the mid that entered that cycle, not the latest trade; composite child levels anchor at the parent's resolved cycle): weights sum to ~1.0 and contributions reconcile to the published price's blended probability, partial composite baskets included. Falls back to stored base weights and current prices only for an index with no compute cycle yet.","items":{"type":"object","properties":{"market_id":{"type":"string","description":"Canonical market id (`<platform>:<raw_ticker>`) for the attributed constituent."},"ticker":{"type":"string","description":"Raw exchange ticker of the constituent market. Use `display_ticker` for a label and `market_id` for lookups or links."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"name":{"type":["string","null"],"description":"The constituent market's question text. Absent when the market has no question on record."},"contribution":{"type":"number","description":"The market's share of the index's blended probability, equal to `weight` multiplied by `price` divided by 100. Rows are ordered by descending absolute contribution and, across all rows, sum to the blended probability behind the published index level."},"weight":{"type":"number","description":"The market's effective weight in the index, as a fraction rather than a percent, after any sub-index legs are flattened. Weights across all rows sum to about 1.0."},"price":{"type":"number","description":"The market's probability, 0-100, as it entered the index calculation these figures reconcile to. Because it is the value that calculation consumed, it can lag the market's latest trade."}}}},"constituent_returns":{"type":"array","description":"Per-constituent own price move for the 1d/7d/30d trailing windows, precomputed server-side. Each row includes percent_change; each window includes group_by and groups.","items":{"type":"object","description":"Per-constituent price moves for one trailing window, computed server-side. A window whose start predates the index's earliest compute cycle comes back empty (rows: [], groups: []), degrading together with the null stats.trailing_returns for the same window.","properties":{"window":{"type":"string","description":"Window label: 1d / 7d / 30d."},"group_by":{"type":"string","description":"Dimension groups are keyed by. state means each group's key is a US state (or other for untagged rows). A city, party, or office grouping is a different group_by value, not a new field on the group.","enum":["state"]},"rows":{"type":"array","description":"One row per constituent held at the end of the window, ordered from largest to smallest end weight. Constituents that left the index before the window ended are omitted, and the array is empty when the index has no history reaching back to the window start.","items":{"type":"object","description":"One constituent's own price move over a trailing window. Every field is computed server-side and rendered verbatim.","properties":{"constituent_id":{"type":"string","description":"Prefixed constituent id (with kind): market_id for a market, index_id for a sub-index leg, rate_id for a rate sleeve, event_id for a same-event race."},"kind":{"type":"string","description":"Navigable kind: market (market page) / index (index page) / rate (rate page) / event (a same-event race, not individually linkable).","enum":["market","index","event","rate"]},"ticker":{"type":"string","description":"Display ticker for the constituent: the market's ticker (a readable slug where the venue provides one), the child index's ticker for a sub-index leg, the rate_id for a rate sleeve, or the race identifier for a same-event group."},"name":{"type":["string","null"],"description":"Readable name for the constituent: the market's question, the child index's name, the rate's name, or the event's name. Absent when the underlying record has none."},"platform":{"type":"string","description":"kalshi/polymarket for markets; index for a composite's sub-index leg; rate for a rate-backed sleeve."},"state_code":{"type":["string","null"],"description":"Two-letter state for House/Senate/Gov market constituents; absent for composite legs, same-event races, and markets with no state."},"weight":{"type":"number","description":"Effective (composite-flattened, normalized) weight at the window end."},"start_weight":{"type":"number","description":"Same weight at the window start, so a tile whose size changed over the window (a reweighting) is explainable (start_weight -> weight)."},"start_price":{"type":"number","description":"Constituent value at the start of the window (0-100 probability for markets; the child's UPFI value for a composite's sub-index leg; the rate mark for a rate sleeve)."},"end_price":{"type":"number","description":"Constituent value at the end of the window (same scale as start_price)."},"point_change":{"type":"number","description":"end_price minus start_price, in the constituent's own points."},"percent_change":{"type":["number","null"],"description":"Percent change from start_price to end_price: (end_price - start_price) / start_price * 100. Null when start_price is 0."}}}},"groups":{"type":"array","description":"Aggregates of rows under group_by, ordered from largest to smallest weight. Empty when rows is empty.","items":{"type":"object","description":"One grouped slice of constituent returns for a trailing window. The grouping dimension is the window's group_by; key identifies the group. Weight, point_change, and percent_change are computed server-side from the window's rows.","properties":{"key":{"type":"string","description":"Group id inside group_by. When group_by is state, this is a two-letter US state, or other for untagged rows."},"label":{"type":"string","description":"Display string when it differs from key. Omitted when key is already the label."},"weight":{"type":"number","description":"Sum of member end weights."},"member_count":{"type":"integer","description":"Count of members with end weight greater than 0."},"point_change":{"type":"number","description":"Weight-average of member point_change."},"percent_change":{"type":["number","null"],"description":"Weight-average of member percent_change over members whose percent_change is present. Null when no member has a usable start_price."}}}}}}}}}],"nullable":true},"halted":{"type":"boolean","description":"True when the latest index value was carried forward because the index fell below its constituent floor."},"halt_valid_constituents":{"type":["integer","null"],"description":"When halted, the valid (priced, guardrail-passing) constituents at the most recent halt cycle. Omitted when not halted."},"halt_min_constituents":{"type":["integer","null"],"description":"When halted, the category constituent floor the index fell below. Omitted when not halted."},"halt_reason":{"type":["string","null"],"description":"When halted, a human-readable explanation of the halt, composed from the constituent halt counts. Omitted when not halted."},"visibility":{"type":"string","description":"Access level of the index. `public` is visible to everyone; `organization` is visible to members of listed organizations. Other reserved values may appear on authenticated responses. Omitted on the anonymous public tier, which returns only public indices.","enum":["public","superuser","organization"]},"official_daily_value":{"description":"Most recent official daily value. Null when this index family does not publish daily values.","allOf":[{"type":"object","description":"One official daily value: the value stamped for one US-Eastern calendar day.","required":["et_date","value"],"properties":{"et_date":{"type":"string","format":"date","description":"The US-Eastern calendar day the value is official for."},"value":{"type":"number","description":"The official index value for that day, in index points."}}}],"nullable":true},"sleeves":{"type":"array","description":"Current sleeve state for an NFL team index. Empty for other index families.","items":{"type":"object","description":"One sleeve of an NFL team index: a fixed seat holding at most one market at a time.","required":["sleeve","active","cumulative_points"],"properties":{"sleeve":{"type":"string","description":"Stable sleeve name.","enum":["super_bowl","conference","division","next_game"]},"active":{"type":"boolean","description":"Whether the sleeve holds an active member. An inactive sleeve keeps its seat and contributes nothing until a successor is admitted."},"market_id":{"type":["string","null"],"description":"The current member's market id. Omitted for an inactive sleeve."},"display_ticker":{"type":["string","null"],"description":"Display label for the current member. Omitted for an inactive sleeve."},"name":{"type":["string","null"],"description":"The current member's question. Omitted for an inactive sleeve."},"mark_price":{"type":["number","null"],"description":"The sleeve's latest approved mark, 0-100. Omitted for an inactive sleeve or before the sleeve's first computed mark."},"cumulative_points":{"type":"number","description":"The sleeve's cumulative contribution to the index level since base, in index points."}}}}}},"example":{"index_id":"red","name":"Republican Political Future Index","ticker":"RED","description":"Composite of Republican party-line contests across all levels of office in the United States","constituents_count":5,"latest_price":91.3069,"price_change_1d":0.2663,"price_change_7d":-0.3112,"halted":false},"examples":[{"name":"default","value":{"index_id":"red","name":"Republican Political Future Index","ticker":"RED","description":"Composite of Republican party-line contests across all levels of office in the United States","constituents_count":5,"latest_price":91.3069,"price_change_1d":0.2663,"price_change_7d":-0.3112,"halted":false}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Index not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Index not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Index not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get index constituents
url: "https://docs.adjacent.markets/api/get-api-v1-indices-id-constituents.md"
description: Get constituent markets with weights and prices
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/indices/<id>/constituents" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "kind": "index",
          "market_id": "presr_kalshi",
          "ticker": "presr_kalshi",
          "display_ticker": "presr_kalshi",
          "platform": "index",
          "weight": 0.4,
          "price": 91.5,
          "name": "Presidential (R)"
        },
        {
          "kind": "index",
          "market_id": "senater_kalshi",
          "ticker": "senater_kalshi",
          "display_ticker": "senater_kalshi",
          "platform": "index",
          "weight": 0.3,
          "price": 99.0654,
          "name": "Senate (R)"
        }
      ],
      "meta": {
        "total": 5,
        "page": 1,
        "per_page": 500,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Index not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/indices/{id}/constituents","summary":"Get index constituents","description":"Get constituent markets with weights and prices","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g.","schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","description":"Rows per page (max 500).","schema":{"type":"integer","default":500,"minimum":1,"maximum":500}},{"name":"expand","in":"query","description":"`markets` flattens a composite index into its leaf markets server-side, each returned once with its effective weight (product of the BASE parent×child weights along the path; sums to ~1.0 for a full composite basket, under 1.0 for a partial basket whose methodology categories are not all linked).","schema":{"type":"string"}},{"name":"flatten","in":"query","description":"Boolean alias for `expand=markets`.","schema":{"type":"boolean","default":false}},{"name":"search","in":"query","description":"Case-insensitive substring match over ticker and name, applied server-side.","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Paginated constituents","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","required":["kind","market_id","ticker","display_ticker","platform","weight"],"properties":{"kind":{"type":"string","description":"Discriminator: 'market' for leaf prediction markets, 'index' for composite sub-indices.","enum":["market","index"]},"market_id":{"type":"string","description":"Canonical id. For markets: `<platform>:<raw_ticker>`. For composites: the child index_id."},"ticker":{"type":"string","description":"For markets: raw exchange ticker. For composites: the child index_id."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"'kalshi'/'polymarket' for markets; 'index' for composite components."},"weight":{"type":"number","description":"This constituent's share of the index, as a fraction of 1 (0.18 means 18 percent). These are the index's stored base weights, which sum to 1 across the full constituent list; a given published price point can differ, because the calculation renormalizes over only the constituents that had a usable price that cycle."},"price":{"type":["number","null"],"description":"Latest value for the constituent: for market constituents, the most recent yes-side traded price on the 0-100 cents scale; for sub-index constituents (`kind` = `index`), the child index's latest published level, which is in index points and not on the 0-100 scale. Null when the constituent has never traded or has no published value yet, and it carries no age bound, so an inactive market's price can be hours old."},"name":{"type":["string","null"],"description":"Display label for the constituent: the market's question for market rows, and the sub-index's name for `kind` = `index` rows."},"volume":{"type":["number","null"],"description":"All-time traded volume as a contract/share count (Kalshi contracts, Polymarket shares), not dollars. Present for kind='market' rows only. Unit is in `volume_unit`."},"volume_unit":{"description":"Wire unit for `volume`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"open_interest":{"type":["number","null"],"description":"Open interest: a Kalshi contract count; Polymarket's is USD. Present for kind='market' rows only. Unit is in `open_interest_unit`."},"open_interest_unit":{"description":"Wire unit for `open_interest`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"end_date":{"type":["string","null"],"format":"date-time","description":"When trading closes for a market constituent. Always null for sub-index constituents (`kind` = `index`), which do not expire."},"state_code":{"type":["string","null"],"description":"Two-letter state code (House/Senate/Gubernatorial); market rows only"},"city_code":{"type":["string","null"],"description":"City code (Mayoral); market rows only"}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"kind":"index","market_id":"presr_kalshi","ticker":"presr_kalshi","display_ticker":"presr_kalshi","platform":"index","weight":0.4,"price":91.5,"name":"Presidential (R)"},{"kind":"index","market_id":"senater_kalshi","ticker":"senater_kalshi","display_ticker":"senater_kalshi","platform":"index","weight":0.3,"price":99.0654,"name":"Senate (R)"}],"meta":{"total":5,"page":1,"per_page":500,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"kind":"index","market_id":"presr_kalshi","ticker":"presr_kalshi","display_ticker":"presr_kalshi","platform":"index","weight":0.4,"price":91.5,"name":"Presidential (R)"},{"kind":"index","market_id":"senater_kalshi","ticker":"senater_kalshi","display_ticker":"senater_kalshi","platform":"index","weight":0.3,"price":99.0654,"name":"Senate (R)"}],"meta":{"total":5,"page":1,"per_page":500,"total_pages":1,"has_next":false,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Index not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Index not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Index not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Find related news
url: "https://docs.adjacent.markets/api/get-api-v1-indices-id-news.md"
description: "Related news drawn from the index's constituent markets, ranked by closest market match (viamarketid, viamarketquestion) and relevance blended with recency."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/indices/<id>/news" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "article_id": "a1b2c3d4",
          "similarity": 0.84,
          "title": "Senate race tightens in Pennsylvania",
          "url": "https://example.com/news/senate-pa",
          "published_date": "2026-06-01T08:00:00Z",
          "source": "Reuters"
        },
        {
          "article_id": "e5f6g7h8",
          "similarity": 0.79,
          "title": "New polling shifts House outlook",
          "url": "https://example.com/news/house-outlook",
          "published_date": "2026-06-01T07:30:00Z",
          "source": "AP"
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 20,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/indices/{id}/news","summary":"Find related news","description":"Related news drawn from the index's constituent markets, ranked by closest market match (via_market_id, via_market_question) and relevance blended with recency.","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID","schema":{"type":"string"}},{"name":"min_similarity","in":"query","description":"Minimum cosine similarity a result must reach.","schema":{"type":"number","default":0.38,"minimum":0,"maximum":1}},{"name":"recency_half_life_days","in":"query","description":"Recency half-life in days for the relevance-recency blend applied to the ranking: a result's score is its similarity times 0.5^(age_days / this).","schema":{"type":"number","minimum":0}},{"name":"page","in":"query","description":"Page number","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","description":"Items per page","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":[{"status":"200","description":"Paginated related news articles","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","required":["article_id","similarity"],"properties":{"article_id":{"type":"string"},"similarity":{"type":"number","format":"double","description":"Cosine similarity of the best embedding match."},"title":{"type":["string","null"]},"url":{"type":["string","null"]},"image_url":{"type":["string","null"]},"published_date":{"type":["string","null"],"format":"date-time"},"source":{"type":["string","null"],"description":"Where the article was published: the publisher's name when known, otherwise the site's hostname."},"via_market_id":{"type":["string","null"],"description":"The market this article matched most closely. Present on index news (the winning constituent market, including a constituent rate's source market) and on rate news when a source market beat the rate itself."},"via_market_question":{"type":["string","null"],"description":"The question text of that market."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"article_id":"a1b2c3d4","similarity":0.84,"title":"Senate race tightens in Pennsylvania","url":"https://example.com/news/senate-pa","published_date":"2026-06-01T08:00:00Z","source":"Reuters"},{"article_id":"e5f6g7h8","similarity":0.79,"title":"New polling shifts House outlook","url":"https://example.com/news/house-outlook","published_date":"2026-06-01T07:30:00Z","source":"AP"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"article_id":"a1b2c3d4","similarity":0.84,"title":"Senate race tightens in Pennsylvania","url":"https://example.com/news/senate-pa","published_date":"2026-06-01T08:00:00Z","source":"Reuters"},{"article_id":"e5f6g7h8","similarity":0.79,"title":"New polling shifts House outlook","url":"https://example.com/news/house-outlook","published_date":"2026-06-01T07:30:00Z","source":"AP"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}}}]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get index price history
url: "https://docs.adjacent.markets/api/get-api-v1-indices-id-prices.md"
description: Get historical index values
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/indices/<id>/prices" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "timestamp": "2026-06-20T19:00:00Z",
          "price": 91.2892
        },
        {
          "timestamp": "2026-06-20T18:55:00Z",
          "price": 91.2703
        }
      ],
      "meta": {
        "total": 7398,
        "page": 1,
        "per_page": 100,
        "total_pages": 74,
        "has_next": true,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/indices/{id}/prices","summary":"Get index price history","description":"Get historical index values","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g.","schema":{"type":"string"}},{"name":"per_page","in":"query","description":"Points per page (1-1000).","schema":{"type":"integer","default":100,"minimum":1,"maximum":1000}},{"name":"start","in":"query","description":"Start time","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","description":"End time","schema":{"type":"string","format":"date-time"}},{"name":"interval","in":"query","description":"Time bucket interval (daily, 1day also accepted as aliases for 1d)","schema":{"type":"string","enum":["1min","5min","1hour","1d"],"default":"5min"}},{"name":"order","in":"query","description":"Sort direction by timestamp","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","default":1,"minimum":1}}],"responses":[{"status":"200","description":"Price history for the requested window, newest first unless `order=asc`.","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"Start of the aggregation bucket this point covers, in UTC. Daily buckets are anchored to midnight US Eastern, so a `1d` point's timestamp is 04:00 or 05:00 UTC depending on daylight saving."},"price":{"type":"number","description":"Value of the series for this bucket: the last price recorded within it. Equals `ohlc.close` on the same point where OHLC is returned, and is the same statistic the `previous_close_*` baselines are measured against. The scale is 0-100 for market and rate series, and the index level (roughly 50-150) for index series."},"price_raw":{"type":["number","null"],"description":"Not currently reachable on any tier, and always absent. The unsmoothed value exists only on the un-bucketed series, but every accepted interval (and the default) maps to a bucketed one, so no request can return it."},"volume":{"type":["number","null"],"description":"Not currently populated on any price series, on any tier, and always absent. Reserved: use the market volume fields for traded volume."},"ohlc":{"description":"Open, high, low and close for the bucket, on the same 0-100 scale as `price`. Returned on the market and rate price series only (index series omit it), and on a daily series a gap-filled day repeats the previous day's values rather than reporting new trading.","allOf":[{"type":"object","required":["open","high","low","close"],"properties":{"open":{"type":"number","description":"Price of the first trade in the bucket, in cents (0-100)."},"high":{"type":"number","description":"Highest traded price in the bucket, in cents (0-100)."},"low":{"type":"number","description":"Lowest traded price in the bucket, in cents (0-100)."},"close":{"type":"number","description":"Price of the last trade in the bucket, in cents (0-100). The same value the point's `price` field carries."}}}],"nullable":true},"spread":{"type":["number","null"],"description":"Dispersion across the source markets behind a reference-rate value: the highest source price minus the lowest, in the same 0-100 points as `price`. Meaningful only on rate series, and currently not populated on any price-series response, so it is always absent."},"sources":{"type":["object","null"],"description":"Provenance for a reference-rate value: the blending method used, plus the per-source prices and weights behind it. Currently not populated on any price-series response, so it is always absent; use `constituents` for the per-source breakdown.","additionalProperties":true},"constituents":{"type":["array","null"],"description":"The source markets behind a reference-rate value at this timestamp, each with its probability (0-100) and its weight renormalized to sum to 1 across the markets listed. Returned on the authenticated rate price series only, covering markets that were active at the timestamp and traded in that bucket; pass `sources=false` to omit it.","items":{"type":"object","properties":{"market_id":{"type":"string"},"price":{"type":"number"},"weight":{"type":"number"}}}}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"timestamp":"2026-06-20T19:00:00Z","price":91.2892},{"timestamp":"2026-06-20T18:55:00Z","price":91.2703}],"meta":{"total":7398,"page":1,"per_page":100,"total_pages":74,"has_next":true,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"timestamp":"2026-06-20T19:00:00Z","price":91.2892},{"timestamp":"2026-06-20T18:55:00Z","price":91.2703}],"meta":{"total":7398,"page":1,"per_page":100,"total_pages":74,"has_next":true,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get official daily values
url: "https://docs.adjacent.markets/api/get-api-v1-indices-id-daily-values.md"
description: "Official daily values for an index whose family publishes one, newest first. The NFL team indices stamp one official value per US-Eastern calendar day, taken from a fixed morning window; days without "
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/indices/<id>/daily-values" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/indices/{id}/daily-values","summary":"Get official daily values","description":"Official daily values for an index whose family publishes one, newest first. The NFL team indices stamp one official value per US-Eastern calendar day, taken from a fixed morning window; days without a stamped value have no row, and official values begin accruing when the index goes live. Indices without a daily-value rule return an empty list. Returns the `{data, meta}` envelope. Not paginated: `meta.total` counts the rows in this response and `has_next` is always false.","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g. `seatr_kalshi` or `SEATR`.","schema":{"type":"string"}},{"name":"from","in":"query","required":false,"description":"Inclusive lower bound on the US-Eastern calendar day (YYYY-MM-DD).","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"description":"Inclusive upper bound on the US-Eastern calendar day (YYYY-MM-DD).","schema":{"type":"string","format":"date"}},{"name":"per_page","in":"query","required":false,"description":"Rows returned in this response (1-366), newest first.","schema":{"type":"integer","default":90,"minimum":1,"maximum":366}}],"responses":[{"status":"200","description":"Rows, newest first","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","description":"One official daily value: the value stamped for one US-Eastern calendar day.","required":["et_date","value"],"properties":{"et_date":{"type":"string","format":"date","description":"The US-Eastern calendar day the value is official for."},"value":{"type":"number","description":"The official index value for that day, in index points."}}}},"meta":{"allOf":[{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}]}}},"examples":[]},{"status":"400","description":"The `from` date is after the `to` date.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]},{"status":"404","description":"Index not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get membership events
url: "https://docs.adjacent.markets/api/get-api-v1-indices-id-membership-events.md"
description: "Recent membership events for an NFL team index, newest first: admissions (a market became its sleeve's active member) and settlements (a member's market resolved and its final value was booked). Indic"
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/indices/<id>/membership-events" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/indices/{id}/membership-events","summary":"Get membership events","description":"Recent membership events for an NFL team index, newest first: admissions (a market became its sleeve's active member) and settlements (a member's market resolved and its final value was booked). Indices without sleeve membership return an empty list. Returns the `{data, meta}` envelope. Not paginated: `meta.total` counts the rows in this response and `has_next` is always false.","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g. `seatr_kalshi` or `SEATR`.","schema":{"type":"string"}},{"name":"per_page","in":"query","required":false,"description":"Rows returned in this response (1-100), newest first.","schema":{"type":"integer","default":20,"minimum":1,"maximum":100}}],"responses":[{"status":"200","description":"Rows, newest first","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","description":"One membership event of an NFL team index: an admission (a market became its sleeve's active member) or a settlement (a member's market resolved and its final value was booked).","required":["kind","occurred_at","market_id","display_ticker"],"properties":{"kind":{"type":"string","description":"The event type.","enum":["admission","settlement"]},"occurred_at":{"type":"string","format":"date-time","description":"When the event took effect."},"sleeve":{"type":["string","null"],"description":"The sleeve the event belongs to, when resolvable."},"market_id":{"type":"string","description":"The market the event is about."},"display_ticker":{"type":"string","description":"Display label for the market."},"name":{"type":["string","null"],"description":"The market's question. Omitted when the market is unknown."},"settled_price":{"type":["number","null"],"description":"For a settlement, the booked final value (0 or 100). Omitted for admissions."}}}},"meta":{"allOf":[{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}]}}},"examples":[]},{"status":"400","description":"The `from` date is after the `to` date.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]},{"status":"404","description":"Index not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List markets
url: "https://docs.adjacent.markets/api/get-api-v1-markets.md"
description: Get a paginated list of prediction markets with filtering options.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/markets" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "market_id": "kalshi:KXNBA-26-SAS",
          "ticker": "KXNBA-26-SAS",
          "display_ticker": "KXNBA-26-SAS",
          "platform": "kalshi",
          "question": "Will the San Antonio win the 2026 Pro Basketball Finals?",
          "link": "https://kalshi.com/markets/kxnba/kxnba-26",
          "probability": 65,
          "volume": 44526290,
          "volume_24h": 1157100.4,
          "open_interest": 21229516,
          "status": "active",
          "category": "Sports",
          "is_constituent": false,
          "end_date": "2028-06-29T14:00:00Z",
          "created_at": "2026-06-03T14:46:46.966195Z",
          "updated_at": "2026-06-03T14:46:46.966195Z"
        },
        {
          "market_id": "kalshi:KXNBA-26-NYK",
          "ticker": "KXNBA-26-NYK",
          "display_ticker": "KXNBA-26-NYK",
          "platform": "kalshi",
          "question": "Will the New York win the 2026 Pro Basketball Finals?",
          "link": "https://kalshi.com/markets/kxnba/kxnba-26",
          "probability": 37,
          "volume": 42456692,
          "volume_24h": 1904408,
          "open_interest": 24467278,
          "status": "active",
          "category": "Sports",
          "is_constituent": false,
          "end_date": "2028-06-29T14:00:00Z",
          "created_at": "2026-06-03T14:41:36.373567Z",
          "updated_at": "2026-06-03T14:41:36.373567Z"
        }
      ],
      "meta": {
        "total": 87749,
        "page": 1,
        "per_page": 20,
        "total_pages": 4388,
        "has_next": true,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/markets","summary":"List markets","description":"Get a paginated list of prediction markets with filtering options.","parameters":[{"name":"platform","in":"query","description":"Filter by platform (kalshi, polymarket)","schema":{"type":"string"}},{"name":"category","in":"query","description":"Filter by category","schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by exact market status.","schema":{"type":"string"}},{"name":"state_code","in":"query","description":"Filter by assigned US state abbreviation (case-insensitive)","schema":{"type":"string"}},{"name":"search","in":"query","description":"Case-insensitive word match over the market's question, description, series title, market ID (e.g. kalshi:KXPRESPARTY-2028-R), and market slug (e.g. mlb-atl-nym-2026-07-29-nrfi).","schema":{"type":"string"}},{"name":"tag","in":"query","description":"Case-sensitive substring match against the market's raw metadata document (not a discrete tag field), so short values match broadly.","schema":{"type":"string"}},{"name":"start","in":"query","description":"Filter by creation date (after)","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","description":"Filter by creation date (before)","schema":{"type":"string","format":"date-time"}},{"name":"end_date_after","in":"query","description":"Filter markets ending after this date","schema":{"type":"string","format":"date-time"}},{"name":"end_date_before","in":"query","description":"Filter markets ending before this date","schema":{"type":"string","format":"date-time"}},{"name":"probability_min","in":"query","description":"Minimum probability (0-100)","schema":{"type":"number"}},{"name":"probability_max","in":"query","description":"Maximum probability (0-100)","schema":{"type":"number"}},{"name":"volume_min","in":"query","description":"Minimum volume","schema":{"type":"number"}},{"name":"volume_max","in":"query","description":"Maximum volume","schema":{"type":"number"}},{"name":"include_closed","in":"query","description":"Include closed markets","schema":{"type":"boolean","default":false}},{"name":"include_resolved","in":"query","description":"Include resolved markets","schema":{"type":"boolean","default":false}},{"name":"sort","in":"query","description":"Sort key.","schema":{"type":"string","enum":["volume","ticker","price","open_interest","expiration"],"default":"volume"}},{"name":"sort_dir","in":"query","description":"Sort direction","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"page","in":"query","description":"Page number","schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","description":"Items per page","schema":{"type":"integer","default":100,"maximum":500}}],"responses":[{"status":"200","description":"List of markets","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"market_id":{"type":"string","description":"Canonical identifier for the market, formed as `<platform>:<venue ticker>` (for example `kalshi:SENATEPA-26-R`). This is the id every other endpoint accepts, so use it rather than `ticker` when looking a market up."},"ticker":{"type":"string","description":"The venue's own symbol for the market, without the `<platform>:` prefix. Not guaranteed unique across venues, so use `market_id` as the lookup key and `display_ticker` as the human-readable label."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"The venue that lists this market: `kalshi` or `polymarket`. It is also the prefix of `market_id`, and it determines what the volume and open interest figures are counted in (see the companion `volume_unit`, `volume_24h_unit`, and `open_interest_unit` fields)."},"question":{"type":"string","description":"The market's question, worded as the venue words it. When a venue supplies no title we fall back to the raw ticker, so this is never empty."},"probability":{"type":["number","null"],"description":"Implied yes-side probability on the 0-100 scale, where 48.5 means 48.5 percent. This is the market's latest traded price."},"volume":{"type":["number","null"],"description":"All-time traded volume as a contract/share count (Kalshi contracts, Polymarket shares), not dollars. Unit is in `volume_unit`."},"volume_unit":{"description":"Wire unit for `volume`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"volume_24h":{"type":["number","null"],"description":"Trailing 24h volume. Platform-native: Kalshi contracts, Polymarket USD. Unit is in `volume_24h_unit`."},"volume_24h_unit":{"description":"Wire unit for `volume_24h`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"open_interest":{"type":["number","null"],"description":"Open interest: a Kalshi contract count; Polymarket's is USD. Unit is in `open_interest_unit`."},"open_interest_unit":{"description":"Wire unit for `open_interest`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"status":{"type":"string","description":"Lifecycle state of the market: `active` (trading), `closed` (trading has ended, outcome not yet published), `resolved` (settled with a known outcome), `expired` (ended long ago and never settled by the venue), or `unknown` (the venue reported no status we recognize)."},"category":{"type":["string","null"],"description":"Topic category of this market's parent event, normalized across venues (for example `Politics`, `Sports`, `Crypto`). Every market under the same event shares it."},"is_constituent":{"type":"boolean","description":"True when the market is a constituent of at least one index. The public markets list exposes every tracked market; default to constituents by filtering on this flag."},"indices":{"type":"array","description":"Index ids this market is a constituent of, ascending. Omitted when the market is in no index. Populated only on the authenticated /api/v1/markets list.","items":{"type":"string"}},"end_date":{"type":["string","null"],"format":"date-time","description":"When trading closes on the venue. This is not the settlement time; a market can sit in `closed` for a while before its outcome is published."},"created_at":{"type":"string","format":"date-time","description":"When we first recorded this market, not when the venue listed it. Only the authenticated markets list returns it; the public markets list omits it."},"updated_at":{"type":"string","format":"date-time","description":"When any stored field on this market last changed on our side, so it also moves on routine metadata refreshes and is not a price-move timestamp. Only the authenticated markets list returns it; the public markets list omits it."},"link":{"type":["string","null"],"description":"URL of the venue's public page for this contract, which on both venues is the parent event page rather than a single strike. Null when no working URL can be built, which happens for Kalshi markets whose series is unknown."},"state_code":{"type":["string","null"],"description":"Two-letter US state code when the contract is tied to a state race. Absent for national contests and for markets with no state on record."},"city_code":{"type":["string","null"],"description":"Mayoral city code parsed at ingest; present for Mayoral markets, absent otherwise."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"market_id":"kalshi:KXNBA-26-SAS","ticker":"KXNBA-26-SAS","display_ticker":"KXNBA-26-SAS","platform":"kalshi","question":"Will the San Antonio win the 2026 Pro Basketball Finals?","link":"https://kalshi.com/markets/kxnba/kxnba-26","probability":65,"volume":44526290,"volume_24h":1157100.4,"open_interest":21229516,"status":"active","category":"Sports","is_constituent":false,"end_date":"2028-06-29T14:00:00Z","created_at":"2026-06-03T14:46:46.966195Z","updated_at":"2026-06-03T14:46:46.966195Z"},{"market_id":"kalshi:KXNBA-26-NYK","ticker":"KXNBA-26-NYK","display_ticker":"KXNBA-26-NYK","platform":"kalshi","question":"Will the New York win the 2026 Pro Basketball Finals?","link":"https://kalshi.com/markets/kxnba/kxnba-26","probability":37,"volume":42456692,"volume_24h":1904408,"open_interest":24467278,"status":"active","category":"Sports","is_constituent":false,"end_date":"2028-06-29T14:00:00Z","created_at":"2026-06-03T14:41:36.373567Z","updated_at":"2026-06-03T14:41:36.373567Z"}],"meta":{"total":87749,"page":1,"per_page":20,"total_pages":4388,"has_next":true,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"market_id":"kalshi:KXNBA-26-SAS","ticker":"KXNBA-26-SAS","display_ticker":"KXNBA-26-SAS","platform":"kalshi","question":"Will the San Antonio win the 2026 Pro Basketball Finals?","link":"https://kalshi.com/markets/kxnba/kxnba-26","probability":65,"volume":44526290,"volume_24h":1157100.4,"open_interest":21229516,"status":"active","category":"Sports","is_constituent":false,"end_date":"2028-06-29T14:00:00Z","created_at":"2026-06-03T14:46:46.966195Z","updated_at":"2026-06-03T14:46:46.966195Z"},{"market_id":"kalshi:KXNBA-26-NYK","ticker":"KXNBA-26-NYK","display_ticker":"KXNBA-26-NYK","platform":"kalshi","question":"Will the New York win the 2026 Pro Basketball Finals?","link":"https://kalshi.com/markets/kxnba/kxnba-26","probability":37,"volume":42456692,"volume_24h":1904408,"open_interest":24467278,"status":"active","category":"Sports","is_constituent":false,"end_date":"2028-06-29T14:00:00Z","created_at":"2026-06-03T14:41:36.373567Z","updated_at":"2026-06-03T14:41:36.373567Z"}],"meta":{"total":87749,"page":1,"per_page":20,"total_pages":4388,"has_next":true,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get market details
url: "https://docs.adjacent.markets/api/get-api-v1-markets-id.md"
description: Get detailed information about a specific market
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/markets/<id>" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "market_id": "kalshi:KXNBA-26-SAS",
      "ticker": "KXNBA-26-SAS",
      "display_ticker": "KXNBA-26-SAS",
      "platform": "kalshi",
      "question": "Will the San Antonio win the 2026 Pro Basketball Finals?",
      "probability": 65,
      "volume": 44526290,
      "volume_24h": 1157100.4,
      "open_interest": 21229516,
      "status": "active",
      "open_time": "2025-07-12T14:00:00Z",
      "end_date": "2028-06-29T14:00:00Z",
      "expiration_date": "2026-06-30T14:00:00Z",
      "link": "https://kalshi.com/markets/kxnba/kxnba-26",
      "category": "Sports",
      "market_type": "binary",
      "rules_primary": "If San Antonio win the 2026 Pro Basketball Finals, then the market resolves to Yes.",
      "rules_secondary": "",
      "yes_sub_title": "San Antonio",
      "no_sub_title": "San Antonio"
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Market not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/markets/{id}","summary":"Get market details","description":"Get detailed information about a specific market","parameters":[{"name":"id","in":"path","required":true,"description":"Market ID","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Market details","schema":{"type":"object","description":"A single market with full detail. Both the authenticated and public market-detail routes return this exact shape.","required":["market_id","ticker","display_ticker","platform"],"properties":{"market_id":{"type":"string","description":"Canonical identifier for the market, formed as `<platform>:<venue ticker>` (for example `kalshi:SENATEPA-26-R`). This is the id every other endpoint accepts, so use it rather than `ticker` when looking a market up."},"ticker":{"type":"string","description":"The venue's own symbol for the market, without the `<platform>:` prefix. Not guaranteed unique across venues, so use `market_id` as the lookup key and `display_ticker` as the human-readable label."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"The venue that lists this market: `kalshi` or `polymarket`. It is also the prefix of `market_id`, and it determines what the volume and open interest figures are counted in (see the companion `volume_unit`, `volume_24h_unit`, and `open_interest_unit` fields)."},"question":{"type":["string","null"],"description":"The market's question, worded as the venue words it. When a venue supplies no title we fall back to the raw ticker, so this is never empty."},"description":{"type":["string","null"],"description":"Longer explanatory text for the contract as supplied by the venue (Kalshi's subtitle, Polymarket's description). Frequently absent, especially on Kalshi."},"probability":{"type":["number","null"],"description":"Implied yes-side probability on the 0-100 scale, where 48.5 means 48.5 percent. For a live market this is the latest traded price. For a resolved market with a known yes/no outcome it is the settlement value (100 or 0) rather than the last traded price."},"volume":{"type":["number","null"],"description":"All-time traded volume as a contract/share count (Kalshi contracts, Polymarket shares), not dollars. Unit is in `volume_unit`."},"volume_unit":{"description":"Wire unit for `volume`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"volume_24h":{"type":["number","null"],"description":"Trailing 24h volume. Platform-native: Kalshi contracts, Polymarket USD. Unit is in `volume_24h_unit`."},"volume_24h_unit":{"description":"Wire unit for `volume_24h`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"open_interest":{"type":["number","null"],"description":"Open interest: a Kalshi contract count; Polymarket's is USD. Unit is in `open_interest_unit`."},"open_interest_unit":{"description":"Wire unit for `open_interest`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"yes_bid":{"type":["number","null"],"description":"Latest top-of-book YES bid (0-100 cents, ~1-min fresh)."},"yes_ask":{"type":["number","null"],"description":"Latest top-of-book YES ask (0-100 cents, ~1-min fresh)."},"no_bid":{"type":["number","null"],"description":"Derived NO bid (100 - yes_ask)."},"no_ask":{"type":["number","null"],"description":"Derived NO ask (100 - yes_bid)."},"event_ticker":{"type":["string","null"],"description":"Raw venue event ticker (unprefixed)."},"status":{"type":["string","null"],"description":"Lifecycle state of the market: `active` (trading), `closed` (trading has ended, outcome not yet published), `resolved` (settled with a known outcome), `expired` (ended long ago and never settled by the venue), or `unknown` (the venue reported no status we recognize)."},"open_time":{"type":["string","null"],"format":"date-time","description":"When the market opened for trading on the venue. Static once set, and absent for venues that do not report an open time."},"end_date":{"type":["string","null"],"format":"date-time","description":"When trading closes on the venue. This is not the settlement time; a market can sit in `closed` for a while before it resolves, so see `expiration_date` for the expected settlement."},"expiration_date":{"type":["string","null"],"format":"date-time","description":"Expected settlement time as published by the venue. Distinct from `end_date`, which is when trading closes; a market sits between the two while awaiting its outcome."},"link":{"type":["string","null"],"description":"URL of the venue's public page for this contract, which on both venues is the parent event page rather than a single strike. Null when no working URL can be built, which happens for Kalshi markets whose series is unknown."},"category":{"type":["string","null"],"description":"Topic category of this market's parent event, normalized across venues (for example `Politics`, `Sports`, `Crypto`). Every market under the same event shares it."},"state_code":{"type":["string","null"],"description":"Two-letter US state code parsed from the ticker when the contract is tied to a state (Senate, Governor, House). Absent for contracts with no state, including Mayoral markets, which carry `city_code` instead."},"city_code":{"type":["string","null"],"description":"Mayoral city code parsed at ingest; present for Mayoral markets, absent otherwise."},"market_type":{"type":["string","null"],"description":"The venue's own contract-type label (for example a binary or scalar market). Static contract metadata, absent when the venue reports none."},"rules_primary":{"type":["string","null"],"description":"The venue's primary settlement rules text, describing what resolves the contract YES."},"rules_secondary":{"type":["string","null"],"description":"Additional settlement rules text from the venue, covering edge cases and sourcing. Frequently absent."},"yes_sub_title":{"type":["string","null"],"description":"Short label for the YES leg as the venue words it, suitable for a button or leg header."},"no_sub_title":{"type":["string","null"],"description":"Short label for the NO leg as the venue words it, suitable for a button or leg header."},"settlement":{"type":["object","null"],"description":"Resolution provenance, platform-agnostic (Kalshi series object / Polymarket resolution_source).","properties":{"sources":{"type":"array","items":{"type":"object","properties":{"name":{"type":["string","null"]},"url":{"type":["string","null"]}}}},"terms_url":{"type":["string","null"]}}},"result":{"type":["string","null"],"description":"Resolution outcome reported by the venue: `yes` or `no`. Absent while the market is open, and for markets that settle to a scalar value or without a per-market yes/no outcome. When set, `probability` is the settlement value (100 or 0)."},"stats":{"description":"Trailing returns and risk statistics computed from the market's daily trade-price series over roughly the trailing 400 days. The values are null individually when the series is too short for that window.","allOf":[{"type":"object","properties":{"trailing_returns":{"type":"array","description":"Percent price change over each of six fixed trailing windows: 1D, 1W, 1M, 3M, YTD, and 1Y.","items":{"type":"object","required":["label"],"properties":{"label":{"type":"string","description":"The trailing window this return covers: `1D`, `1W`, `1M`, `3M`, `YTD`, or `1Y`."},"value":{"type":["number","null"],"description":"Percent change from the value at the start of the window to the latest value in the series. Null when the series has no data point close enough to the start of that window."},"point_change":{"type":["number","null"],"description":"Absolute change in the level's own units over the same window. Point-quoted indices (quote_convention `points`) express trailing performance with this figure; omitted when no comparable historical point exists."}}}},"risk":{"type":"object","description":"Volatility, range, and period return computed over the most recent 31 points of the daily series. The window counts data points, so a series with gaps spans more than 31 calendar days.","properties":{"volatility":{"type":["number","null"],"description":"Annualized volatility in percent, from the daily returns across the most recent 31 daily data points, annualized over 365 days because these markets trade every calendar day. Null when the daily series has fewer than 3 points."},"daily_vol":{"type":["number","null"],"description":"Standard deviation of the daily returns across the most recent 31 daily data points, in percent and not annualized. Null when the daily series has fewer than 3 points."},"range_high":{"type":["number","null"],"description":"Highest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"range_low":{"type":["number","null"],"description":"Lowest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"return_pct":{"type":["number","null"],"description":"Percent change from the first to the last of the most recent 31 daily data points. Null when the daily series has fewer than 3 points."}}}}}],"nullable":true}}},"example":{"market_id":"kalshi:KXNBA-26-SAS","ticker":"KXNBA-26-SAS","display_ticker":"KXNBA-26-SAS","platform":"kalshi","question":"Will the San Antonio win the 2026 Pro Basketball Finals?","probability":65,"volume":44526290,"volume_24h":1157100.4,"open_interest":21229516,"status":"active","open_time":"2025-07-12T14:00:00Z","end_date":"2028-06-29T14:00:00Z","expiration_date":"2026-06-30T14:00:00Z","link":"https://kalshi.com/markets/kxnba/kxnba-26","category":"Sports","market_type":"binary","rules_primary":"If San Antonio win the 2026 Pro Basketball Finals, then the market resolves to Yes.","rules_secondary":"","yes_sub_title":"San Antonio","no_sub_title":"San Antonio"},"examples":[{"name":"default","value":{"market_id":"kalshi:KXNBA-26-SAS","ticker":"KXNBA-26-SAS","display_ticker":"KXNBA-26-SAS","platform":"kalshi","question":"Will the San Antonio win the 2026 Pro Basketball Finals?","probability":65,"volume":44526290,"volume_24h":1157100.4,"open_interest":21229516,"status":"active","open_time":"2025-07-12T14:00:00Z","end_date":"2028-06-29T14:00:00Z","expiration_date":"2026-06-30T14:00:00Z","link":"https://kalshi.com/markets/kxnba/kxnba-26","category":"Sports","market_type":"binary","rules_primary":"If San Antonio win the 2026 Pro Basketball Finals, then the market resolves to Yes.","rules_secondary":"","yes_sub_title":"San Antonio","no_sub_title":"San Antonio"}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Market not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Market not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Market not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get market candles
url: "https://docs.adjacent.markets/api/get-api-v1-markets-id-candles.md"
description: "Get OHLC candles for a market, optionally scoped to a source bucket window."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/markets/<id>/candles" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "timestamp": "2026-06-01T14:00:00Z",
          "yes_bid": 47,
          "yes_ask": 49,
          "mid": 48,
          "close": 48,
          "volume": 12500,
          "source": "kalshi_candlestick",
          "synthetic_book": false
        },
        {
          "timestamp": "2026-06-01T13:00:00Z",
          "yes_bid": 47,
          "yes_ask": 47,
          "mid": 47,
          "close": 47,
          "volume": 9800,
          "source": "polymarket_clob_history",
          "synthetic_book": true
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 100,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Market not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/markets/{id}/candles","summary":"Get market candles","description":"Get OHLC candles for a market, optionally scoped to a source bucket window.","parameters":[{"name":"id","in":"path","required":true,"description":"Market ID","schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","description":"Items per page","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}},{"name":"from","in":"query","description":"Inclusive lower bound on `timestamp`","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"Exclusive upper bound on `timestamp`","schema":{"type":"string","format":"date-time"}},{"name":"interval","in":"query","description":"Candle period length in minutes","schema":{"type":"integer","default":60,"minimum":1}}],"responses":[{"status":"200","description":"OK","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","required":["timestamp","mid","source","synthetic_book"],"properties":{"timestamp":{"type":"string","format":"date-time","description":"End of the candle period, in UTC. The candle covers the requested `interval` minutes ending at this instant."},"yes_bid":{"type":["number","null"],"description":"Best YES bid at the end of the period, in cents (0-100), so 47 means a 47% probability. Absent when no bid was recorded for the period."},"yes_ask":{"type":["number","null"],"description":"Best YES ask at the end of the period, in cents (0-100), so 49 means a 49% probability. Absent when no ask was recorded for the period."},"mid":{"type":"number","description":"Reference price for the period, in cents (0-100), resolved in order: the midpoint of `yes_bid` and `yes_ask` when both are present, otherwise the period's mean traded price, otherwise the closing traded price. It is therefore not always a book midpoint and can be identical to `close`, so do not read it as a quote without checking `yes_bid` and `yes_ask`."},"close":{"type":["number","null"],"description":"Last traded price in the period, in cents (0-100). Absent when the period had no trades."},"volume":{"type":["number","null"],"description":"Contracts traded during the period. Reported for Kalshi candles only; Polymarket candles are built from a midpoint price feed that carries no trade sizes, so this is absent for them."},"source":{"type":"string","description":"Where the row came from. `polymarket_clob_history` rows are built from the CLOB prices-history midpoint feed rather than from a trade tape.","enum":["kalshi_candlestick","kalshi_historical_candlestick","polymarket_clob_history"]},"synthetic_book":{"type":"boolean","description":"True when yes_bid/yes_ask were synthesized as a zero-spread book from a midpoint-only feed (source = polymarket_clob_history) rather than observed on the venue; clients should badge these books as synthetic."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"timestamp":"2026-06-01T14:00:00Z","yes_bid":47,"yes_ask":49,"mid":48,"close":48,"volume":12500,"source":"kalshi_candlestick","synthetic_book":false},{"timestamp":"2026-06-01T13:00:00Z","yes_bid":47,"yes_ask":47,"mid":47,"close":47,"volume":9800,"source":"polymarket_clob_history","synthetic_book":true}],"meta":{"total":2,"page":1,"per_page":100,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"timestamp":"2026-06-01T14:00:00Z","yes_bid":47,"yes_ask":49,"mid":48,"close":48,"volume":12500,"source":"kalshi_candlestick","synthetic_book":false},{"timestamp":"2026-06-01T13:00:00Z","yes_bid":47,"yes_ask":47,"mid":47,"close":47,"volume":9800,"source":"polymarket_clob_history","synthetic_book":true}],"meta":{"total":2,"page":1,"per_page":100,"total_pages":1,"has_next":false,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Market not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Market not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Market not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Find related news
url: "https://docs.adjacent.markets/api/get-api-v1-markets-id-news.md"
description: Find news articles semantically related to a market using AI embeddings
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/markets/<id>/news" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "article_id": "a1b2c3d4",
          "similarity": 0.87,
          "title": "Senate race tightens in Pennsylvania",
          "url": "https://example.com/news/senate-pa",
          "published_date": "2026-06-01T08:00:00Z",
          "source": "Reuters"
        },
        {
          "article_id": "e5f6g7h8",
          "similarity": 0.81,
          "title": "New polling shifts House outlook",
          "url": "https://example.com/news/house-outlook",
          "published_date": "2026-06-01T07:30:00Z",
          "source": "AP"
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 20,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/markets/{id}/news","summary":"Find related news","description":"Find news articles semantically related to a market using AI embeddings","parameters":[{"name":"id","in":"path","required":true,"description":"Market ID","schema":{"type":"string"}},{"name":"min_similarity","in":"query","description":"Minimum cosine similarity a result must reach.","schema":{"type":"number","default":0.38,"minimum":0,"maximum":1}},{"name":"recency_half_life_days","in":"query","description":"Recency half-life in days for the relevance-recency blend applied to the ranking: a result's score is its similarity times 0.5^(age_days / this).","schema":{"type":"number","minimum":0}},{"name":"page","in":"query","description":"Page number","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","description":"Items per page","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":[{"status":"200","description":"Paginated related news articles","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"article_id":{"type":"string"},"similarity":{"type":"number"},"title":{"type":["string","null"]},"url":{"type":["string","null"]},"published_date":{"type":["string","null"],"format":"date-time"},"source":{"type":["string","null"]}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"article_id":"a1b2c3d4","similarity":0.87,"title":"Senate race tightens in Pennsylvania","url":"https://example.com/news/senate-pa","published_date":"2026-06-01T08:00:00Z","source":"Reuters"},{"article_id":"e5f6g7h8","similarity":0.81,"title":"New polling shifts House outlook","url":"https://example.com/news/house-outlook","published_date":"2026-06-01T07:30:00Z","source":"AP"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"article_id":"a1b2c3d4","similarity":0.87,"title":"Senate race tightens in Pennsylvania","url":"https://example.com/news/senate-pa","published_date":"2026-06-01T08:00:00Z","source":"Reuters"},{"article_id":"e5f6g7h8","similarity":0.81,"title":"New polling shifts House outlook","url":"https://example.com/news/house-outlook","published_date":"2026-06-01T07:30:00Z","source":"AP"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}}}]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get market price history
url: "https://docs.adjacent.markets/api/get-api-v1-markets-id-prices.md"
description: Get historical price data with OHLC aggregation
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/markets/<id>/prices" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "timestamp": "2026-06-03T04:00:00Z",
          "price": 64.5219,
          "ohlc": {
            "open": 63,
            "high": 65,
            "low": 61,
            "close": 64
          }
        },
        {
          "timestamp": "2026-06-02T04:00:00Z",
          "price": 63.9531,
          "ohlc": {
            "open": 63,
            "high": 65,
            "low": 61,
            "close": 64
          }
        }
      ],
      "meta": {
        "total": 68,
        "page": 1,
        "per_page": 100,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Market not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/markets/{id}/prices","summary":"Get market price history","description":"Get historical price data with OHLC aggregation","parameters":[{"name":"id","in":"path","required":true,"description":"Market ID","schema":{"type":"string"}},{"name":"per_page","in":"query","description":"Points per page (1-1000).","schema":{"type":"integer","default":100,"minimum":1,"maximum":1000}},{"name":"start","in":"query","description":"Start time","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","description":"End time","schema":{"type":"string","format":"date-time"}},{"name":"interval","in":"query","description":"Time bucket interval (daily, 1day also accepted as aliases for 1d)","schema":{"type":"string","enum":["1min","5min","1hour","1d"],"default":"5min"}},{"name":"order","in":"query","description":"Sort direction by timestamp","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"page","in":"query","required":false,"description":"1-based page number.","schema":{"type":"integer","default":1,"minimum":1}}],"responses":[{"status":"200","description":"Price history for the requested window, newest first unless `order=asc`.","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"Start of the aggregation bucket this point covers, in UTC. Daily buckets are anchored to midnight US Eastern, so a `1d` point's timestamp is 04:00 or 05:00 UTC depending on daylight saving."},"price":{"type":"number","description":"Value of the series for this bucket: the last price recorded within it. Equals `ohlc.close` on the same point where OHLC is returned, and is the same statistic the `previous_close_*` baselines are measured against. The scale is 0-100 for market and rate series, and the index level (roughly 50-150) for index series."},"price_raw":{"type":["number","null"],"description":"Not currently reachable on any tier, and always absent. The unsmoothed value exists only on the un-bucketed series, but every accepted interval (and the default) maps to a bucketed one, so no request can return it."},"volume":{"type":["number","null"],"description":"Not currently populated on any price series, on any tier, and always absent. Reserved: use the market volume fields for traded volume."},"ohlc":{"description":"Open, high, low and close for the bucket, on the same 0-100 scale as `price`. Returned on the market and rate price series only (index series omit it), and on a daily series a gap-filled day repeats the previous day's values rather than reporting new trading.","allOf":[{"type":"object","required":["open","high","low","close"],"properties":{"open":{"type":"number","description":"Price of the first trade in the bucket, in cents (0-100)."},"high":{"type":"number","description":"Highest traded price in the bucket, in cents (0-100)."},"low":{"type":"number","description":"Lowest traded price in the bucket, in cents (0-100)."},"close":{"type":"number","description":"Price of the last trade in the bucket, in cents (0-100). The same value the point's `price` field carries."}}}],"nullable":true},"spread":{"type":["number","null"],"description":"Dispersion across the source markets behind a reference-rate value: the highest source price minus the lowest, in the same 0-100 points as `price`. Meaningful only on rate series, and currently not populated on any price-series response, so it is always absent."},"sources":{"type":["object","null"],"description":"Provenance for a reference-rate value: the blending method used, plus the per-source prices and weights behind it. Currently not populated on any price-series response, so it is always absent; use `constituents` for the per-source breakdown.","additionalProperties":true},"constituents":{"type":["array","null"],"description":"The source markets behind a reference-rate value at this timestamp, each with its probability (0-100) and its weight renormalized to sum to 1 across the markets listed. Returned on the authenticated rate price series only, covering markets that were active at the timestamp and traded in that bucket; pass `sources=false` to omit it.","items":{"type":"object","properties":{"market_id":{"type":"string"},"price":{"type":"number"},"weight":{"type":"number"}}}}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"timestamp":"2026-06-03T04:00:00Z","price":64.5219,"ohlc":{"open":63,"high":65,"low":61,"close":64}},{"timestamp":"2026-06-02T04:00:00Z","price":63.9531,"ohlc":{"open":63,"high":65,"low":61,"close":64}}],"meta":{"total":68,"page":1,"per_page":100,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"timestamp":"2026-06-03T04:00:00Z","price":64.5219,"ohlc":{"open":63,"high":65,"low":61,"close":64}},{"timestamp":"2026-06-02T04:00:00Z","price":63.9531,"ohlc":{"open":63,"high":65,"low":61,"close":64}}],"meta":{"total":68,"page":1,"per_page":100,"total_pages":1,"has_next":false,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Market not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Market not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Market not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get market quote snapshots
url: "https://docs.adjacent.markets/api/get-api-v1-markets-id-quotes.md"
description: "Get raw bid/ask quote snapshots for a market, optionally scoped to a source bucket window."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/markets/<id>/quotes" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "timestamp": "2026-06-01T14:22:10Z",
          "yes_bid": 47,
          "yes_ask": 49,
          "mid": 48
        },
        {
          "timestamp": "2026-06-01T14:21:10Z",
          "yes_bid": 46,
          "yes_ask": 48,
          "mid": 47
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 100,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Market not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/markets/{id}/quotes","summary":"Get market quote snapshots","description":"Get raw bid/ask quote snapshots for a market, optionally scoped to a source bucket window.","parameters":[{"name":"id","in":"path","required":true,"description":"Market ID","schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","description":"Items per page","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}},{"name":"from","in":"query","description":"Inclusive lower bound on `timestamp`","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"Exclusive upper bound on `timestamp`","schema":{"type":"string","format":"date-time"}}],"responses":[{"status":"200","description":"OK","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","required":["timestamp","yes_bid","yes_ask","mid"],"properties":{"timestamp":{"type":"string","format":"date-time","description":"When this bid/ask snapshot was recorded, in UTC."},"yes_bid":{"type":"number","description":"Top-of-book YES bid in cents (0-100)."},"yes_ask":{"type":"number","description":"Top-of-book YES ask in cents (0-100)."},"mid":{"type":"number","description":"Top-of-book mid = (yes_bid + yes_ask) / 2, in cents (0-100)."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"timestamp":"2026-06-01T14:22:10Z","yes_bid":47,"yes_ask":49,"mid":48},{"timestamp":"2026-06-01T14:21:10Z","yes_bid":46,"yes_ask":48,"mid":47}],"meta":{"total":2,"page":1,"per_page":100,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"timestamp":"2026-06-01T14:22:10Z","yes_bid":47,"yes_ask":49,"mid":48},{"timestamp":"2026-06-01T14:21:10Z","yes_bid":46,"yes_ask":48,"mid":47}],"meta":{"total":2,"page":1,"per_page":100,"total_pages":1,"has_next":false,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Market not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Market not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Market not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Find similar markets
url: "https://docs.adjacent.markets/api/get-api-v1-markets-id-similar.md"
description: Find semantically similar markets using AI embeddings
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/markets/<id>/similar" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "market_id": "kalshi:KXNBA-26-NYK",
          "similarity": 0.91,
          "platform": "kalshi",
          "question": "Will the New York win the 2026 Pro Basketball Finals?"
        },
        {
          "market_id": "kalshi:KXNBA-26-BOS",
          "similarity": 0.88,
          "platform": "kalshi",
          "question": "Will the Boston win the 2026 Pro Basketball Finals?"
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 20,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/markets/{id}/similar","summary":"Find similar markets","description":"Find semantically similar markets using AI embeddings","parameters":[{"name":"id","in":"path","required":true,"description":"Market ID","schema":{"type":"string"}},{"name":"min_similarity","in":"query","description":"Minimum cosine similarity a result must reach.","schema":{"type":"number","default":0.38,"minimum":0,"maximum":1}},{"name":"page","in":"query","description":"Page number","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","description":"Items per page","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":[{"status":"200","description":"Paginated similar markets","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"market_id":{"type":"string"},"similarity":{"type":"number"},"description":{"type":["string","null"]},"platform":{"type":["string","null"]},"latest_price":{"type":["number","null"]},"question":{"type":["string","null"],"description":"The market's question."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"market_id":"kalshi:KXNBA-26-NYK","similarity":0.91,"platform":"kalshi","question":"Will the New York win the 2026 Pro Basketball Finals?"},{"market_id":"kalshi:KXNBA-26-BOS","similarity":0.88,"platform":"kalshi","question":"Will the Boston win the 2026 Pro Basketball Finals?"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"market_id":"kalshi:KXNBA-26-NYK","similarity":0.91,"platform":"kalshi","question":"Will the New York win the 2026 Pro Basketball Finals?"},{"market_id":"kalshi:KXNBA-26-BOS","similarity":0.88,"platform":"kalshi","question":"Will the Boston win the 2026 Pro Basketball Finals?"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get market trades
url: "https://docs.adjacent.markets/api/get-api-v1-markets-id-trades.md"
description: Get recent trades for a market
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/markets/<id>/trades" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "trade_id": "d25ba779-817d-6df2-9bc1-e381aeadecbc",
          "timestamp": "2026-06-03T14:46:34.680308Z",
          "price": 65,
          "count": 30,
          "side": "yes",
          "volume": 19.5
        },
        {
          "trade_id": "acd34816-75a9-6fb6-72f9-f6b48c48a660",
          "timestamp": "2026-06-03T14:46:31.814730Z",
          "price": 65,
          "count": 225,
          "side": "yes",
          "volume": 146.25
        }
      ],
      "meta": {
        "total": 128113,
        "page": 1,
        "per_page": 20,
        "total_pages": 6406,
        "has_next": true,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Market not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/markets/{id}/trades","summary":"Get market trades","description":"Get recent trades for a market","parameters":[{"name":"id","in":"path","required":true,"description":"Market ID","schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","description":"Items per page","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}},{"name":"from","in":"query","description":"Inclusive lower bound on `timestamp`","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"Exclusive upper bound on `timestamp`","schema":{"type":"string","format":"date-time"}}],"responses":[{"status":"200","description":"Paginated trades","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"trade_id":{"type":"string","description":"Identifier for the trade. Kalshi supplies its own trade id; Polymarket fills have no venue id, so theirs is a composite key derived from the settling transaction and the fill's own fields."},"timestamp":{"type":"string","format":"date-time","description":"When the trade executed on the venue, in UTC."},"price":{"type":"number","description":"Yes-side traded price in cents (0-100), the canonical API scale."},"count":{"type":"integer","description":"Quantity traded: contracts on Kalshi, shares on Polymarket (rounded to a whole number)."},"side":{"type":"string","description":"Which side the taker (the aggressing order) was on, `yes` or `no`. Polymarket buy/sell fills are normalized onto the same two values."},"volume":{"type":["number","null"],"description":"Trade size. Platform-native: Kalshi is USD notional, Polymarket is shares."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"trade_id":"d25ba779-817d-6df2-9bc1-e381aeadecbc","timestamp":"2026-06-03T14:46:34.680308Z","price":65,"count":30,"side":"yes","volume":19.5},{"trade_id":"acd34816-75a9-6fb6-72f9-f6b48c48a660","timestamp":"2026-06-03T14:46:31.814730Z","price":65,"count":225,"side":"yes","volume":146.25}],"meta":{"total":128113,"page":1,"per_page":20,"total_pages":6406,"has_next":true,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"trade_id":"d25ba779-817d-6df2-9bc1-e381aeadecbc","timestamp":"2026-06-03T14:46:34.680308Z","price":65,"count":30,"side":"yes","volume":19.5},{"trade_id":"acd34816-75a9-6fb6-72f9-f6b48c48a660","timestamp":"2026-06-03T14:46:31.814730Z","price":65,"count":225,"side":"yes","volume":146.25}],"meta":{"total":128113,"page":1,"per_page":20,"total_pages":6406,"has_next":true,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Market not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Market not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Market not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List news articles
url: "https://docs.adjacent.markets/api/get-api-v1-news.md"
description: "Stored articles, newest first, with optional source and language filters."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/news" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/news","summary":"List news articles","description":"Stored articles, newest first, with optional source and language filters.","parameters":[{"name":"limit","in":"query","description":"Page size.","schema":{"type":"integer","default":50,"minimum":1,"maximum":500}},{"name":"offset","in":"query","description":"Row offset.","schema":{"type":"integer","default":0,"minimum":0}},{"name":"source","in":"query","description":"Restrict to one source id.","schema":{"type":"string"}},{"name":"language","in":"query","description":"Restrict to one ISO 639-1 code.","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Articles plus total/limit/offset","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","required":["id","url","source","embedded"],"properties":{"id":{"type":"string","description":"Opaque, stable article identifier."},"title":{"type":["string","null"],"description":"Headline, where the source reported one."},"url":{"type":"string","description":"Link to the article on the publisher's site."},"source":{"type":"string","description":"Source id the article was collected under. See /api/v1/news/filters for the values in use."},"published_date":{"type":["string","null"],"format":"date-time","description":"Publication time reported by the source, never later than when we ingested it."},"language":{"type":["string","null"],"description":"ISO 639-1 code, resolved from the source catalog. Null when the source is not in the catalog."},"image_url":{"type":["string","null"],"description":"Lead image URL where the source provides one."},"publisher":{"type":["string","null"],"description":"Publishing outlet name as reported by the source."},"created_at":{"type":["string","null"],"format":"date-time","description":"When this row was first recorded."},"embedded":{"type":"boolean","description":"Whether a semantic-search embedding exists for this article. False whenever embeddings are disabled."}}}},"meta":{"type":"object","required":["total","limit","offset"],"properties":{"total":{"type":"integer","description":"Total articles matching the filters, ignoring limit/offset."},"limit":{"type":"integer","description":"Page size actually applied after clamping."},"offset":{"type":"integer","description":"Row offset applied."}}}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List available news filters
url: "https://docs.adjacent.markets/api/get-api-v1-news-filters.md"
description: "Distinct source ids and language codes present in the articles, for populating filter controls."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/news/filters" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/news/filters","summary":"List available news filters","description":"Distinct source ids and language codes present in the articles, for populating filter controls.","parameters":[],"responses":[{"status":"200","description":"Available filter values","schema":{"type":"object","description":"The distinct values currently present in the articles, for populating filter controls.","required":["sources","languages"],"properties":{"sources":{"type":"array","description":"Distinct source ids present.","items":{"type":"string"}},"languages":{"type":"array","description":"Distinct ISO 639-1 codes present.","items":{"type":"string"}}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get latest news
url: "https://docs.adjacent.markets/api/get-api-v1-news-latest.md"
description: "Get the latest news articles from 5,000+ sources"
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/news/latest" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "id": "a1b2c3d4",
          "title": "Senate race tightens in Pennsylvania",
          "url": "https://example.com/news/senate-pa",
          "published_date": "2026-06-01T08:00:00Z",
          "author": "Jane Doe",
          "source": "Reuters"
        },
        {
          "id": "e5f6g7h8",
          "title": "New polling shifts House outlook",
          "url": "https://example.com/news/house-outlook",
          "published_date": "2026-06-01T07:30:00Z",
          "author": "John Smith",
          "source": "AP"
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 20,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/news/latest","summary":"Get latest news","description":"Get the latest news articles from 5,000+ sources","parameters":[{"name":"page","in":"query","description":"Page number","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","description":"Items per page","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}},{"name":"days","in":"query","description":"Number of days to look back","schema":{"type":"integer","default":7,"minimum":1,"maximum":365}}],"responses":[{"status":"200","description":"Paginated news articles","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","required":["id","title"],"properties":{"id":{"type":"string","description":"Opaque, stable identifier for the article. It is not a publisher identifier and will not match anything upstream."},"title":{"type":"string","description":"The article's headline."},"url":{"type":["string","null"],"description":"Link to the article on the publisher's site."},"published_date":{"type":["string","null"],"format":"date-time","description":"When the article was published according to its source, falling back to when it was first recorded if the source gave no date. The list is ordered by this field, newest first."},"author":{"type":["string","null"],"description":"Byline where the source reports one. Many feeds do not, so this is frequently absent."},"source":{"type":["string","null"],"description":"Short name of the feed the article was collected from; some providers report the publishing outlet's name here instead."},"image_url":{"type":["string","null"],"description":"Lead image URL where the source provides one."},"favicon_url":{"type":["string","null"],"description":"Publisher favicon URL. Currently always null."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"id":"a1b2c3d4","title":"Senate race tightens in Pennsylvania","url":"https://example.com/news/senate-pa","published_date":"2026-06-01T08:00:00Z","author":"Jane Doe","source":"Reuters"},{"id":"e5f6g7h8","title":"New polling shifts House outlook","url":"https://example.com/news/house-outlook","published_date":"2026-06-01T07:30:00Z","author":"John Smith","source":"AP"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"id":"a1b2c3d4","title":"Senate race tightens in Pennsylvania","url":"https://example.com/news/senate-pa","published_date":"2026-06-01T08:00:00Z","author":"Jane Doe","source":"Reuters"},{"id":"e5f6g7h8","title":"New polling shifts House outlook","url":"https://example.com/news/house-outlook","published_date":"2026-06-01T07:30:00Z","author":"John Smith","source":"AP"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get a news article
url: "https://docs.adjacent.markets/api/get-api-v1-news-id.md"
description: "Full stored record for one article, including its description and truncated body."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/news/<id>" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/news/{id}","summary":"Get a news article","description":"Full stored record for one article, including its description and truncated body.","parameters":[{"name":"id","in":"path","required":true,"description":"Article id.","schema":{"type":"string"}}],"responses":[{"status":"200","description":"The article","schema":{"type":"object","required":["id","url","source"],"properties":{"id":{"type":"string","description":"Opaque, stable article identifier."},"title":{"type":["string","null"],"description":"Headline, where the source reported one."},"url":{"type":"string","description":"Link to the article on the publisher's site."},"source":{"type":"string","description":"Source id the article was collected under. See /api/v1/news/filters for the values in use."},"published_date":{"type":["string","null"],"format":"date-time","description":"Publication time reported by the source, never later than when we ingested it."},"language":{"type":["string","null"],"description":"ISO 639-1 code, resolved from the source catalog. Null when the source is not in the catalog."},"image_url":{"type":["string","null"],"description":"Lead image URL where the source provides one."},"publisher":{"type":["string","null"],"description":"Publishing outlet name as reported by the source."},"created_at":{"type":["string","null"],"format":"date-time","description":"When this row was first recorded."},"author":{"type":["string","null"],"description":"Byline where the source reports one."},"description":{"type":["string","null"],"description":"Short summary supplied by the source."},"content":{"type":["string","null"],"description":"Truncated body text, typically around 200 characters."},"updated_at":{"type":["string","null"],"format":"date-time","description":"When this row was last refreshed by a re-ingest of the same URL."}}},"examples":[]},{"status":"404","description":"No article with that id","examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Find related markets
url: "https://docs.adjacent.markets/api/get-api-v1-news-id-markets.md"
description: Find markets semantically related to a news article using AI embeddings
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/news/<id>/markets" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "market_id": "kalshi:SENATEPA-26-R",
          "similarity": 0.89,
          "name": "Will a Republican win the 2026 Pennsylvania U.S. Senate election?",
          "platform": "kalshi"
        },
        {
          "market_id": "kalshi:GOVPA-26-R",
          "similarity": 0.76,
          "name": "Will a Republican win the 2026 Pennsylvania Governor election?",
          "platform": "kalshi"
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 20,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/news/{id}/markets","summary":"Find related markets","description":"Find markets semantically related to a news article using AI embeddings","parameters":[{"name":"id","in":"path","required":true,"description":"Article ID","schema":{"type":"string"}},{"name":"min_similarity","in":"query","description":"Minimum cosine similarity a result must reach.","schema":{"type":"number","default":0.38,"minimum":0,"maximum":1}},{"name":"page","in":"query","description":"Page number","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","description":"Items per page","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":[{"status":"200","description":"Paginated related markets","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"market_id":{"type":"string"},"similarity":{"type":"number"},"name":{"type":["string","null"]},"description":{"type":["string","null"]},"category":{"type":["string","null"]},"platform":{"type":["string","null"]},"latest_price":{"type":["number","null"]}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"market_id":"kalshi:SENATEPA-26-R","similarity":0.89,"name":"Will a Republican win the 2026 Pennsylvania U.S. Senate election?","platform":"kalshi"},{"market_id":"kalshi:GOVPA-26-R","similarity":0.76,"name":"Will a Republican win the 2026 Pennsylvania Governor election?","platform":"kalshi"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"market_id":"kalshi:SENATEPA-26-R","similarity":0.89,"name":"Will a Republican win the 2026 Pennsylvania U.S. Senate election?","platform":"kalshi"},{"market_id":"kalshi:GOVPA-26-R","similarity":0.76,"name":"Will a Republican win the 2026 Pennsylvania Governor election?","platform":"kalshi"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}}}]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List public events
url: "https://docs.adjacent.markets/api/get-api-v1-public-events.md"
description: Markets grouped into their parent events.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/events"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "event_id": "kalshi:KXPRESPARTY-2028",
          "name": "2028 Presidential Election winner? (Party)",
          "category": "Elections",
          "market_count": 2,
          "volume": 525225.94,
          "volume_unit": "contracts",
          "open_interest": 254090.81,
          "open_interest_unit": "contracts",
          "is_constituent": true,
          "markets": [
            {
              "market_id": "kalshi:KXPRESPARTY-2028-D",
              "ticker": "KXPRESPARTY-2028-D",
              "display_ticker": "KXPRESPARTY-2028-D",
              "platform": "kalshi",
              "question": "Will Democratic win the Presidency in 2028?",
              "link": "https://kalshi.com/markets/kxpresparty/kxpresparty-2028",
              "probability": 58,
              "volume": 233444.98,
              "volume_unit": "contracts",
              "volume_24h": 14.2,
              "volume_24h_unit": "contracts",
              "open_interest": 116538.21,
              "open_interest_unit": "contracts",
              "status": "active",
              "category": "Elections",
              "is_constituent": true,
              "end_date": "2029-11-07T15:00:00Z"
            }
          ]
        }
      ],
      "meta": {
        "total": 412,
        "page": 1,
        "per_page": 1,
        "total_pages": 412,
        "has_next": true,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/events","summary":"List public events","description":"Markets grouped into their parent events.","parameters":[{"name":"scope","in":"query","description":"`constituents` (default) returns events with at least one constituent market; `all` returns every event.","schema":{"type":"string","enum":["constituents","all"],"default":"constituents"}},{"name":"search","in":"query","description":"Case-insensitive word match over an event's member markets (question, description, series title, market ID, and market slug) plus the event name and ID.","schema":{"type":"string"}},{"name":"sort","in":"query","description":"Sort key.","schema":{"type":"string","enum":["created","title","volume","open_interest","market_count"],"default":"created"}},{"name":"sort_dir","in":"query","description":"Sort direction, `asc` or `desc` (default `desc`).","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"page","in":"query","description":"Page number (1-based).","schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","description":"Events per page (clamped to 500).","schema":{"type":"integer","default":100,"maximum":500}},{"name":"status","in":"query","description":"Market status filter applied to the rows feeding the grouping.","schema":{"type":"string"}},{"name":"category","in":"query","description":"Exact-match event category; CSV for multiple (matches ANY).","schema":{"type":"string"}},{"name":"venue","in":"query","description":"Venue / platform filter (CSV), matched on the `market_id` prefix (e.g.","schema":{"type":"string"}},{"name":"platform","in":"query","description":"Alias for `venue`.","schema":{"type":"string"}},{"name":"volume_min","in":"query","description":"Minimum summed (event-level) volume.","schema":{"type":"number"}},{"name":"oi_min","in":"query","description":"Minimum summed (event-level) open interest.","schema":{"type":"number"}},{"name":"expires_before","in":"query","description":"ISO date/datetime inclusive upper bound on a market's `end_date` (a bare date snaps to end-of-day).","schema":{"type":"string"}},{"name":"expires_after","in":"query","description":"ISO date/datetime inclusive lower bound on a market's `end_date` (a bare date snaps to start-of-day).","schema":{"type":"string"}},{"name":"exclude_categories","in":"query","description":"CSV of category substrings to exclude (case-insensitive substring match).","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Paginated list of event summaries with embedded child markets","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","description":"A parent event on the public markets list, aggregated from its child markets. Lets the markets/search UI collapse a multi-strike event into one expandable row.","required":["event_id","market_count","is_constituent","markets"],"properties":{"event_id":{"type":"string","description":"Prefixed venue event ticker (e.g. `kalshi:KXBTCD-…`), the grouping key."},"category":{"type":["string","null"],"description":"Category shared by this event's markets, drawn from the same fixed cross-venue taxonomy as everywhere else in the API. Null only when the parent event has no category recorded."},"market_count":{"type":"integer","description":"Number of child markets within the requested scope."},"volume":{"type":["number","null"],"description":"Summed all-time contract/share volume across the child markets, not dollars. Unit is in `volume_unit`."},"volume_unit":{"description":"Wire unit for `volume`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"open_interest":{"type":["number","null"],"description":"Summed open interest across the child markets: Kalshi contract counts plus Polymarket USD. Unit is in `open_interest_unit`."},"open_interest_unit":{"description":"Wire unit for `open_interest`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"is_constituent":{"type":"boolean","description":"True when any child market is an index constituent."},"markets":{"type":"array","description":"The child markets, each the same shape as a flat /public/markets row.","items":{"type":"object","properties":{"market_id":{"type":"string","description":"Canonical identifier for the market, formed as `<platform>:<venue ticker>` (for example `kalshi:SENATEPA-26-R`). This is the id every other endpoint accepts, so use it rather than `ticker` when looking a market up."},"ticker":{"type":"string","description":"The venue's own symbol for the market, without the `<platform>:` prefix. Not guaranteed unique across venues, so use `market_id` as the lookup key and `display_ticker` as the human-readable label."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"The venue that lists this market: `kalshi` or `polymarket`. It is also the prefix of `market_id`, and it determines what the volume and open interest figures are counted in (see the companion `volume_unit`, `volume_24h_unit`, and `open_interest_unit` fields)."},"question":{"type":"string","description":"The market's question, worded as the venue words it. When a venue supplies no title we fall back to the raw ticker, so this is never empty."},"probability":{"type":["number","null"],"description":"Implied yes-side probability on the 0-100 scale, where 48.5 means 48.5 percent. This is the market's latest traded price."},"volume":{"type":["number","null"],"description":"All-time traded volume as a contract/share count (Kalshi contracts, Polymarket shares), not dollars. Unit is in `volume_unit`."},"volume_unit":{"description":"Wire unit for `volume`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"volume_24h":{"type":["number","null"],"description":"Trailing 24h volume. Platform-native: Kalshi contracts, Polymarket USD. Unit is in `volume_24h_unit`."},"volume_24h_unit":{"description":"Wire unit for `volume_24h`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"open_interest":{"type":["number","null"],"description":"Open interest: a Kalshi contract count; Polymarket's is USD. Unit is in `open_interest_unit`."},"open_interest_unit":{"description":"Wire unit for `open_interest`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"status":{"type":"string","description":"Lifecycle state of the market: `active` (trading), `closed` (trading has ended, outcome not yet published), `resolved` (settled with a known outcome), `expired` (ended long ago and never settled by the venue), or `unknown` (the venue reported no status we recognize)."},"category":{"type":["string","null"],"description":"Topic category of this market's parent event, normalized across venues (for example `Politics`, `Sports`, `Crypto`). Every market under the same event shares it."},"is_constituent":{"type":"boolean","description":"True when the market is a constituent of at least one index. The public markets list exposes every tracked market; default to constituents by filtering on this flag."},"indices":{"type":"array","description":"Index ids this market is a constituent of, ascending. Omitted when the market is in no index. Populated only on the authenticated /api/v1/markets list.","items":{"type":"string"}},"end_date":{"type":["string","null"],"format":"date-time","description":"When trading closes on the venue. This is not the settlement time; a market can sit in `closed` for a while before its outcome is published."},"created_at":{"type":"string","format":"date-time","description":"When we first recorded this market, not when the venue listed it. Only the authenticated markets list returns it; the public markets list omits it."},"updated_at":{"type":"string","format":"date-time","description":"When any stored field on this market last changed on our side, so it also moves on routine metadata refreshes and is not a price-move timestamp. Only the authenticated markets list returns it; the public markets list omits it."},"link":{"type":["string","null"],"description":"URL of the venue's public page for this contract, which on both venues is the parent event page rather than a single strike. Null when no working URL can be built, which happens for Kalshi markets whose series is unknown."},"state_code":{"type":["string","null"],"description":"Two-letter US state code when the contract is tied to a state race. Absent for national contests and for markets with no state on record."},"city_code":{"type":["string","null"],"description":"Mayoral city code parsed at ingest; present for Mayoral markets, absent otherwise."}}}},"name":{"type":["string","null"],"description":"Human-readable parent event name."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"event_id":"kalshi:KXPRESPARTY-2028","name":"2028 Presidential Election winner? (Party)","category":"Elections","market_count":2,"volume":525225.94,"volume_unit":"contracts","open_interest":254090.81,"open_interest_unit":"contracts","is_constituent":true,"markets":[{"market_id":"kalshi:KXPRESPARTY-2028-D","ticker":"KXPRESPARTY-2028-D","display_ticker":"KXPRESPARTY-2028-D","platform":"kalshi","question":"Will Democratic win the Presidency in 2028?","link":"https://kalshi.com/markets/kxpresparty/kxpresparty-2028","probability":58,"volume":233444.98,"volume_unit":"contracts","volume_24h":14.2,"volume_24h_unit":"contracts","open_interest":116538.21,"open_interest_unit":"contracts","status":"active","category":"Elections","is_constituent":true,"end_date":"2029-11-07T15:00:00Z"}]}],"meta":{"total":412,"page":1,"per_page":1,"total_pages":412,"has_next":true,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"event_id":"kalshi:KXPRESPARTY-2028","name":"2028 Presidential Election winner? (Party)","category":"Elections","market_count":2,"volume":525225.94,"volume_unit":"contracts","open_interest":254090.81,"open_interest_unit":"contracts","is_constituent":true,"markets":[{"market_id":"kalshi:KXPRESPARTY-2028-D","ticker":"KXPRESPARTY-2028-D","display_ticker":"KXPRESPARTY-2028-D","platform":"kalshi","question":"Will Democratic win the Presidency in 2028?","link":"https://kalshi.com/markets/kxpresparty/kxpresparty-2028","probability":58,"volume":233444.98,"volume_unit":"contracts","volume_24h":14.2,"volume_24h_unit":"contracts","open_interest":116538.21,"open_interest_unit":"contracts","status":"active","category":"Elections","is_constituent":true,"end_date":"2029-11-07T15:00:00Z"}]}],"meta":{"total":412,"page":1,"per_page":1,"total_pages":412,"has_next":true,"has_prev":false}}}]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List public indices
url: "https://docs.adjacent.markets/api/get-api-v1-public-indices.md"
description: List all indices from the public snapshot tier.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/indices"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "index_id": "red",
          "name": "Republican Political Future Index",
          "ticker": "RED",
          "description": "Composite of Republican party-line contests across all levels of office in the United States",
          "constituents_count": 5,
          "is_composite": true,
          "office_category": null,
          "party_side": "republican",
          "latest_price": 96.6691,
          "previous_close_1d": 96.6815,
          "change_1d": -0.0217,
          "price_change_1d": -0.0124,
          "change_7d": 0.9579976564409233,
          "change_30d": 6.543321995939699,
          "change_90d": 8.343186711332823,
          "previous_close_7d": 95.7518,
          "previous_close_30d": 90.7322,
          "previous_close_90d": 89.2249,
          "updated_at": "2026-07-29T14:02:00Z",
          "methodology": "upfi",
          "created_at": "2026-06-02T14:20:24.299003Z",
          "display_order": 1,
          "halted": false
        }
      ],
      "meta": {
        "total": 10,
        "page": 1,
        "per_page": 1,
        "total_pages": 10,
        "has_next": true,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/indices","summary":"List public indices","description":"List all indices from the public snapshot tier.","parameters":[],"responses":[{"status":"200","description":"List of index summaries","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","required":["index_id","name","ticker","description","constituents_count","is_composite","office_category"],"properties":{"index_id":{"type":"string","description":"Stable identifier for the index (for example `red`). Use it as the `{id}` path parameter on the index detail, constituents, and price endpoints."},"name":{"type":"string","description":"Full display name of the index."},"ticker":{"type":"string","description":"Short uppercase symbol for the index (for example `RED`). The detail endpoint accepts either this ticker (case-insensitively) or `index_id` as its path parameter."},"description":{"type":"string","description":"One-line description of what the index tracks, suitable for a listing card."},"constituents_count":{"type":"integer","description":"Number of constituents in the index: member markets for a market-basket index, or child sub-indices for a composite. A derived index that inherits its book from a base index reports 0 and names that base in `base_index_id`."},"is_composite":{"type":"boolean","description":"True for a composite index (its constituents are other indices and its price blends child sub-index values); false for a market-basket index (its constituents are exchange markets). Always present, so a client can branch on index kind even when the index has no constituents yet."},"office_category":{"type":["string","null"],"description":"The index's declared office category (lowercase, e.g. \"senate\"), the input to methodology weighting and composite child-weight derivation. Null for composites and uncategorized indices; always present."},"latest_price":{"type":["number","null"],"description":"Most recent index level, on the base-100 index scale (100 is neutral; for the probability-based families each point above or below 100 is one percentage point of the blended win probability). Omitted when the index has no computed value yet."},"previous_close_1d":{"type":["number","null"],"description":"The index level at the previous daily close, meaning the most recent completed daily close before the current day in US Eastern time, not a rolling 24-hour window. Baseline for change_1d."},"change_1d":{"type":["number","null"],"description":"Trailing percent change from the previous completed ET daily close (`previous_close_1d`) to the live tip. Omitted when there is no prior daily close."},"price_change_1d":{"type":["number","null"],"description":"Absolute 1-day change in index points (latest_price minus previous_close_1d), measured against the same previous ET daily close as change_1d. Omitted when there is no prior daily close."},"price_change_7d":{"type":["number","null"],"description":"Absolute 7-day change in index points (latest_price minus previous_close_7d), measured against the same daily-close baseline as change_7d. Omitted when there is no daily close that far back."},"price_change_30d":{"type":["number","null"],"description":"Absolute 30-day change in index points (latest_price minus previous_close_30d), measured against the same daily-close baseline as change_30d. Omitted when there is no daily close that far back."},"price_change_90d":{"type":["number","null"],"description":"Absolute 90-day change in index points (latest_price minus previous_close_90d), measured against the same daily-close baseline as change_90d. Omitted when there is no daily close that far back."},"change_7d":{"type":["number","null"],"description":"Trailing percent change from the index value 7 days ago to the live tip, from the daily close series. Omitted when there is no daily close that far back."},"change_30d":{"type":["number","null"],"description":"Trailing percent change over the last 30 days. Omitted when there is no daily close that far back."},"change_90d":{"type":["number","null"],"description":"Trailing percent change over the last 90 days. Omitted when there is no daily close that far back."},"previous_close_7d":{"type":["number","null"],"description":"The index value (daily close) 7 days before the snapshot, the baseline change_7d is measured against, so a client can show the absolute change on the same baseline. Omitted when there is no daily close that far back."},"previous_close_30d":{"type":["number","null"],"description":"The index value (daily close) 30 days before the snapshot."},"previous_close_90d":{"type":["number","null"],"description":"The index value (daily close) 90 days before the snapshot."},"updated_at":{"type":["string","null"],"format":"date-time","description":"Timestamp of `latest_price`. Omitted when the index has no computed value yet."},"methodology":{"type":["string","null"],"description":"Key of the methodology family that defines this index's constituent weighting and level calculation, for example `upfi`, `battleground`, or `total_return`. Null for an index with no methodology recorded."},"quote_convention":{"type":"string","description":"The unit this index quotes trailing performance in. `percent`: render the `change_*` fields. `points`: render the `price_change_*` fields, because the level is a point sum and a percent of it carries no meaning.","enum":["percent","points"]},"base_index_id":{"type":["string","null"],"description":"For a total_return index, the composite index it derives its book from; null for every curated family."},"created_at":{"type":"string","format":"date-time","description":"When the index was created in this API. Returned by the authenticated indices list only."},"display_order":{"type":["integer","null"],"description":"Presentation ordering; lower values sort first, null sorts last."},"halted":{"type":"boolean","description":"True when the latest index value was carried forward because the index fell below its constituent floor."},"halt_valid_constituents":{"type":["integer","null"],"description":"When halted, the valid (priced, guardrail-passing) constituents at the most recent halt cycle. Omitted when not halted."},"halt_min_constituents":{"type":["integer","null"],"description":"When halted, the category constituent floor the index fell below. Omitted when not halted."},"halt_reason":{"type":["string","null"],"description":"When halted, a human-readable explanation of the halt, composed from the constituent halt counts. Omitted when not halted."},"party_side":{"type":["string","null"],"description":"Which party line the basket is priced on, or null for a non-party index. Drives composition.state_exposure.party_lean (the Dem/Rep axis the state map colors on). Always present so a client can render the side an index carries rather than inferring it.","enum":["republican","democrat"]},"visibility":{"type":"string","description":"Access level of the index. `public` is visible to everyone; `organization` is visible to members of listed organizations. Other reserved values may appear on authenticated responses. Omitted on the anonymous public tier, which returns only public indices.","enum":["public","superuser","organization"]}}}},"meta":{"allOf":[{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}]}}},"example":{"data":[{"index_id":"red","name":"Republican Political Future Index","ticker":"RED","description":"Composite of Republican party-line contests across all levels of office in the United States","constituents_count":5,"is_composite":true,"office_category":null,"party_side":"republican","latest_price":96.6691,"previous_close_1d":96.6815,"change_1d":-0.0217,"price_change_1d":-0.0124,"change_7d":0.9579976564409233,"change_30d":6.543321995939699,"change_90d":8.343186711332823,"previous_close_7d":95.7518,"previous_close_30d":90.7322,"previous_close_90d":89.2249,"updated_at":"2026-07-29T14:02:00Z","methodology":"upfi","created_at":"2026-06-02T14:20:24.299003Z","display_order":1,"halted":false}],"meta":{"total":10,"page":1,"per_page":1,"total_pages":10,"has_next":true,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"index_id":"red","name":"Republican Political Future Index","ticker":"RED","description":"Composite of Republican party-line contests across all levels of office in the United States","constituents_count":5,"is_composite":true,"office_category":null,"party_side":"republican","latest_price":96.6691,"previous_close_1d":96.6815,"change_1d":-0.0217,"price_change_1d":-0.0124,"change_7d":0.9579976564409233,"change_30d":6.543321995939699,"change_90d":8.343186711332823,"previous_close_7d":95.7518,"previous_close_30d":90.7322,"previous_close_90d":89.2249,"updated_at":"2026-07-29T14:02:00Z","methodology":"upfi","created_at":"2026-06-02T14:20:24.299003Z","display_order":1,"halted":false}],"meta":{"total":10,"page":1,"per_page":1,"total_pages":10,"has_next":true,"has_prev":false}}}]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get public index detail
url: "https://docs.adjacent.markets/api/get-api-v1-public-indices-id.md"
description: "Index detail with trailing-return and risk stats, plus composition analytics: state exposure, maturity profile, weight attribution, and per-constituent returns over 1d, 7d, and 30d."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/indices/<id>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "index_id": "red",
      "name": "Republican Political Future Index",
      "ticker": "RED",
      "description": "Composite of Republican party-line contests across all levels of office in the United States",
      "office_category": null,
      "methodology": "upfi",
      "is_composite": true,
      "constituents_count": 5,
      "latest_price": 96.6691,
      "level_interpretation": [
        {
          "label": "Index level",
          "value": "96.7"
        },
        {
          "label": "Composite probability value",
          "value": "46.7%"
        },
        {
          "label": "Interpretation",
          "value": "-3.3 pts"
        }
      ],
      "price_change_1d": -0.0124,
      "price_change_7d": 0.9173,
      "previous_close_1d": 96.6815,
      "previous_close_7d": 95.7518,
      "stats": {
        "trailing_returns": [
          {
            "label": "1D",
            "value": -0.01282561813790593
          },
          {
            "label": "1W",
            "value": 0.9579976564409206
          }
        ]
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/indices/{id}","summary":"Get public index detail","description":"Index detail with trailing-return and risk stats, plus composition analytics: state exposure, maturity profile, weight attribution, and per-constituent returns over 1d, 7d, and 30d.","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g.","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Index detail","schema":{"type":"object","required":["index_id","name","ticker","description","constituents_count","is_composite","office_category"],"properties":{"index_id":{"type":"string","description":"Stable identifier for the index (for example `red`). Use it as the `{id}` path parameter on the index detail, constituents, and price endpoints."},"name":{"type":"string","description":"Full display name of the index."},"ticker":{"type":"string","description":"Short uppercase symbol for the index (for example `RED`). This endpoint accepts either this ticker (case-insensitively) or `index_id` as its path parameter."},"description":{"type":["string","null"],"description":"Free-text description of what the index tracks."},"methodology":{"type":["string","null"],"description":"Registered methodology key used to compute the index. Omitted only when no methodology is stored."},"quote_convention":{"type":"string","description":"The unit this index quotes trailing performance in. `percent`: render the `change_*` fields. `points`: render the `price_change_*` fields, because the level is a point sum and a percent of it carries no meaning.","enum":["percent","points"]},"constituents_count":{"type":"integer","description":"Number of constituents in the index: member markets for a market-basket index, or child sub-indices for a composite. A derived index that inherits its book from a base index reports 0 and names that base in `base_index_id`."},"is_composite":{"type":"boolean","description":"True for a composite index (its constituents are other indices and its price blends child sub-index values); false for a market-basket index (its constituents are exchange markets). Always present, so a client can branch on index kind even when the index has no constituents yet."},"office_category":{"type":["string","null"],"description":"The index's declared office category (lowercase, e.g. \"senate\"), the input to methodology weighting and composite child-weight derivation. Null for composites and uncategorized indices; always present."},"base_index_id":{"type":["string","null"],"description":"For a derived total_return index, the composite index it compounds the returns of; null for the curated families, which have no base. The detail page shows this in place of the constituent count a derived index lacks."},"latest_price":{"type":["number","null"],"description":"Most recent index level, on the base-100 index scale (100 is neutral). See `level_interpretation` for how this index's methodology frames the level, since a probability family and a total-return family read the same number differently."},"level_interpretation":{"type":"array","description":"Methodology-resolved rows explaining what latest_price means, formatted server-side (the curated families frame it as a composite probability, total_return as a compounding return). The client renders them verbatim; omitted when the level or the methodology is unavailable.","items":{"type":"object","required":["label","value"],"properties":{"label":{"type":"string"},"value":{"type":"string"}}}},"price_change_1d":{"type":["number","null"],"description":"Absolute change in index points (not a percent) from the previous daily close to `latest_price`. The baseline is the last completed daily close before the current day in US Eastern time, so this is a change against a settled value rather than a rolling 24-hour window."},"price_change_7d":{"type":["number","null"],"description":"Absolute change in index points (not a percent) from the daily close seven days before the current day in US Eastern time to `latest_price`. Null when the index has no daily close that far back."},"previous_close_1d":{"type":["number","null"],"description":"The index level at the previous daily close, meaning the last completed daily close before the current day in US Eastern time, not a rolling 24-hour window. Returned by `GET /api/v1/public/indices/{id}`; omitted on `GET /api/v1/indices/{id}`."},"previous_close_7d":{"type":["number","null"],"description":"The index level at the daily close seven days before the current day in US Eastern time, the baseline `price_change_7d` is measured against. Returned by `GET /api/v1/public/indices/{id}`; omitted on `GET /api/v1/indices/{id}`."},"stats":{"description":"Trailing returns and risk statistics computed from the index's daily close series over roughly the trailing 400 days. Returned by both index detail endpoints; the values are null individually when the series is too short for that window.","allOf":[{"type":"object","properties":{"trailing_returns":{"type":"array","description":"Percent price change over each of six fixed trailing windows: 1D, 1W, 1M, 3M, YTD, and 1Y.","items":{"type":"object","required":["label"],"properties":{"label":{"type":"string","description":"The trailing window this return covers: `1D`, `1W`, `1M`, `3M`, `YTD`, or `1Y`."},"value":{"type":["number","null"],"description":"Percent change from the value at the start of the window to the latest value in the series. Null when the series has no data point close enough to the start of that window."},"point_change":{"type":["number","null"],"description":"Absolute change in the level's own units over the same window. Point-quoted indices (quote_convention `points`) express trailing performance with this figure; omitted when no comparable historical point exists."}}}},"risk":{"type":"object","description":"Volatility, range, and period return computed over the most recent 31 points of the daily series. The window counts data points, so a series with gaps spans more than 31 calendar days.","properties":{"volatility":{"type":["number","null"],"description":"Annualized volatility in percent, from the daily returns across the most recent 31 daily data points, annualized over 365 days because these markets trade every calendar day. Null when the daily series has fewer than 3 points."},"daily_vol":{"type":["number","null"],"description":"Standard deviation of the daily returns across the most recent 31 daily data points, in percent and not annualized. Null when the daily series has fewer than 3 points."},"range_high":{"type":["number","null"],"description":"Highest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"range_low":{"type":["number","null"],"description":"Lowest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"return_pct":{"type":["number","null"],"description":"Percent change from the first to the last of the most recent 31 daily data points. Null when the daily series has fewer than 3 points."}}}}}],"nullable":true},"composition":{"description":"Breakdown of the index over its flattened constituents: per-state exposure and a maturity profile of when those constituents expire.","allOf":[{"type":"object","properties":{"state_exposure":{"type":"array","description":"Per-state breakdown of the index, alphabetical by state code. Only constituents that map to a US state are represented, so a national contest contributes to none of these entries.","items":{"type":"object","properties":{"state_code":{"type":"string","description":"Two-letter US state code. Entries are ordered alphabetically, and only constituents that map to a state appear, so national contests are absent."},"probability":{"type":"number","description":"Weight-blended probability for the state, 0-100, across the markets listed in `markets`. Falls back to a plain average of those markets when none of them carry weight."},"party_lean":{"type":"number","description":"Weight-blended Republican lean for map coloring (0 = Dem favored, 100 = Rep favored). Derived from probability and the index's party_side (democrat inverts; republican or unset passes through). Heatmap color uses this field only."},"weight":{"type":"number","description":"Combined index weight of this state's markets, as a fraction rather than a percent."},"count":{"type":"integer","description":"Number of constituent markets contributing to this state."},"markets":{"type":"array","description":"The individual constituent markets behind this state's blended probability and weight.","items":{"type":"object","required":["ticker","display_ticker","price","weight"],"properties":{"ticker":{"type":"string","description":"Raw exchange ticker of the market. Use `display_ticker` for a label."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"name":{"type":["string","null"],"description":"The market's question text. Absent when the market has no question on record."},"price":{"type":"number","description":"The market's probability, 0-100, as it entered the index calculation. A market with no usable price is reported as 0."},"weight":{"type":"number","description":"The market's effective weight in the index, as a fraction rather than a percent."}}}}}}},"maturity":{"type":"object","description":"When the index's constituents expire: future expirations bucketed by date, plus a count of constituents that have already expired.","properties":{"buckets":{"type":"array","description":"Future expiration dates in ascending order, one entry per date on which at least one constituent expires. Constituents with no expiration date on record appear neither here nor in `expired`.","items":{"type":"object","properties":{"date":{"type":"string","description":"ISO date YYYY-MM-DD."},"count":{"type":"integer","description":"Number of constituent markets expiring on this date."},"total_weight":{"type":"number","description":"Combined index weight of the markets expiring on this date, as a fraction rather than a percent."}}}},"expired":{"type":"integer","description":"Number of constituents whose expiration has already passed. They are counted here only and are excluded from `buckets`."}}},"attribution":{"type":"array","description":"Per-leaf-market contribution to the index level (weight times price/100), with weight and price computed together server-side (the price is the mid that entered that cycle, not the latest trade; composite child levels anchor at the parent's resolved cycle): weights sum to ~1.0 and contributions reconcile to the published price's blended probability, partial composite baskets included. Falls back to stored base weights and current prices only for an index with no compute cycle yet.","items":{"type":"object","properties":{"market_id":{"type":"string","description":"Canonical market id (`<platform>:<raw_ticker>`) for the attributed constituent."},"ticker":{"type":"string","description":"Raw exchange ticker of the constituent market. Use `display_ticker` for a label and `market_id` for lookups or links."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"name":{"type":["string","null"],"description":"The constituent market's question text. Absent when the market has no question on record."},"contribution":{"type":"number","description":"The market's share of the index's blended probability, equal to `weight` multiplied by `price` divided by 100. Rows are ordered by descending absolute contribution and, across all rows, sum to the blended probability behind the published index level."},"weight":{"type":"number","description":"The market's effective weight in the index, as a fraction rather than a percent, after any sub-index legs are flattened. Weights across all rows sum to about 1.0."},"price":{"type":"number","description":"The market's probability, 0-100, as it entered the index calculation these figures reconcile to. Because it is the value that calculation consumed, it can lag the market's latest trade."}}}},"constituent_returns":{"type":"array","description":"Per-constituent own price move for the 1d/7d/30d trailing windows, precomputed server-side. Each row includes percent_change; each window includes group_by and groups.","items":{"type":"object","description":"Per-constituent price moves for one trailing window, computed server-side. A window whose start predates the index's earliest compute cycle comes back empty (rows: [], groups: []), degrading together with the null stats.trailing_returns for the same window.","properties":{"window":{"type":"string","description":"Window label: 1d / 7d / 30d."},"group_by":{"type":"string","description":"Dimension groups are keyed by. state means each group's key is a US state (or other for untagged rows). A city, party, or office grouping is a different group_by value, not a new field on the group.","enum":["state"]},"rows":{"type":"array","description":"One row per constituent held at the end of the window, ordered from largest to smallest end weight. Constituents that left the index before the window ended are omitted, and the array is empty when the index has no history reaching back to the window start.","items":{"type":"object","description":"One constituent's own price move over a trailing window. Every field is computed server-side and rendered verbatim.","properties":{"constituent_id":{"type":"string","description":"Prefixed constituent id (with kind): market_id for a market, index_id for a sub-index leg, rate_id for a rate sleeve, event_id for a same-event race."},"kind":{"type":"string","description":"Navigable kind: market (market page) / index (index page) / rate (rate page) / event (a same-event race, not individually linkable).","enum":["market","index","event","rate"]},"ticker":{"type":"string","description":"Display ticker for the constituent: the market's ticker (a readable slug where the venue provides one), the child index's ticker for a sub-index leg, the rate_id for a rate sleeve, or the race identifier for a same-event group."},"name":{"type":["string","null"],"description":"Readable name for the constituent: the market's question, the child index's name, the rate's name, or the event's name. Absent when the underlying record has none."},"platform":{"type":"string","description":"kalshi/polymarket for markets; index for a composite's sub-index leg; rate for a rate-backed sleeve."},"state_code":{"type":["string","null"],"description":"Two-letter state for House/Senate/Gov market constituents; absent for composite legs, same-event races, and markets with no state."},"weight":{"type":"number","description":"Effective (composite-flattened, normalized) weight at the window end."},"start_weight":{"type":"number","description":"Same weight at the window start, so a tile whose size changed over the window (a reweighting) is explainable (start_weight -> weight)."},"start_price":{"type":"number","description":"Constituent value at the start of the window (0-100 probability for markets; the child's UPFI value for a composite's sub-index leg; the rate mark for a rate sleeve)."},"end_price":{"type":"number","description":"Constituent value at the end of the window (same scale as start_price)."},"point_change":{"type":"number","description":"end_price minus start_price, in the constituent's own points."},"percent_change":{"type":["number","null"],"description":"Percent change from start_price to end_price: (end_price - start_price) / start_price * 100. Null when start_price is 0."}}}},"groups":{"type":"array","description":"Aggregates of rows under group_by, ordered from largest to smallest weight. Empty when rows is empty.","items":{"type":"object","description":"One grouped slice of constituent returns for a trailing window. The grouping dimension is the window's group_by; key identifies the group. Weight, point_change, and percent_change are computed server-side from the window's rows.","properties":{"key":{"type":"string","description":"Group id inside group_by. When group_by is state, this is a two-letter US state, or other for untagged rows."},"label":{"type":"string","description":"Display string when it differs from key. Omitted when key is already the label."},"weight":{"type":"number","description":"Sum of member end weights."},"member_count":{"type":"integer","description":"Count of members with end weight greater than 0."},"point_change":{"type":"number","description":"Weight-average of member point_change."},"percent_change":{"type":["number","null"],"description":"Weight-average of member percent_change over members whose percent_change is present. Null when no member has a usable start_price."}}}}}}}}}],"nullable":true},"halted":{"type":"boolean","description":"True when the latest index value was carried forward because the index fell below its constituent floor."},"halt_valid_constituents":{"type":["integer","null"],"description":"When halted, the valid (priced, guardrail-passing) constituents at the most recent halt cycle. Omitted when not halted."},"halt_min_constituents":{"type":["integer","null"],"description":"When halted, the category constituent floor the index fell below. Omitted when not halted."},"halt_reason":{"type":["string","null"],"description":"When halted, a human-readable explanation of the halt, composed from the constituent halt counts. Omitted when not halted."},"visibility":{"type":"string","description":"Access level of the index. `public` is visible to everyone; `organization` is visible to members of listed organizations. Other reserved values may appear on authenticated responses. Omitted on the anonymous public tier, which returns only public indices.","enum":["public","superuser","organization"]},"official_daily_value":{"description":"Most recent official daily value. Null when this index family does not publish daily values.","allOf":[{"type":"object","description":"One official daily value: the value stamped for one US-Eastern calendar day.","required":["et_date","value"],"properties":{"et_date":{"type":"string","format":"date","description":"The US-Eastern calendar day the value is official for."},"value":{"type":"number","description":"The official index value for that day, in index points."}}}],"nullable":true},"sleeves":{"type":"array","description":"Current sleeve state for an NFL team index. Empty for other index families.","items":{"type":"object","description":"One sleeve of an NFL team index: a fixed seat holding at most one market at a time.","required":["sleeve","active","cumulative_points"],"properties":{"sleeve":{"type":"string","description":"Stable sleeve name.","enum":["super_bowl","conference","division","next_game"]},"active":{"type":"boolean","description":"Whether the sleeve holds an active member. An inactive sleeve keeps its seat and contributes nothing until a successor is admitted."},"market_id":{"type":["string","null"],"description":"The current member's market id. Omitted for an inactive sleeve."},"display_ticker":{"type":["string","null"],"description":"Display label for the current member. Omitted for an inactive sleeve."},"name":{"type":["string","null"],"description":"The current member's question. Omitted for an inactive sleeve."},"mark_price":{"type":["number","null"],"description":"The sleeve's latest approved mark, 0-100. Omitted for an inactive sleeve or before the sleeve's first computed mark."},"cumulative_points":{"type":"number","description":"The sleeve's cumulative contribution to the index level since base, in index points."}}}}}},"example":{"index_id":"red","name":"Republican Political Future Index","ticker":"RED","description":"Composite of Republican party-line contests across all levels of office in the United States","office_category":null,"methodology":"upfi","is_composite":true,"constituents_count":5,"latest_price":96.6691,"level_interpretation":[{"label":"Index level","value":"96.7"},{"label":"Composite probability value","value":"46.7%"},{"label":"Interpretation","value":"-3.3 pts"}],"price_change_1d":-0.0124,"price_change_7d":0.9173,"previous_close_1d":96.6815,"previous_close_7d":95.7518,"stats":{"trailing_returns":[{"label":"1D","value":-0.01282561813790593},{"label":"1W","value":0.9579976564409206}]}},"examples":[{"name":"default","value":{"index_id":"red","name":"Republican Political Future Index","ticker":"RED","description":"Composite of Republican party-line contests across all levels of office in the United States","office_category":null,"methodology":"upfi","is_composite":true,"constituents_count":5,"latest_price":96.6691,"level_interpretation":[{"label":"Index level","value":"96.7"},{"label":"Composite probability value","value":"46.7%"},{"label":"Interpretation","value":"-3.3 pts"}],"price_change_1d":-0.0124,"price_change_7d":0.9173,"previous_close_1d":96.6815,"previous_close_7d":95.7518,"stats":{"trailing_returns":[{"label":"1D","value":-0.01282561813790593},{"label":"1W","value":0.9579976564409206}]}}}]},{"status":"404","description":"Index not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get public index constituents
url: "https://docs.adjacent.markets/api/get-api-v1-public-indices-id-constituents.md"
description: "Constituents of an index, both markets and child sub-indices, with their weights."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/indices/<id>/constituents"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "kind": "index",
          "market_id": "presr_kalshi",
          "ticker": "presr_kalshi",
          "display_ticker": "presr_kalshi",
          "platform": "index",
          "weight": 0.4000000059604645,
          "price": 91.5,
          "name": "Presidential (R)"
        }
      ],
      "meta": {
        "total": 5,
        "page": 1,
        "per_page": 1,
        "total_pages": 5,
        "has_next": true,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/indices/{id}/constituents","summary":"Get public index constituents","description":"Constituents of an index, both markets and child sub-indices, with their weights.","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g.","schema":{"type":"string"}},{"name":"expand","in":"query","description":"`markets` flattens a composite index into its leaf markets server-side, each returned once with its effective weight (product of the BASE parent×child weights along the path; sums to ~1.0 for a full composite basket, under 1.0 for a partial basket whose methodology categories are not all linked).","schema":{"type":"string"}},{"name":"flatten","in":"query","description":"Boolean alias for `expand=markets`.","schema":{"type":"boolean","default":false}},{"name":"search","in":"query","description":"Case-insensitive substring match over ticker and name, applied server-side.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page number, 1-based.","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","required":false,"description":"Rows per page (max 500).","schema":{"type":"integer","default":500,"minimum":1,"maximum":500}}],"responses":[{"status":"200","description":"List of constituents","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","required":["kind","market_id","ticker","display_ticker","platform","weight"],"properties":{"kind":{"type":"string","description":"Discriminator: 'market' for leaf prediction markets, 'index' for composite sub-indices.","enum":["market","index"]},"market_id":{"type":"string","description":"Canonical id. For markets: `<platform>:<raw_ticker>`. For composites: the child index_id."},"ticker":{"type":"string","description":"For markets: raw exchange ticker. For composites: the child index_id."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"'kalshi'/'polymarket' for markets; 'index' for composite components."},"weight":{"type":"number","description":"This constituent's share of the index, as a fraction of 1 (0.18 means 18 percent). These are the index's stored base weights, which sum to 1 across the full constituent list; a given published price point can differ, because the calculation renormalizes over only the constituents that had a usable price that cycle."},"price":{"type":["number","null"],"description":"Latest value for the constituent: for market constituents, the most recent yes-side traded price on the 0-100 cents scale; for sub-index constituents (`kind` = `index`), the child index's latest published level, which is in index points and not on the 0-100 scale. Null when the constituent has never traded or has no published value yet, and it carries no age bound, so an inactive market's price can be hours old."},"name":{"type":["string","null"],"description":"Display label for the constituent: the market's question for market rows, and the sub-index's name for `kind` = `index` rows."},"volume":{"type":["number","null"],"description":"All-time traded volume as a contract/share count (Kalshi contracts, Polymarket shares), not dollars. Present for kind='market' rows only. Unit is in `volume_unit`."},"volume_unit":{"description":"Wire unit for `volume`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"open_interest":{"type":["number","null"],"description":"Open interest: a Kalshi contract count; Polymarket's is USD. Present for kind='market' rows only. Unit is in `open_interest_unit`."},"open_interest_unit":{"description":"Wire unit for `open_interest`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"end_date":{"type":["string","null"],"format":"date-time","description":"When trading closes for a market constituent. Always null for sub-index constituents (`kind` = `index`), which do not expire."},"state_code":{"type":["string","null"],"description":"Two-letter state code (House/Senate/Gubernatorial); market rows only"},"city_code":{"type":["string","null"],"description":"City code (Mayoral); market rows only"}}}},"meta":{"allOf":[{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}]}}},"example":{"data":[{"kind":"index","market_id":"presr_kalshi","ticker":"presr_kalshi","display_ticker":"presr_kalshi","platform":"index","weight":0.4000000059604645,"price":91.5,"name":"Presidential (R)"}],"meta":{"total":5,"page":1,"per_page":1,"total_pages":5,"has_next":true,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"kind":"index","market_id":"presr_kalshi","ticker":"presr_kalshi","display_ticker":"presr_kalshi","platform":"index","weight":0.4000000059604645,"price":91.5,"name":"Presidential (R)"}],"meta":{"total":5,"page":1,"per_page":1,"total_pages":5,"has_next":true,"has_prev":false}}}]},{"status":"404","description":"Index not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get public index correlation matrix
url: "https://docs.adjacent.markets/api/get-api-v1-public-indices-id-correlation.md"
description: "Pearson correlation matrix of daily returns across a composite index's sub-indices."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/indices/<id>/correlation"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "labels": [
        "PRESR",
        "SENR",
        "HOUSER"
      ],
      "matrix": [
        [
          1,
          0.14106277110820079,
          0.011328065794435568
        ],
        [
          0.14106277110820079,
          1,
          0.2001014424010028
        ],
        [
          0.011328065794435568,
          0.2001014424010028,
          1
        ]
      ]
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/indices/{id}/correlation","summary":"Get public index correlation matrix","description":"Pearson correlation matrix of daily returns across a composite index's sub-indices.","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g.","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Correlation matrix","schema":{"type":"object","properties":{"labels":{"type":"array","description":"Tickers of the sub-indices, in the same order as the rows and columns of `matrix`. Empty for an index that has no sub-indices.","items":{"type":"string"}},"matrix":{"type":"array","description":"Row-major NxN matrix; diagonal is 1.0, cells with insufficient overlap are null.","items":{"type":"array","items":{"type":["number","null"]}}},"days":{"type":"integer","description":"Number of dates on which every sub-index has a daily return, which is the sample the correlations are computed over. Below 5 no correlations are produced and `matrix` comes back empty."}}},"example":{"labels":["PRESR","SENR","HOUSER"],"matrix":[[1,0.14106277110820079,0.011328065794435568],[0.14106277110820079,1,0.2001014424010028],[0.011328065794435568,0.2001014424010028,1]]},"examples":[{"name":"default","value":{"labels":["PRESR","SENR","HOUSER"],"matrix":[[1,0.14106277110820079,0.011328065794435568],[0.14106277110820079,1,0.2001014424010028],[0.011328065794435568,0.2001014424010028,1]]}}]},{"status":"404","description":"Index not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get public index price history
url: "https://docs.adjacent.markets/api/get-api-v1-public-indices-id-prices.md"
description: Delayed index price series.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/indices/<id>/prices"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "timestamp": "2026-07-29T14:04:00Z",
          "price": 96.6692
        },
        {
          "timestamp": "2026-07-28T04:00:00Z",
          "price": 96.6815
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 2,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/indices/{id}/prices","summary":"Get public index price history","description":"Delayed index price series.","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g.","schema":{"type":"string"}},{"name":"interval","in":"query","required":false,"description":"1hour (30d window) or 1d (90d window).","schema":{"type":"string","enum":["1hour","1d"],"default":"1hour"}},{"name":"per_page","in":"query","required":false,"description":"Rows returned in this response (1-1000).","schema":{"type":"integer","default":1000,"minimum":1,"maximum":1000}},{"name":"start","in":"query","required":false,"description":"Optional ISO-8601 or YYYY-MM-DD lower bound, clipped to the contract window.","schema":{"type":"string"}},{"name":"end","in":"query","required":false,"description":"Optional ISO-8601 or YYYY-MM-DD upper bound; defaults to the snapshot pin.","schema":{"type":"string"}},{"name":"order","in":"query","required":false,"description":"Sort direction.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}],"responses":[{"status":"200","description":"Price points","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"Start of the aggregation bucket this point covers, in UTC. Daily buckets are anchored to midnight US Eastern, so a `1d` point's timestamp is 04:00 or 05:00 UTC depending on daylight saving."},"price":{"type":"number","description":"Value of the series for this bucket: the last price recorded within it. Equals `ohlc.close` on the same point where OHLC is returned, and is the same statistic the `previous_close_*` baselines are measured against. The scale is 0-100 for market and rate series, and the index level (roughly 50-150) for index series."},"price_raw":{"type":["number","null"],"description":"Not currently reachable on any tier, and always absent. The unsmoothed value exists only on the un-bucketed series, but every accepted interval (and the default) maps to a bucketed one, so no request can return it."},"volume":{"type":["number","null"],"description":"Not currently populated on any price series, on any tier, and always absent. Reserved: use the market volume fields for traded volume."},"ohlc":{"description":"Open, high, low and close for the bucket, on the same 0-100 scale as `price`. Returned on the market and rate price series only (index series omit it), and on a daily series a gap-filled day repeats the previous day's values rather than reporting new trading.","allOf":[{"type":"object","required":["open","high","low","close"],"properties":{"open":{"type":"number","description":"Price of the first trade in the bucket, in cents (0-100)."},"high":{"type":"number","description":"Highest traded price in the bucket, in cents (0-100)."},"low":{"type":"number","description":"Lowest traded price in the bucket, in cents (0-100)."},"close":{"type":"number","description":"Price of the last trade in the bucket, in cents (0-100). The same value the point's `price` field carries."}}}],"nullable":true},"spread":{"type":["number","null"],"description":"Dispersion across the source markets behind a reference-rate value: the highest source price minus the lowest, in the same 0-100 points as `price`. Meaningful only on rate series, and currently not populated on any price-series response, so it is always absent."},"sources":{"type":["object","null"],"description":"Provenance for a reference-rate value: the blending method used, plus the per-source prices and weights behind it. Currently not populated on any price-series response, so it is always absent; use `constituents` for the per-source breakdown.","additionalProperties":true},"constituents":{"type":["array","null"],"description":"The source markets behind a reference-rate value at this timestamp, each with its probability (0-100) and its weight renormalized to sum to 1 across the markets listed. Returned on the authenticated rate price series only, covering markets that were active at the timestamp and traded in that bucket; pass `sources=false` to omit it.","items":{"type":"object","properties":{"market_id":{"type":"string"},"price":{"type":"number"},"weight":{"type":"number"}}}}}}},"meta":{"allOf":[{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}]}}},"example":{"data":[{"timestamp":"2026-07-29T14:04:00Z","price":96.6692},{"timestamp":"2026-07-28T04:00:00Z","price":96.6815}],"meta":{"total":2,"page":1,"per_page":2,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"timestamp":"2026-07-29T14:04:00Z","price":96.6692},{"timestamp":"2026-07-28T04:00:00Z","price":96.6815}],"meta":{"total":2,"page":1,"per_page":2,"total_pages":1,"has_next":false,"has_prev":false}}}]},{"status":"400","description":"Invalid interval or bound","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]},{"status":"404","description":"Index not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List public markets
url: "https://docs.adjacent.markets/api/get-api-v1-public-markets.md"
description: Paginated list of tracked markets on the 15-minute-delayed public tier.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/markets"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "market_id": "kalshi:KXPRESPARTY-2028-D",
          "ticker": "KXPRESPARTY-2028-D",
          "display_ticker": "KXPRESPARTY-2028-D",
          "platform": "kalshi",
          "question": "Will Democratic win the Presidency in 2028?",
          "link": "https://kalshi.com/markets/kxpresparty/kxpresparty-2028",
          "probability": 58,
          "volume": 233444.98,
          "volume_unit": "contracts",
          "volume_24h": 14.2,
          "volume_24h_unit": "contracts",
          "open_interest": 116538.21,
          "open_interest_unit": "contracts",
          "status": "active",
          "category": "Elections",
          "is_constituent": true
        }
      ],
      "meta": {
        "total": 1155,
        "page": 1,
        "per_page": 1,
        "total_pages": 1155,
        "has_next": true,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/markets","summary":"List public markets","description":"Paginated list of tracked markets on the 15-minute-delayed public tier.","parameters":[{"name":"scope","in":"query","description":"`constituents` (default) returns only index constituents; `all` returns every tracked market.","schema":{"type":"string","enum":["constituents","all"],"default":"constituents"}},{"name":"search","in":"query","description":"Case-insensitive word match over the market's question, description, series title, market ID, and market slug.","schema":{"type":"string"}},{"name":"sort","in":"query","description":"Sort key.","schema":{"type":"string","enum":["volume","ticker","price","open_interest","expiration"],"default":"volume"}},{"name":"sort_dir","in":"query","description":"Sort direction, `asc` or `desc` (default `desc`).","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"page","in":"query","description":"Page number (1-based).","schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","description":"Items per page (clamped to 500).","schema":{"type":"integer","default":100,"maximum":500}},{"name":"status","in":"query","description":"Market status filter.","schema":{"type":"string"}},{"name":"category","in":"query","description":"Exact-match event category; CSV for multiple (matches ANY).","schema":{"type":"string"}},{"name":"venue","in":"query","description":"Venue / platform filter (CSV), matched on the `market_id` prefix (e.g.","schema":{"type":"string"}},{"name":"platform","in":"query","description":"Alias for `venue`.","schema":{"type":"string"}},{"name":"volume_min","in":"query","description":"Minimum per-market volume.","schema":{"type":"number"}},{"name":"oi_min","in":"query","description":"Minimum per-market open interest.","schema":{"type":"number"}},{"name":"expires_before","in":"query","description":"ISO date/datetime inclusive upper bound on `end_date` (a bare date snaps to end-of-day).","schema":{"type":"string"}},{"name":"expires_after","in":"query","description":"ISO date/datetime inclusive lower bound on `end_date` (a bare date snaps to start-of-day).","schema":{"type":"string"}},{"name":"exclude_categories","in":"query","description":"CSV of category substrings to exclude (case-insensitive substring match).","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Paginated list of market summaries","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"market_id":{"type":"string","description":"Canonical identifier for the market, formed as `<platform>:<venue ticker>` (for example `kalshi:SENATEPA-26-R`). This is the id every other endpoint accepts, so use it rather than `ticker` when looking a market up."},"ticker":{"type":"string","description":"The venue's own symbol for the market, without the `<platform>:` prefix. Not guaranteed unique across venues, so use `market_id` as the lookup key and `display_ticker` as the human-readable label."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"The venue that lists this market: `kalshi` or `polymarket`. It is also the prefix of `market_id`, and it determines what the volume and open interest figures are counted in (see the companion `volume_unit`, `volume_24h_unit`, and `open_interest_unit` fields)."},"question":{"type":"string","description":"The market's question, worded as the venue words it. When a venue supplies no title we fall back to the raw ticker, so this is never empty."},"probability":{"type":["number","null"],"description":"Implied yes-side probability on the 0-100 scale, where 48.5 means 48.5 percent. This is the market's latest traded price."},"volume":{"type":["number","null"],"description":"All-time traded volume as a contract/share count (Kalshi contracts, Polymarket shares), not dollars. Unit is in `volume_unit`."},"volume_unit":{"description":"Wire unit for `volume`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"volume_24h":{"type":["number","null"],"description":"Trailing 24h volume. Platform-native: Kalshi contracts, Polymarket USD. Unit is in `volume_24h_unit`."},"volume_24h_unit":{"description":"Wire unit for `volume_24h`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"open_interest":{"type":["number","null"],"description":"Open interest: a Kalshi contract count; Polymarket's is USD. Unit is in `open_interest_unit`."},"open_interest_unit":{"description":"Wire unit for `open_interest`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"status":{"type":"string","description":"Lifecycle state of the market: `active` (trading), `closed` (trading has ended, outcome not yet published), `resolved` (settled with a known outcome), `expired` (ended long ago and never settled by the venue), or `unknown` (the venue reported no status we recognize)."},"category":{"type":["string","null"],"description":"Topic category of this market's parent event, normalized across venues (for example `Politics`, `Sports`, `Crypto`). Every market under the same event shares it."},"is_constituent":{"type":"boolean","description":"True when the market is a constituent of at least one index. The public markets list exposes every tracked market; default to constituents by filtering on this flag."},"indices":{"type":"array","description":"Index ids this market is a constituent of, ascending. Omitted when the market is in no index. Populated only on the authenticated /api/v1/markets list.","items":{"type":"string"}},"end_date":{"type":["string","null"],"format":"date-time","description":"When trading closes on the venue. This is not the settlement time; a market can sit in `closed` for a while before its outcome is published."},"created_at":{"type":"string","format":"date-time","description":"When we first recorded this market, not when the venue listed it. Only the authenticated markets list returns it; the public markets list omits it."},"updated_at":{"type":"string","format":"date-time","description":"When any stored field on this market last changed on our side, so it also moves on routine metadata refreshes and is not a price-move timestamp. Only the authenticated markets list returns it; the public markets list omits it."},"link":{"type":["string","null"],"description":"URL of the venue's public page for this contract, which on both venues is the parent event page rather than a single strike. Null when no working URL can be built, which happens for Kalshi markets whose series is unknown."},"state_code":{"type":["string","null"],"description":"Two-letter US state code when the contract is tied to a state race. Absent for national contests and for markets with no state on record."},"city_code":{"type":["string","null"],"description":"Mayoral city code parsed at ingest; present for Mayoral markets, absent otherwise."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"market_id":"kalshi:KXPRESPARTY-2028-D","ticker":"KXPRESPARTY-2028-D","display_ticker":"KXPRESPARTY-2028-D","platform":"kalshi","question":"Will Democratic win the Presidency in 2028?","link":"https://kalshi.com/markets/kxpresparty/kxpresparty-2028","probability":58,"volume":233444.98,"volume_unit":"contracts","volume_24h":14.2,"volume_24h_unit":"contracts","open_interest":116538.21,"open_interest_unit":"contracts","status":"active","category":"Elections","is_constituent":true}],"meta":{"total":1155,"page":1,"per_page":1,"total_pages":1155,"has_next":true,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"market_id":"kalshi:KXPRESPARTY-2028-D","ticker":"KXPRESPARTY-2028-D","display_ticker":"KXPRESPARTY-2028-D","platform":"kalshi","question":"Will Democratic win the Presidency in 2028?","link":"https://kalshi.com/markets/kxpresparty/kxpresparty-2028","probability":58,"volume":233444.98,"volume_unit":"contracts","volume_24h":14.2,"volume_24h_unit":"contracts","open_interest":116538.21,"open_interest_unit":"contracts","status":"active","category":"Elections","is_constituent":true}],"meta":{"total":1155,"page":1,"per_page":1,"total_pages":1155,"has_next":true,"has_prev":false}}}]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get public market detail
url: "https://docs.adjacent.markets/api/get-api-v1-public-markets-id.md"
description: Live single-market detail with enriched static metadata and the latest available quote.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/markets/<id>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "market_id": "kalshi:KXPRESPARTY-2028-D",
      "ticker": "KXPRESPARTY-2028-D",
      "display_ticker": "KXPRESPARTY-2028-D",
      "platform": "kalshi",
      "question": "Will Democratic win the Presidency in 2028?",
      "probability": 58,
      "volume": 233444.98,
      "volume_unit": "contracts",
      "volume_24h": 14.2,
      "volume_24h_unit": "contracts",
      "open_interest": 116538.21,
      "open_interest_unit": "contracts",
      "yes_bid": 57,
      "yes_ask": 58,
      "no_bid": 42,
      "no_ask": 43,
      "event_ticker": "KXPRESPARTY-2028",
      "status": "active",
      "open_time": "2024-11-06T15:00:00Z",
      "end_date": "2029-11-07T15:00:00Z",
      "expiration_date": "2029-01-21T15:00:00Z",
      "link": "https://kalshi.com/markets/kxpresparty/kxpresparty-2028",
      "category": "Elections",
      "market_type": "binary"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/markets/{id}","summary":"Get public market detail","description":"Live single-market detail with enriched static metadata and the latest available quote.","parameters":[{"name":"id","in":"path","required":true,"description":"Prefixed market_id.","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Market detail","schema":{"type":"object","description":"A single market with full detail. Both the authenticated and public market-detail routes return this exact shape.","required":["market_id","ticker","display_ticker","platform"],"properties":{"market_id":{"type":"string","description":"Canonical identifier for the market, formed as `<platform>:<venue ticker>` (for example `kalshi:SENATEPA-26-R`). This is the id every other endpoint accepts, so use it rather than `ticker` when looking a market up."},"ticker":{"type":"string","description":"The venue's own symbol for the market, without the `<platform>:` prefix. Not guaranteed unique across venues, so use `market_id` as the lookup key and `display_ticker` as the human-readable label."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"The venue that lists this market: `kalshi` or `polymarket`. It is also the prefix of `market_id`, and it determines what the volume and open interest figures are counted in (see the companion `volume_unit`, `volume_24h_unit`, and `open_interest_unit` fields)."},"question":{"type":["string","null"],"description":"The market's question, worded as the venue words it. When a venue supplies no title we fall back to the raw ticker, so this is never empty."},"description":{"type":["string","null"],"description":"Longer explanatory text for the contract as supplied by the venue (Kalshi's subtitle, Polymarket's description). Frequently absent, especially on Kalshi."},"probability":{"type":["number","null"],"description":"Implied yes-side probability on the 0-100 scale, where 48.5 means 48.5 percent. For a live market this is the latest traded price. For a resolved market with a known yes/no outcome it is the settlement value (100 or 0) rather than the last traded price."},"volume":{"type":["number","null"],"description":"All-time traded volume as a contract/share count (Kalshi contracts, Polymarket shares), not dollars. Unit is in `volume_unit`."},"volume_unit":{"description":"Wire unit for `volume`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"volume_24h":{"type":["number","null"],"description":"Trailing 24h volume. Platform-native: Kalshi contracts, Polymarket USD. Unit is in `volume_24h_unit`."},"volume_24h_unit":{"description":"Wire unit for `volume_24h`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"open_interest":{"type":["number","null"],"description":"Open interest: a Kalshi contract count; Polymarket's is USD. Unit is in `open_interest_unit`."},"open_interest_unit":{"description":"Wire unit for `open_interest`. See QuantityUnit.","allOf":[{"type":"string","description":"Wire unit for a market quantity field. Backend-owned from platform reporting conventions so clients never map platform→unit themselves. `contracts` = Kalshi contract count; `shares` = Polymarket share count (lifetime volume); `usd` = Polymarket USD notional (volume_24h / OI); `mixed` = event-level aggregate over children that disagree.","enum":["contracts","shares","usd","mixed"]}],"nullable":true},"yes_bid":{"type":["number","null"],"description":"Latest top-of-book YES bid (0-100 cents, ~1-min fresh)."},"yes_ask":{"type":["number","null"],"description":"Latest top-of-book YES ask (0-100 cents, ~1-min fresh)."},"no_bid":{"type":["number","null"],"description":"Derived NO bid (100 - yes_ask)."},"no_ask":{"type":["number","null"],"description":"Derived NO ask (100 - yes_bid)."},"event_ticker":{"type":["string","null"],"description":"Raw venue event ticker (unprefixed)."},"status":{"type":["string","null"],"description":"Lifecycle state of the market: `active` (trading), `closed` (trading has ended, outcome not yet published), `resolved` (settled with a known outcome), `expired` (ended long ago and never settled by the venue), or `unknown` (the venue reported no status we recognize)."},"open_time":{"type":["string","null"],"format":"date-time","description":"When the market opened for trading on the venue. Static once set, and absent for venues that do not report an open time."},"end_date":{"type":["string","null"],"format":"date-time","description":"When trading closes on the venue. This is not the settlement time; a market can sit in `closed` for a while before it resolves, so see `expiration_date` for the expected settlement."},"expiration_date":{"type":["string","null"],"format":"date-time","description":"Expected settlement time as published by the venue. Distinct from `end_date`, which is when trading closes; a market sits between the two while awaiting its outcome."},"link":{"type":["string","null"],"description":"URL of the venue's public page for this contract, which on both venues is the parent event page rather than a single strike. Null when no working URL can be built, which happens for Kalshi markets whose series is unknown."},"category":{"type":["string","null"],"description":"Topic category of this market's parent event, normalized across venues (for example `Politics`, `Sports`, `Crypto`). Every market under the same event shares it."},"state_code":{"type":["string","null"],"description":"Two-letter US state code parsed from the ticker when the contract is tied to a state (Senate, Governor, House). Absent for contracts with no state, including Mayoral markets, which carry `city_code` instead."},"city_code":{"type":["string","null"],"description":"Mayoral city code parsed at ingest; present for Mayoral markets, absent otherwise."},"market_type":{"type":["string","null"],"description":"The venue's own contract-type label (for example a binary or scalar market). Static contract metadata, absent when the venue reports none."},"rules_primary":{"type":["string","null"],"description":"The venue's primary settlement rules text, describing what resolves the contract YES."},"rules_secondary":{"type":["string","null"],"description":"Additional settlement rules text from the venue, covering edge cases and sourcing. Frequently absent."},"yes_sub_title":{"type":["string","null"],"description":"Short label for the YES leg as the venue words it, suitable for a button or leg header."},"no_sub_title":{"type":["string","null"],"description":"Short label for the NO leg as the venue words it, suitable for a button or leg header."},"settlement":{"type":["object","null"],"description":"Resolution provenance, platform-agnostic (Kalshi series object / Polymarket resolution_source).","properties":{"sources":{"type":"array","items":{"type":"object","properties":{"name":{"type":["string","null"]},"url":{"type":["string","null"]}}}},"terms_url":{"type":["string","null"]}}},"result":{"type":["string","null"],"description":"Resolution outcome reported by the venue: `yes` or `no`. Absent while the market is open, and for markets that settle to a scalar value or without a per-market yes/no outcome. When set, `probability` is the settlement value (100 or 0)."},"stats":{"description":"Trailing returns and risk statistics computed from the market's daily trade-price series over roughly the trailing 400 days. The values are null individually when the series is too short for that window.","allOf":[{"type":"object","properties":{"trailing_returns":{"type":"array","description":"Percent price change over each of six fixed trailing windows: 1D, 1W, 1M, 3M, YTD, and 1Y.","items":{"type":"object","required":["label"],"properties":{"label":{"type":"string","description":"The trailing window this return covers: `1D`, `1W`, `1M`, `3M`, `YTD`, or `1Y`."},"value":{"type":["number","null"],"description":"Percent change from the value at the start of the window to the latest value in the series. Null when the series has no data point close enough to the start of that window."},"point_change":{"type":["number","null"],"description":"Absolute change in the level's own units over the same window. Point-quoted indices (quote_convention `points`) express trailing performance with this figure; omitted when no comparable historical point exists."}}}},"risk":{"type":"object","description":"Volatility, range, and period return computed over the most recent 31 points of the daily series. The window counts data points, so a series with gaps spans more than 31 calendar days.","properties":{"volatility":{"type":["number","null"],"description":"Annualized volatility in percent, from the daily returns across the most recent 31 daily data points, annualized over 365 days because these markets trade every calendar day. Null when the daily series has fewer than 3 points."},"daily_vol":{"type":["number","null"],"description":"Standard deviation of the daily returns across the most recent 31 daily data points, in percent and not annualized. Null when the daily series has fewer than 3 points."},"range_high":{"type":["number","null"],"description":"Highest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"range_low":{"type":["number","null"],"description":"Lowest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"return_pct":{"type":["number","null"],"description":"Percent change from the first to the last of the most recent 31 daily data points. Null when the daily series has fewer than 3 points."}}}}}],"nullable":true}}},"example":{"market_id":"kalshi:KXPRESPARTY-2028-D","ticker":"KXPRESPARTY-2028-D","display_ticker":"KXPRESPARTY-2028-D","platform":"kalshi","question":"Will Democratic win the Presidency in 2028?","probability":58,"volume":233444.98,"volume_unit":"contracts","volume_24h":14.2,"volume_24h_unit":"contracts","open_interest":116538.21,"open_interest_unit":"contracts","yes_bid":57,"yes_ask":58,"no_bid":42,"no_ask":43,"event_ticker":"KXPRESPARTY-2028","status":"active","open_time":"2024-11-06T15:00:00Z","end_date":"2029-11-07T15:00:00Z","expiration_date":"2029-01-21T15:00:00Z","link":"https://kalshi.com/markets/kxpresparty/kxpresparty-2028","category":"Elections","market_type":"binary"},"examples":[{"name":"default","value":{"market_id":"kalshi:KXPRESPARTY-2028-D","ticker":"KXPRESPARTY-2028-D","display_ticker":"KXPRESPARTY-2028-D","platform":"kalshi","question":"Will Democratic win the Presidency in 2028?","probability":58,"volume":233444.98,"volume_unit":"contracts","volume_24h":14.2,"volume_24h_unit":"contracts","open_interest":116538.21,"open_interest_unit":"contracts","yes_bid":57,"yes_ask":58,"no_bid":42,"no_ask":43,"event_ticker":"KXPRESPARTY-2028","status":"active","open_time":"2024-11-06T15:00:00Z","end_date":"2029-11-07T15:00:00Z","expiration_date":"2029-01-21T15:00:00Z","link":"https://kalshi.com/markets/kxpresparty/kxpresparty-2028","category":"Elections","market_type":"binary"}}]},{"status":"404","description":"Market not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get public market price history
url: "https://docs.adjacent.markets/api/get-api-v1-public-markets-id-prices.md"
description: Delayed market price series in cents (0-100).
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/markets/<id>/prices"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "timestamp": "2026-07-29T02:04:00Z",
          "price": 58
        },
        {
          "timestamp": "2026-07-28T04:00:00Z",
          "price": 58
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 2,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/markets/{id}/prices","summary":"Get public market price history","description":"Delayed market price series in cents (0-100).","parameters":[{"name":"id","in":"path","required":true,"description":"Prefixed market_id.","schema":{"type":"string"}},{"name":"interval","in":"query","required":false,"description":"1hour (30d window) or 1d (90d window).","schema":{"type":"string","enum":["1hour","1d"],"default":"1hour"}},{"name":"per_page","in":"query","required":false,"description":"Rows returned in this response (1-1000).","schema":{"type":"integer","default":1000,"minimum":1,"maximum":1000}},{"name":"start","in":"query","required":false,"description":"Optional ISO-8601 or YYYY-MM-DD lower bound, clipped to the contract window.","schema":{"type":"string"}},{"name":"end","in":"query","required":false,"description":"Optional ISO-8601 or YYYY-MM-DD upper bound; defaults to the snapshot pin.","schema":{"type":"string"}},{"name":"order","in":"query","required":false,"description":"Sort direction.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}],"responses":[{"status":"200","description":"Price points","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"Start of the aggregation bucket this point covers, in UTC. Daily buckets are anchored to midnight US Eastern, so a `1d` point's timestamp is 04:00 or 05:00 UTC depending on daylight saving."},"price":{"type":"number","description":"Value of the series for this bucket: the last price recorded within it. Equals `ohlc.close` on the same point where OHLC is returned, and is the same statistic the `previous_close_*` baselines are measured against. The scale is 0-100 for market and rate series, and the index level (roughly 50-150) for index series."},"price_raw":{"type":["number","null"],"description":"Not currently reachable on any tier, and always absent. The unsmoothed value exists only on the un-bucketed series, but every accepted interval (and the default) maps to a bucketed one, so no request can return it."},"volume":{"type":["number","null"],"description":"Not currently populated on any price series, on any tier, and always absent. Reserved: use the market volume fields for traded volume."},"ohlc":{"description":"Open, high, low and close for the bucket, on the same 0-100 scale as `price`. Returned on the market and rate price series only (index series omit it), and on a daily series a gap-filled day repeats the previous day's values rather than reporting new trading.","allOf":[{"type":"object","required":["open","high","low","close"],"properties":{"open":{"type":"number","description":"Price of the first trade in the bucket, in cents (0-100)."},"high":{"type":"number","description":"Highest traded price in the bucket, in cents (0-100)."},"low":{"type":"number","description":"Lowest traded price in the bucket, in cents (0-100)."},"close":{"type":"number","description":"Price of the last trade in the bucket, in cents (0-100). The same value the point's `price` field carries."}}}],"nullable":true},"spread":{"type":["number","null"],"description":"Dispersion across the source markets behind a reference-rate value: the highest source price minus the lowest, in the same 0-100 points as `price`. Meaningful only on rate series, and currently not populated on any price-series response, so it is always absent."},"sources":{"type":["object","null"],"description":"Provenance for a reference-rate value: the blending method used, plus the per-source prices and weights behind it. Currently not populated on any price-series response, so it is always absent; use `constituents` for the per-source breakdown.","additionalProperties":true},"constituents":{"type":["array","null"],"description":"The source markets behind a reference-rate value at this timestamp, each with its probability (0-100) and its weight renormalized to sum to 1 across the markets listed. Returned on the authenticated rate price series only, covering markets that were active at the timestamp and traded in that bucket; pass `sources=false` to omit it.","items":{"type":"object","properties":{"market_id":{"type":"string"},"price":{"type":"number"},"weight":{"type":"number"}}}}}}},"meta":{"allOf":[{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}]}}},"example":{"data":[{"timestamp":"2026-07-29T02:04:00Z","price":58},{"timestamp":"2026-07-28T04:00:00Z","price":58}],"meta":{"total":2,"page":1,"per_page":2,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"timestamp":"2026-07-29T02:04:00Z","price":58},{"timestamp":"2026-07-28T04:00:00Z","price":58}],"meta":{"total":2,"page":1,"per_page":2,"total_pages":1,"has_next":false,"has_prev":false}}}]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get snapshot metadata
url: "https://docs.adjacent.markets/api/get-api-v1-public-meta.md"
description: "Returns the pinned snapshot timestamp, last refresh time, and the daily-bucket timezone for the public snapshot tier."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/meta"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "snapshot_at": "2026-07-29T14:02:34.885595Z",
      "refreshed_at": "2026-07-29T14:17:34.885595Z",
      "day_boundary_timezone": "America/New_York",
      "market_statuses": [
        "unknown",
        "active",
        "closed",
        "resolved",
        "expired"
      ],
      "market_platforms": [
        "kalshi",
        "polymarket"
      ],
      "market_categories": [
        "Politics",
        "Elections",
        "World",
        "Economics",
        "Crypto"
      ],
      "freshness": [
        {
          "tier": "markets",
          "mode": "delayed",
          "delay_seconds": 900
        },
        {
          "tier": "indices",
          "mode": "delayed",
          "delay_seconds": 900
        }
      ]
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/meta","summary":"Get snapshot metadata","description":"Returns the pinned snapshot timestamp, last refresh time, and the daily-bucket timezone for the public snapshot tier.","parameters":[],"responses":[{"status":"200","description":"Snapshot metadata","schema":{"type":"object","required":["snapshot_at","refreshed_at","day_boundary_timezone","market_statuses","market_platforms","market_categories","freshness"],"properties":{"snapshot_at":{"type":"string","format":"date-time","description":"The pinned snapshot timestamp (≈ now - 15 minutes)."},"refreshed_at":{"type":"string","format":"date-time","description":"Wall-clock time at which the public snapshot was last rebuilt. It tells you how recently the rebuild ran, not how recent the data is: the data cutoff is `snapshot_at`, which each rebuild pins roughly 15 minutes earlier."},"day_boundary_timezone":{"type":"string","description":"IANA tz that daily buckets align to (America/New_York)."},"market_statuses":{"type":"array","description":"Valid market status values.","items":{"type":"string"}},"market_platforms":{"type":"array","description":"Distinct platforms present in the catalog.","items":{"type":"string"}},"market_categories":{"type":"array","description":"Distinct event categories present in the catalog.","items":{"type":"string"}},"freshness":{"type":"array","description":"Per-tier list freshness. Every tier is delayed: prices are pinned about 15 minutes behind live at the snapshot_at cutoff. Time-series and price reads are as-of snapshot_at for every tier; single-market detail is live. Related-news reads are not listed here: they are live queries whose articles are at least 24 hours old.","items":{"type":"object","properties":{"tier":{"type":"string","description":"markets, events, indices, or rates."},"mode":{"type":"string","description":"delayed: prices are pinned behind live. Every tier is delayed."},"delay_seconds":{"type":"integer","description":"Maximum normal delay from live data, in seconds."}}}}}},"example":{"snapshot_at":"2026-07-29T14:02:34.885595Z","refreshed_at":"2026-07-29T14:17:34.885595Z","day_boundary_timezone":"America/New_York","market_statuses":["unknown","active","closed","resolved","expired"],"market_platforms":["kalshi","polymarket"],"market_categories":["Politics","Elections","World","Economics","Crypto"],"freshness":[{"tier":"markets","mode":"delayed","delay_seconds":900},{"tier":"indices","mode":"delayed","delay_seconds":900}]},"examples":[{"name":"default","value":{"snapshot_at":"2026-07-29T14:02:34.885595Z","refreshed_at":"2026-07-29T14:17:34.885595Z","day_boundary_timezone":"America/New_York","market_statuses":["unknown","active","closed","resolved","expired"],"market_platforms":["kalshi","polymarket"],"market_categories":["Politics","Elections","World","Economics","Crypto"],"freshness":[{"tier":"markets","mode":"delayed","delay_seconds":900},{"tier":"indices","mode":"delayed","delay_seconds":900}]}}]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List purchasable API plans
url: "https://docs.adjacent.markets/api/get-api-v1-public-plans.md"
description: "The purchasable plans, Pro and Premium, with their monthly price, seat count, and per-minute and per-day request ceilings."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/plans"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "id": "pro",
          "monthly_price_usd": 50,
          "seats": 5,
          "rpm": 30,
          "daily": 20000
        },
        {
          "id": "premium",
          "monthly_price_usd": 250,
          "seats": 10,
          "rpm": 180,
          "daily": 150000
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 2,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/plans","summary":"List purchasable API plans","description":"The purchasable plans, Pro and Premium, with their monthly price, seat count, and per-minute and per-day request ceilings.","parameters":[],"responses":[{"status":"200","description":"Purchasable plan catalog","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","required":["id","monthly_price_usd","seats","rpm","daily"],"properties":{"id":{"type":"string","description":"Plan identifier: `pro` or `premium`.","enum":["pro","premium"]},"monthly_price_usd":{"type":"integer","description":"Plan price in whole US dollars per month.","minimum":0},"seats":{"type":"integer","description":"Number of member seats the plan includes.","minimum":0},"rpm":{"type":"integer","description":"Requests per minute allowed on the plan.","minimum":0},"daily":{"type":"integer","description":"Requests per day allowed on the plan.","minimum":0}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"id":"pro","monthly_price_usd":50,"seats":5,"rpm":30,"daily":20000},{"id":"premium","monthly_price_usd":250,"seats":10,"rpm":180,"daily":150000}],"meta":{"total":2,"page":1,"per_page":2,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"id":"pro","monthly_price_usd":50,"seats":5,"rpm":30,"daily":20000},{"id":"premium","monthly_price_usd":250,"seats":10,"rpm":180,"daily":150000}],"meta":{"total":2,"page":1,"per_page":2,"total_pages":1,"has_next":false,"has_prev":false}}}]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List public reference rates
url: "https://docs.adjacent.markets/api/get-api-v1-public-rates.md"
description: "Returns the {data, meta} envelope."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/rates"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "rate_id": "adj_bluh",
          "name": "Democratic House",
          "methodology": "simple_average",
          "sources_count": 1,
          "latest_price": 83.5,
          "previous_close_1d": 83.5,
          "price_change_1d": 0,
          "spread": 0,
          "sources": [
            {
              "market_id": "kalshi:CONTROLH-2026-D",
              "display_ticker": "CONTROLH-2026-D",
              "platform": "kalshi",
              "weight": 1,
              "question": "Will Democrats win the House in 2026?",
              "latest_price": 83.5,
              "end_date": "2027-02-01T15:00:00Z",
              "is_active": true
            }
          ]
        }
      ],
      "meta": {
        "total": 8,
        "page": 1,
        "per_page": 1,
        "total_pages": 8,
        "has_next": true,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/rates","summary":"List public reference rates","description":"Returns the `{data, meta}` envelope.","parameters":[],"responses":[{"status":"200","description":"Rate summaries. A rate whose every source is inactive (`is_active` is false) is omitted. A rate with no sources yet is still listed.","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"rate_id":{"type":"string","description":"Stable identifier for the reference rate (for example `adj_redp`). Use it as the `{id}` path parameter on the rate detail and price endpoints."},"name":{"type":"string","description":"Full display name of the reference rate."},"methodology":{"type":"string","description":"How the rate blends its source market prices into a single value: `volume_weighted_average`, `simple_average`, or `median`."},"sources_count":{"type":"integer","description":"Number of source markets configured for this rate. When `sources` is present, that array includes every configured market even if it did not enter the latest print, so its length can differ from this count."},"latest_price":{"type":["number","null"],"description":"Most recent rate value on the 0-100 scale, where 52.4 means 52.4 percent. Null when the rate has never been computed, or when its last print is older than seven days. On the authenticated list, the window is `start`/`end` (`start` defaults to seven days ago)."},"spread":{"type":["number","null"],"description":"Dispersion across the rate's source markets at the latest computed value: the highest source price minus the lowest, in points on the 0-100 scale. This is a measure of source disagreement, not a bid/ask spread. Null under the same window as `latest_price`."},"previous_close_1d":{"type":["number","null"],"description":"The rate value at the previous daily close, meaning the last completed daily close before the current day in US Eastern time, not a rolling 24-hour window."},"price_change_1d":{"type":["number","null"],"description":"Absolute 1-day change in points on the 0-100 scale (latest_price minus previous_close_1d), measured against the previous completed ET daily close. Omitted when there is no prior daily close."},"sources":{"type":"array","description":"Source markets feeding the rate. Returned by GET /api/v1/public/rates so clients can resolve a market's rates in one call; absent on the authenticated paginated list.","items":{"type":"object","properties":{"market_id":{"type":"string","description":"Identifier of the source market, prefixed with its venue (for example `kalshi:KXPRESPARTY-2028-R`). Use it to look the market up on the markets endpoints."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"Venue the source market trades on, lowercase: `kalshi` or `polymarket`. Identical on both tiers."},"weight":{"type":"number","description":"This market's share of the rate value at the latest computed value, as a fraction. Weights across sources that entered that print are normalized to sum to 1. A configured source that did not enter the print still appears, with its catalog weight and no `latest_price`."},"question":{"type":["string","null"],"description":"The source market's question text. Omitted when no question is available for the market."},"latest_price":{"type":["number","null"],"description":"The source market's price as it entered the latest computed rate value, on the 0-100 scale. This is the price the rate actually used, which can lag the market's current price."},"end_date":{"type":["string","null"],"format":"date-time","description":"When the source market's contract expires or settles. Omitted when the market has no end date."},"is_active":{"type":["boolean","null"],"description":"Whether the source market's contract is still open, derived from `end_date` at read time. A source with no end date is open-ended and reports true. Identical on both tiers."}}}}}}},"meta":{"allOf":[{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}]}}},"example":{"data":[{"rate_id":"adj_bluh","name":"Democratic House","methodology":"simple_average","sources_count":1,"latest_price":83.5,"previous_close_1d":83.5,"price_change_1d":0,"spread":0,"sources":[{"market_id":"kalshi:CONTROLH-2026-D","display_ticker":"CONTROLH-2026-D","platform":"kalshi","weight":1,"question":"Will Democrats win the House in 2026?","latest_price":83.5,"end_date":"2027-02-01T15:00:00Z","is_active":true}]}],"meta":{"total":8,"page":1,"per_page":1,"total_pages":8,"has_next":true,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"rate_id":"adj_bluh","name":"Democratic House","methodology":"simple_average","sources_count":1,"latest_price":83.5,"previous_close_1d":83.5,"price_change_1d":0,"spread":0,"sources":[{"market_id":"kalshi:CONTROLH-2026-D","display_ticker":"CONTROLH-2026-D","platform":"kalshi","weight":1,"question":"Will Democrats win the House in 2026?","latest_price":83.5,"end_date":"2027-02-01T15:00:00Z","is_active":true}]}],"meta":{"total":8,"page":1,"per_page":1,"total_pages":8,"has_next":true,"has_prev":false}}}]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get public reference rate detail
url: "https://docs.adjacent.markets/api/get-api-v1-public-rates-id.md"
description: Get public reference rate detail
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/rates/<id>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "rate_id": "adj_bluh",
      "name": "Democratic House",
      "description": "Rolling rate from contract chain 'bluh_chain'",
      "methodology": "simple_average",
      "sources": [
        {
          "market_id": "kalshi:CONTROLH-2026-D",
          "display_ticker": "CONTROLH-2026-D",
          "platform": "kalshi",
          "weight": 1,
          "question": "Will Democrats win the House in 2026?",
          "latest_price": 83.5,
          "end_date": "2027-02-01T15:00:00Z",
          "is_active": true
        }
      ],
      "latest_price": 83.5,
      "price_change_1d": 0,
      "price_change_7d": 1,
      "previous_close_1d": 83.5,
      "previous_close_7d": 82.5,
      "spread": 0,
      "stats": {
        "trailing_returns": [
          {
            "label": "1D",
            "value": 0
          },
          {
            "label": "1W",
            "value": 1.2121212121212122
          }
        ]
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/rates/{id}","summary":"Get public reference rate detail","parameters":[{"name":"id","in":"path","required":true,"description":"Rate ID.","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Rate detail","schema":{"type":"object","properties":{"rate_id":{"type":"string","description":"Stable identifier for the reference rate (for example `adj_redp`). Use it as the `{id}` path parameter on the rate detail and price endpoints."},"name":{"type":"string","description":"Full display name of the reference rate."},"description":{"type":["string","null"],"description":"Free-text description of the rate. Omitted for rates created without one."},"methodology":{"type":"string","description":"How the rate blends its source market prices into a single value: `volume_weighted_average`, `simple_average`, or `median`."},"sources":{"type":"array","description":"Source markets for this rate: legs that entered the latest computed value, plus configured markets the print omitted. Ordered by descending weight. A source that did not enter the print has no `latest_price`. Empty when the rate has no configured sources and has never been computed.","items":{"type":"object","properties":{"market_id":{"type":"string","description":"Identifier of the source market, prefixed with its venue (for example `kalshi:KXPRESPARTY-2028-R`). Use it to look the market up on the markets endpoints."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"Venue the source market trades on, lowercase: `kalshi` or `polymarket`. Identical on both tiers."},"weight":{"type":"number","description":"This market's share of the rate value at the latest computed value, as a fraction. Weights across sources that entered that print are normalized to sum to 1. A configured source that did not enter the print still appears, with its catalog weight and no `latest_price`."},"question":{"type":["string","null"],"description":"The source market's question text. Omitted when no question is available for the market."},"latest_price":{"type":["number","null"],"description":"The source market's price as it entered the latest computed rate value, on the 0-100 scale. This is the price the rate actually used, which can lag the market's current price."},"end_date":{"type":["string","null"],"format":"date-time","description":"When the source market's contract expires or settles. Omitted when the market has no end date."},"is_active":{"type":["boolean","null"],"description":"Whether the source market's contract is still open, derived from `end_date` at read time. A source with no end date is open-ended and reports true. Identical on both tiers."}}}},"latest_price":{"type":["number","null"],"description":"Most recent rate value on the 0-100 scale, where 52.4 means 52.4 percent. Null when the rate has never been computed, or when its last print is older than seven days (below now on the authenticated detail, below the public snapshot pin on the public detail)."},"spread":{"type":["number","null"],"description":"Dispersion across the rate's source markets at the latest computed value: the highest source price minus the lowest, in points on the 0-100 scale. This is a measure of source disagreement, not a bid/ask spread. Null under the same window as `latest_price`."},"price_change_1d":{"type":["number","null"],"description":"Absolute change in points on the 0-100 scale (not a percent) from the previous daily close to `latest_price`. The baseline is the last completed daily close before the current day in US Eastern time, not a rolling 24-hour window."},"price_change_7d":{"type":["number","null"],"description":"Absolute change in points on the 0-100 scale (not a percent) from the daily close seven days before the current day in US Eastern time to `latest_price`. Null when the rate has no daily close that far back."},"previous_close_1d":{"type":["number","null"],"description":"The rate value at the previous daily close, meaning the last completed daily close before the current day in US Eastern time, not a rolling 24-hour window. Returned by `GET /api/v1/public/rates/{id}`; omitted on `GET /api/v1/rates/{id}`."},"previous_close_7d":{"type":["number","null"],"description":"The rate value at the daily close seven days before the current day in US Eastern time, the baseline `price_change_7d` is measured against. Returned by `GET /api/v1/public/rates/{id}`; omitted on `GET /api/v1/rates/{id}`."},"stats":{"description":"Trailing returns and risk statistics computed from the rate's daily close series over roughly the trailing 400 days. Returned by `GET /api/v1/public/rates/{id}` only; always omitted on `GET /api/v1/rates/{id}`.","allOf":[{"type":"object","properties":{"trailing_returns":{"type":"array","description":"Percent price change over each of six fixed trailing windows: 1D, 1W, 1M, 3M, YTD, and 1Y.","items":{"type":"object","required":["label"],"properties":{"label":{"type":"string","description":"The trailing window this return covers: `1D`, `1W`, `1M`, `3M`, `YTD`, or `1Y`."},"value":{"type":["number","null"],"description":"Percent change from the value at the start of the window to the latest value in the series. Null when the series has no data point close enough to the start of that window."},"point_change":{"type":["number","null"],"description":"Absolute change in the level's own units over the same window. Point-quoted indices (quote_convention `points`) express trailing performance with this figure; omitted when no comparable historical point exists."}}}},"risk":{"type":"object","description":"Volatility, range, and period return computed over the most recent 31 points of the daily series. The window counts data points, so a series with gaps spans more than 31 calendar days.","properties":{"volatility":{"type":["number","null"],"description":"Annualized volatility in percent, from the daily returns across the most recent 31 daily data points, annualized over 365 days because these markets trade every calendar day. Null when the daily series has fewer than 3 points."},"daily_vol":{"type":["number","null"],"description":"Standard deviation of the daily returns across the most recent 31 daily data points, in percent and not annualized. Null when the daily series has fewer than 3 points."},"range_high":{"type":["number","null"],"description":"Highest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"range_low":{"type":["number","null"],"description":"Lowest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"return_pct":{"type":["number","null"],"description":"Percent change from the first to the last of the most recent 31 daily data points. Null when the daily series has fewer than 3 points."}}}}}],"nullable":true}}},"example":{"rate_id":"adj_bluh","name":"Democratic House","description":"Rolling rate from contract chain 'bluh_chain'","methodology":"simple_average","sources":[{"market_id":"kalshi:CONTROLH-2026-D","display_ticker":"CONTROLH-2026-D","platform":"kalshi","weight":1,"question":"Will Democrats win the House in 2026?","latest_price":83.5,"end_date":"2027-02-01T15:00:00Z","is_active":true}],"latest_price":83.5,"price_change_1d":0,"price_change_7d":1,"previous_close_1d":83.5,"previous_close_7d":82.5,"spread":0,"stats":{"trailing_returns":[{"label":"1D","value":0},{"label":"1W","value":1.2121212121212122}]}},"examples":[{"name":"default","value":{"rate_id":"adj_bluh","name":"Democratic House","description":"Rolling rate from contract chain 'bluh_chain'","methodology":"simple_average","sources":[{"market_id":"kalshi:CONTROLH-2026-D","display_ticker":"CONTROLH-2026-D","platform":"kalshi","weight":1,"question":"Will Democrats win the House in 2026?","latest_price":83.5,"end_date":"2027-02-01T15:00:00Z","is_active":true}],"latest_price":83.5,"price_change_1d":0,"price_change_7d":1,"previous_close_1d":83.5,"previous_close_7d":82.5,"spread":0,"stats":{"trailing_returns":[{"label":"1D","value":0},{"label":"1W","value":1.2121212121212122}]}}}]},{"status":"404","description":"Rate not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get public reference rate price history
url: "https://docs.adjacent.markets/api/get-api-v1-public-rates-id-prices.md"
description: Delayed rate price series.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/rates/<id>/prices"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "timestamp": "2026-07-29T14:04:00Z",
          "price": 83.5
        },
        {
          "timestamp": "2026-07-28T04:00:00Z",
          "price": 83.5
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 2,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/rates/{id}/prices","summary":"Get public reference rate price history","description":"Delayed rate price series.","parameters":[{"name":"id","in":"path","required":true,"description":"Rate ID.","schema":{"type":"string"}},{"name":"interval","in":"query","required":false,"schema":{"type":"string","enum":["1hour","1d"],"default":"1hour"}},{"name":"per_page","in":"query","required":false,"description":"Rows returned in this response (1-1000).","schema":{"type":"integer","default":1000,"minimum":1,"maximum":1000}},{"name":"start","in":"query","required":false,"schema":{"type":"string"}},{"name":"end","in":"query","required":false,"schema":{"type":"string"}},{"name":"order","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}],"responses":[{"status":"200","description":"Price points","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"Start of the aggregation bucket this point covers, in UTC. Daily buckets are anchored to midnight US Eastern, so a `1d` point's timestamp is 04:00 or 05:00 UTC depending on daylight saving."},"price":{"type":"number","description":"Value of the series for this bucket: the last price recorded within it. Equals `ohlc.close` on the same point where OHLC is returned, and is the same statistic the `previous_close_*` baselines are measured against. The scale is 0-100 for market and rate series, and the index level (roughly 50-150) for index series."},"price_raw":{"type":["number","null"],"description":"Not currently reachable on any tier, and always absent. The unsmoothed value exists only on the un-bucketed series, but every accepted interval (and the default) maps to a bucketed one, so no request can return it."},"volume":{"type":["number","null"],"description":"Not currently populated on any price series, on any tier, and always absent. Reserved: use the market volume fields for traded volume."},"ohlc":{"description":"Open, high, low and close for the bucket, on the same 0-100 scale as `price`. Returned on the market and rate price series only (index series omit it), and on a daily series a gap-filled day repeats the previous day's values rather than reporting new trading.","allOf":[{"type":"object","required":["open","high","low","close"],"properties":{"open":{"type":"number","description":"Price of the first trade in the bucket, in cents (0-100)."},"high":{"type":"number","description":"Highest traded price in the bucket, in cents (0-100)."},"low":{"type":"number","description":"Lowest traded price in the bucket, in cents (0-100)."},"close":{"type":"number","description":"Price of the last trade in the bucket, in cents (0-100). The same value the point's `price` field carries."}}}],"nullable":true},"spread":{"type":["number","null"],"description":"Dispersion across the source markets behind a reference-rate value: the highest source price minus the lowest, in the same 0-100 points as `price`. Meaningful only on rate series, and currently not populated on any price-series response, so it is always absent."},"sources":{"type":["object","null"],"description":"Provenance for a reference-rate value: the blending method used, plus the per-source prices and weights behind it. Currently not populated on any price-series response, so it is always absent; use `constituents` for the per-source breakdown.","additionalProperties":true},"constituents":{"type":["array","null"],"description":"The source markets behind a reference-rate value at this timestamp, each with its probability (0-100) and its weight renormalized to sum to 1 across the markets listed. Returned on the authenticated rate price series only, covering markets that were active at the timestamp and traded in that bucket; pass `sources=false` to omit it.","items":{"type":"object","properties":{"market_id":{"type":"string"},"price":{"type":"number"},"weight":{"type":"number"}}}}}}},"meta":{"allOf":[{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}]}}},"example":{"data":[{"timestamp":"2026-07-29T14:04:00Z","price":83.5},{"timestamp":"2026-07-28T04:00:00Z","price":83.5}],"meta":{"total":2,"page":1,"per_page":2,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"timestamp":"2026-07-29T14:04:00Z","price":83.5},{"timestamp":"2026-07-28T04:00:00Z","price":83.5}],"meta":{"total":2,"page":1,"per_page":2,"total_pages":1,"has_next":false,"has_prev":false}}}]},{"status":"400","description":"Invalid interval or bound","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Related news for a market
url: "https://docs.adjacent.markets/api/get-api-v1-public-markets-id-news.md"
description: "Up to 3 related articles, each published at least 24 hours ago, ordered by relevance blended with recency."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/markets/<id>/news"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/markets/{id}/news","summary":"Related news for a market","description":"Up to 3 related articles, each published at least 24 hours ago, ordered by relevance blended with recency.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"per_page","in":"query","required":false,"description":"Articles to return (1-3).","schema":{"type":"integer","default":3,"minimum":1,"maximum":3}}],"responses":[{"status":"200","description":"Related articles","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","required":["article_id","similarity"],"properties":{"article_id":{"type":"string"},"similarity":{"type":"number","format":"double","description":"Cosine similarity of the best embedding match."},"title":{"type":["string","null"]},"url":{"type":["string","null"]},"image_url":{"type":["string","null"]},"published_date":{"type":["string","null"],"format":"date-time"},"source":{"type":["string","null"],"description":"Where the article was published: the publisher's name when known, otherwise the site's hostname."},"via_market_id":{"type":["string","null"],"description":"The market this article matched most closely. Present on index news (the winning constituent market, including a constituent rate's source market) and on rate news when a source market beat the rate itself."},"via_market_question":{"type":["string","null"],"description":"The question text of that market."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]},{"status":"404","description":"Unknown market id","examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Related news for an index
url: "https://docs.adjacent.markets/api/get-api-v1-public-indices-id-news.md"
description: "Related news drawn from the index's constituent markets, ranked by closest market match (viamarketid, viamarketquestion) and relevance blended with recency."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/indices/<id>/news"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/indices/{id}/news","summary":"Related news for an index","description":"Related news drawn from the index's constituent markets, ranked by closest market match (via_market_id, via_market_question) and relevance blended with recency.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"per_page","in":"query","required":false,"description":"Articles to return (1-3).","schema":{"type":"integer","default":3,"minimum":1,"maximum":3}}],"responses":[{"status":"200","description":"Related articles","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","required":["article_id","similarity"],"properties":{"article_id":{"type":"string"},"similarity":{"type":"number","format":"double","description":"Cosine similarity of the best embedding match."},"title":{"type":["string","null"]},"url":{"type":["string","null"]},"image_url":{"type":["string","null"]},"published_date":{"type":["string","null"],"format":"date-time"},"source":{"type":["string","null"],"description":"Where the article was published: the publisher's name when known, otherwise the site's hostname."},"via_market_id":{"type":["string","null"],"description":"The market this article matched most closely. Present on index news (the winning constituent market, including a constituent rate's source market) and on rate news when a source market beat the rate itself."},"via_market_question":{"type":["string","null"],"description":"The question text of that market."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]},{"status":"404","description":"Unknown index id","examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Related news for a reference rate
url: "https://docs.adjacent.markets/api/get-api-v1-public-rates-id-news.md"
description: "Up to 3 related articles, each published at least 24 hours ago, ordered by relevance blended with recency."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/rates/<id>/news"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/rates/{id}/news","summary":"Related news for a reference rate","description":"Up to 3 related articles, each published at least 24 hours ago, ordered by relevance blended with recency.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"per_page","in":"query","required":false,"description":"Articles to return (1-3).","schema":{"type":"integer","default":3,"minimum":1,"maximum":3}}],"responses":[{"status":"200","description":"Related articles","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","required":["article_id","similarity"],"properties":{"article_id":{"type":"string"},"similarity":{"type":"number","format":"double","description":"Cosine similarity of the best embedding match."},"title":{"type":["string","null"]},"url":{"type":["string","null"]},"image_url":{"type":["string","null"]},"published_date":{"type":["string","null"],"format":"date-time"},"source":{"type":["string","null"],"description":"Where the article was published: the publisher's name when known, otherwise the site's hostname."},"via_market_id":{"type":["string","null"],"description":"The market this article matched most closely. Present on index news (the winning constituent market, including a constituent rate's source market) and on rate news when a source market beat the rate itself."},"via_market_question":{"type":["string","null"],"description":"The question text of that market."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]},{"status":"404","description":"Unknown rate id","examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get official daily values
url: "https://docs.adjacent.markets/api/get-api-v1-public-indices-id-daily-values.md"
description: "Official daily values for an index whose family publishes one, newest first. The NFL team indices stamp one official value per US-Eastern calendar day, taken from a fixed morning window; days without "
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/indices/<id>/daily-values"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/indices/{id}/daily-values","summary":"Get official daily values","description":"Official daily values for an index whose family publishes one, newest first. The NFL team indices stamp one official value per US-Eastern calendar day, taken from a fixed morning window; days without a stamped value have no row, and official values begin accruing when the index goes live. Indices without a daily-value rule return an empty list. Returns the `{data, meta}` envelope. Not paginated: `meta.total` counts the rows in this response and `has_next` is always false. Values are at least 15 minutes delayed on this tier.","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g. `seatr_kalshi` or `SEATR`.","schema":{"type":"string"}},{"name":"from","in":"query","required":false,"description":"Inclusive lower bound on the US-Eastern calendar day (YYYY-MM-DD).","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"description":"Inclusive upper bound on the US-Eastern calendar day (YYYY-MM-DD).","schema":{"type":"string","format":"date"}},{"name":"per_page","in":"query","required":false,"description":"Rows returned in this response (1-366), newest first.","schema":{"type":"integer","default":90,"minimum":1,"maximum":366}}],"responses":[{"status":"200","description":"Rows, newest first","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","description":"One official daily value: the value stamped for one US-Eastern calendar day.","required":["et_date","value"],"properties":{"et_date":{"type":"string","format":"date","description":"The US-Eastern calendar day the value is official for."},"value":{"type":"number","description":"The official index value for that day, in index points."}}}},"meta":{"allOf":[{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}]}}},"examples":[]},{"status":"400","description":"The `from` date is after the `to` date.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]},{"status":"404","description":"Index not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get membership events
url: "https://docs.adjacent.markets/api/get-api-v1-public-indices-id-membership-events.md"
description: "Recent membership events for an NFL team index, newest first: admissions (a market became its sleeve's active member) and settlements (a member's market resolved and its final value was booked). Indic"
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/indices/<id>/membership-events"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/indices/{id}/membership-events","summary":"Get membership events","description":"Recent membership events for an NFL team index, newest first: admissions (a market became its sleeve's active member) and settlements (a member's market resolved and its final value was booked). Indices without sleeve membership return an empty list. Returns the `{data, meta}` envelope. Not paginated: `meta.total` counts the rows in this response and `has_next` is always false. Values are at least 15 minutes delayed on this tier.","parameters":[{"name":"id","in":"path","required":true,"description":"Index ID or ticker (case-insensitive), e.g. `seatr_kalshi` or `SEATR`.","schema":{"type":"string"}},{"name":"per_page","in":"query","required":false,"description":"Rows returned in this response (1-100), newest first.","schema":{"type":"integer","default":20,"minimum":1,"maximum":100}}],"responses":[{"status":"200","description":"Rows, newest first","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","description":"One membership event of an NFL team index: an admission (a market became its sleeve's active member) or a settlement (a member's market resolved and its final value was booked).","required":["kind","occurred_at","market_id","display_ticker"],"properties":{"kind":{"type":"string","description":"The event type.","enum":["admission","settlement"]},"occurred_at":{"type":"string","format":"date-time","description":"When the event took effect."},"sleeve":{"type":["string","null"],"description":"The sleeve the event belongs to, when resolvable."},"market_id":{"type":"string","description":"The market the event is about."},"display_ticker":{"type":"string","description":"Display label for the market."},"name":{"type":["string","null"],"description":"The market's question. Omitted when the market is unknown."},"settled_price":{"type":["number","null"],"description":"For a settlement, the booked final value (0 or 100). Omitted for admissions."}}}},"meta":{"allOf":[{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}]}}},"examples":[]},{"status":"400","description":"The `from` date is after the `to` date.","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]},{"status":"404","description":"Index not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List reference rates
url: "https://docs.adjacent.markets/api/get-api-v1-rates.md"
description: Get all reference rates with current prices
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/rates" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "rate_id": "adj_bluh",
          "name": "Democratic House",
          "methodology": "simple_average",
          "sources_count": 1,
          "latest_price": 77.5,
          "spread": 0
        },
        {
          "rate_id": "adj_blup",
          "name": "Adjacent Democratic President",
          "methodology": "simple_average",
          "sources_count": 2,
          "latest_price": 58.5,
          "spread": 0
        }
      ],
      "meta": {
        "total": 6,
        "page": 1,
        "per_page": 20,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/rates","summary":"List reference rates","description":"Get all reference rates with current prices","parameters":[{"name":"start","in":"query","description":"Lower bound for the print used as `latest_price` and `spread`. Defaults to seven days before now; a rate with no print in the window returns those fields as null.","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"maximum":500}}],"responses":[{"status":"200","description":"List of rates","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"rate_id":{"type":"string","description":"Stable identifier for the reference rate (for example `adj_redp`). Use it as the `{id}` path parameter on the rate detail and price endpoints."},"name":{"type":"string","description":"Full display name of the reference rate."},"methodology":{"type":"string","description":"How the rate blends its source market prices into a single value: `volume_weighted_average`, `simple_average`, or `median`."},"sources_count":{"type":"integer","description":"Number of source markets configured for this rate. When `sources` is present, that array includes every configured market even if it did not enter the latest print, so its length can differ from this count."},"latest_price":{"type":["number","null"],"description":"Most recent rate value on the 0-100 scale, where 52.4 means 52.4 percent. Null when the rate has never been computed, or when its last print is older than seven days. On the authenticated list, the window is `start`/`end` (`start` defaults to seven days ago)."},"spread":{"type":["number","null"],"description":"Dispersion across the rate's source markets at the latest computed value: the highest source price minus the lowest, in points on the 0-100 scale. This is a measure of source disagreement, not a bid/ask spread. Null under the same window as `latest_price`."},"previous_close_1d":{"type":["number","null"],"description":"The rate value at the previous daily close, meaning the last completed daily close before the current day in US Eastern time, not a rolling 24-hour window."},"price_change_1d":{"type":["number","null"],"description":"Absolute 1-day change in points on the 0-100 scale (latest_price minus previous_close_1d), measured against the previous completed ET daily close. Omitted when there is no prior daily close."},"sources":{"type":"array","description":"Source markets feeding the rate. Returned by GET /api/v1/public/rates so clients can resolve a market's rates in one call; absent on the authenticated paginated list.","items":{"type":"object","properties":{"market_id":{"type":"string","description":"Identifier of the source market, prefixed with its venue (for example `kalshi:KXPRESPARTY-2028-R`). Use it to look the market up on the markets endpoints."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"Venue the source market trades on, lowercase: `kalshi` or `polymarket`. Identical on both tiers."},"weight":{"type":"number","description":"This market's share of the rate value at the latest computed value, as a fraction. Weights across sources that entered that print are normalized to sum to 1. A configured source that did not enter the print still appears, with its catalog weight and no `latest_price`."},"question":{"type":["string","null"],"description":"The source market's question text. Omitted when no question is available for the market."},"latest_price":{"type":["number","null"],"description":"The source market's price as it entered the latest computed rate value, on the 0-100 scale. This is the price the rate actually used, which can lag the market's current price."},"end_date":{"type":["string","null"],"format":"date-time","description":"When the source market's contract expires or settles. Omitted when the market has no end date."},"is_active":{"type":["boolean","null"],"description":"Whether the source market's contract is still open, derived from `end_date` at read time. A source with no end date is open-ended and reports true. Identical on both tiers."}}}}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"rate_id":"adj_bluh","name":"Democratic House","methodology":"simple_average","sources_count":1,"latest_price":77.5,"spread":0},{"rate_id":"adj_blup","name":"Adjacent Democratic President","methodology":"simple_average","sources_count":2,"latest_price":58.5,"spread":0}],"meta":{"total":6,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"rate_id":"adj_bluh","name":"Democratic House","methodology":"simple_average","sources_count":1,"latest_price":77.5,"spread":0},{"rate_id":"adj_blup","name":"Adjacent Democratic President","methodology":"simple_average","sources_count":2,"latest_price":58.5,"spread":0}],"meta":{"total":6,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get reference rate details
url: "https://docs.adjacent.markets/api/get-api-v1-rates-id.md"
description: Get rate with contributing sources
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/rates/<id>" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "rate_id": "adj_bluh",
      "name": "Democratic House",
      "description": "Rolling rate from contract chain 'bluh_chain'",
      "methodology": "simple_average",
      "sources": [
        {
          "market_id": "kalshi:CONTROLH-2026-D",
          "display_ticker": "CONTROLH-2026-D",
          "platform": "kalshi",
          "weight": 1,
          "question": "Will Democrats win the House in 2026?",
          "latest_price": 77.5,
          "end_date": "2027-02-01T15:00:00Z",
          "is_active": true
        }
      ],
      "latest_price": 77.5,
      "spread": 0
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```

    ```json title="404 — default" lines=false
    {
      "error": "not_found",
      "message": "Rate not found"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/rates/{id}","summary":"Get reference rate details","description":"Get rate with contributing sources","parameters":[{"name":"id","in":"path","required":true,"description":"Rate ID","schema":{"type":"string"}}],"responses":[{"status":"200","description":"Rate details","schema":{"type":"object","properties":{"rate_id":{"type":"string","description":"Stable identifier for the reference rate (for example `adj_redp`). Use it as the `{id}` path parameter on the rate detail and price endpoints."},"name":{"type":"string","description":"Full display name of the reference rate."},"description":{"type":["string","null"],"description":"Free-text description of the rate. Omitted for rates created without one."},"methodology":{"type":"string","description":"How the rate blends its source market prices into a single value: `volume_weighted_average`, `simple_average`, or `median`."},"sources":{"type":"array","description":"Source markets for this rate: legs that entered the latest computed value, plus configured markets the print omitted. Ordered by descending weight. A source that did not enter the print has no `latest_price`. Empty when the rate has no configured sources and has never been computed.","items":{"type":"object","properties":{"market_id":{"type":"string","description":"Identifier of the source market, prefixed with its venue (for example `kalshi:KXPRESPARTY-2028-R`). Use it to look the market up on the markets endpoints."},"display_ticker":{"type":"string","description":"Human-readable market label, Polymarket market slug when present, else the raw ticker."},"platform":{"type":"string","description":"Venue the source market trades on, lowercase: `kalshi` or `polymarket`. Identical on both tiers."},"weight":{"type":"number","description":"This market's share of the rate value at the latest computed value, as a fraction. Weights across sources that entered that print are normalized to sum to 1. A configured source that did not enter the print still appears, with its catalog weight and no `latest_price`."},"question":{"type":["string","null"],"description":"The source market's question text. Omitted when no question is available for the market."},"latest_price":{"type":["number","null"],"description":"The source market's price as it entered the latest computed rate value, on the 0-100 scale. This is the price the rate actually used, which can lag the market's current price."},"end_date":{"type":["string","null"],"format":"date-time","description":"When the source market's contract expires or settles. Omitted when the market has no end date."},"is_active":{"type":["boolean","null"],"description":"Whether the source market's contract is still open, derived from `end_date` at read time. A source with no end date is open-ended and reports true. Identical on both tiers."}}}},"latest_price":{"type":["number","null"],"description":"Most recent rate value on the 0-100 scale, where 52.4 means 52.4 percent. Null when the rate has never been computed, or when its last print is older than seven days (below now on the authenticated detail, below the public snapshot pin on the public detail)."},"spread":{"type":["number","null"],"description":"Dispersion across the rate's source markets at the latest computed value: the highest source price minus the lowest, in points on the 0-100 scale. This is a measure of source disagreement, not a bid/ask spread. Null under the same window as `latest_price`."},"price_change_1d":{"type":["number","null"],"description":"Absolute change in points on the 0-100 scale (not a percent) from the previous daily close to `latest_price`. The baseline is the last completed daily close before the current day in US Eastern time, not a rolling 24-hour window."},"price_change_7d":{"type":["number","null"],"description":"Absolute change in points on the 0-100 scale (not a percent) from the daily close seven days before the current day in US Eastern time to `latest_price`. Null when the rate has no daily close that far back."},"previous_close_1d":{"type":["number","null"],"description":"The rate value at the previous daily close, meaning the last completed daily close before the current day in US Eastern time, not a rolling 24-hour window. Returned by `GET /api/v1/public/rates/{id}`; omitted on `GET /api/v1/rates/{id}`."},"previous_close_7d":{"type":["number","null"],"description":"The rate value at the daily close seven days before the current day in US Eastern time, the baseline `price_change_7d` is measured against. Returned by `GET /api/v1/public/rates/{id}`; omitted on `GET /api/v1/rates/{id}`."},"stats":{"description":"Trailing returns and risk statistics computed from the rate's daily close series over roughly the trailing 400 days. Returned by `GET /api/v1/public/rates/{id}` only; always omitted on `GET /api/v1/rates/{id}`.","allOf":[{"type":"object","properties":{"trailing_returns":{"type":"array","description":"Percent price change over each of six fixed trailing windows: 1D, 1W, 1M, 3M, YTD, and 1Y.","items":{"type":"object","required":["label"],"properties":{"label":{"type":"string","description":"The trailing window this return covers: `1D`, `1W`, `1M`, `3M`, `YTD`, or `1Y`."},"value":{"type":["number","null"],"description":"Percent change from the value at the start of the window to the latest value in the series. Null when the series has no data point close enough to the start of that window."},"point_change":{"type":["number","null"],"description":"Absolute change in the level's own units over the same window. Point-quoted indices (quote_convention `points`) express trailing performance with this figure; omitted when no comparable historical point exists."}}}},"risk":{"type":"object","description":"Volatility, range, and period return computed over the most recent 31 points of the daily series. The window counts data points, so a series with gaps spans more than 31 calendar days.","properties":{"volatility":{"type":["number","null"],"description":"Annualized volatility in percent, from the daily returns across the most recent 31 daily data points, annualized over 365 days because these markets trade every calendar day. Null when the daily series has fewer than 3 points."},"daily_vol":{"type":["number","null"],"description":"Standard deviation of the daily returns across the most recent 31 daily data points, in percent and not annualized. Null when the daily series has fewer than 3 points."},"range_high":{"type":["number","null"],"description":"Highest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"range_low":{"type":["number","null"],"description":"Lowest value reached within the most recent 31 daily data points, in the series' own units (index points for an index, 0-100 for a rate). Null when the daily series has fewer than 3 points."},"return_pct":{"type":["number","null"],"description":"Percent change from the first to the last of the most recent 31 daily data points. Null when the daily series has fewer than 3 points."}}}}}],"nullable":true}}},"example":{"rate_id":"adj_bluh","name":"Democratic House","description":"Rolling rate from contract chain 'bluh_chain'","methodology":"simple_average","sources":[{"market_id":"kalshi:CONTROLH-2026-D","display_ticker":"CONTROLH-2026-D","platform":"kalshi","weight":1,"question":"Will Democrats win the House in 2026?","latest_price":77.5,"end_date":"2027-02-01T15:00:00Z","is_active":true}],"latest_price":77.5,"spread":0},"examples":[{"name":"default","value":{"rate_id":"adj_bluh","name":"Democratic House","description":"Rolling rate from contract chain 'bluh_chain'","methodology":"simple_average","sources":[{"market_id":"kalshi:CONTROLH-2026-D","display_ticker":"CONTROLH-2026-D","platform":"kalshi","weight":1,"question":"Will Democrats win the House in 2026?","latest_price":77.5,"end_date":"2027-02-01T15:00:00Z","is_active":true}],"latest_price":77.5,"spread":0}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"404","description":"Rate not found","schema":{"type":"object","properties":{"error":{"type":"string","description":"Stable, machine-readable code identifying the failure; branch on this rather than on `message`. One of `bad_request`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `service_unavailable`, `upstream_error`, `service_error`, or `internal_error`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to a user. For client errors it names the specific problem; for server-side failures it is a generic notice and the underlying detail is deliberately withheld."}}},"example":{"error":"not_found","message":"Rate not found"},"examples":[{"name":"default","value":{"error":"not_found","message":"Rate not found"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Find related news
url: "https://docs.adjacent.markets/api/get-api-v1-rates-id-news.md"
description: "Related news for a reference rate: articles matching the rate itself or any of its source markets, ranked by closest match. viamarketid names the source market when that match wins; it is omitted when"
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/rates/<id>/news" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="default" lines=false
    {
      "data": [
        {
          "article_id": "a1b2c3d4",
          "similarity": 0.82,
          "title": "Senate race tightens in Pennsylvania",
          "url": "https://example.com/news/senate-pa",
          "published_date": "2026-06-01T08:00:00Z",
          "source": "Reuters"
        },
        {
          "article_id": "e5f6g7h8",
          "similarity": 0.77,
          "title": "New polling shifts House outlook",
          "url": "https://example.com/news/house-outlook",
          "published_date": "2026-06-01T07:30:00Z",
          "source": "AP"
        }
      ],
      "meta": {
        "total": 2,
        "page": 1,
        "per_page": 20,
        "total_pages": 1,
        "has_next": false,
        "has_prev": false
      }
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/rates/{id}/news","summary":"Find related news","description":"Related news for a reference rate: articles matching the rate itself or any of its source markets, ranked by closest match. via_market_id names the source market when that match wins; it is omitted when the rate itself matched more closely. Relevance is blended with recency. Use recency_half_life_days to tune the blend; paginated.","parameters":[{"name":"id","in":"path","required":true,"description":"Rate ID","schema":{"type":"string"}},{"name":"min_similarity","in":"query","description":"Minimum cosine similarity a result must reach.","schema":{"type":"number","default":0.38,"minimum":0,"maximum":1}},{"name":"recency_half_life_days","in":"query","description":"Recency half-life in days for the relevance-recency blend applied to the ranking: a result's score is its similarity times 0.5^(age_days / this).","schema":{"type":"number","minimum":0}},{"name":"page","in":"query","description":"Page number","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","description":"Items per page","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":[{"status":"200","description":"Paginated related news articles","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"article_id":{"type":"string"},"similarity":{"type":"number"},"title":{"type":["string","null"]},"url":{"type":["string","null"]},"published_date":{"type":["string","null"],"format":"date-time"},"source":{"type":["string","null"]}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"article_id":"a1b2c3d4","similarity":0.82,"title":"Senate race tightens in Pennsylvania","url":"https://example.com/news/senate-pa","published_date":"2026-06-01T08:00:00Z","source":"Reuters"},{"article_id":"e5f6g7h8","similarity":0.77,"title":"New polling shifts House outlook","url":"https://example.com/news/house-outlook","published_date":"2026-06-01T07:30:00Z","source":"AP"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"article_id":"a1b2c3d4","similarity":0.82,"title":"Senate race tightens in Pennsylvania","url":"https://example.com/news/senate-pa","published_date":"2026-06-01T08:00:00Z","source":"Reuters"},{"article_id":"e5f6g7h8","similarity":0.77,"title":"New polling shifts House outlook","url":"https://example.com/news/house-outlook","published_date":"2026-06-01T07:30:00Z","source":"AP"}],"meta":{"total":2,"page":1,"per_page":20,"total_pages":1,"has_next":false,"has_prev":false}}}]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get rate price history
url: "https://docs.adjacent.markets/api/get-api-v1-rates-id-prices.md"
description: Get historical rate values with OHLC
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/rates/<id>/prices" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>

  <ResponseExample>
    ```json title="200 — default" lines=false
    {
      "data": [
        {
          "timestamp": "2026-06-20T19:00:00Z",
          "price": 77.5
        },
        {
          "timestamp": "2026-06-20T18:00:00Z",
          "price": 77.2
        }
      ],
      "meta": {
        "total": 420,
        "page": 1,
        "per_page": 100,
        "total_pages": 5,
        "has_next": true,
        "has_prev": false
      }
    }
    ```

    ```json title="403 — default" lines=false
    {
      "error": "Insufficient scope: a Pro or Premium API plan is required",
      "status": 403,
      "upgrade_url": "https://adjacent.markets/subscribe"
    }
    ```
  </ResponseExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/rates/{id}/prices","summary":"Get rate price history","description":"Get historical rate values with OHLC","parameters":[{"name":"id","in":"path","required":true,"description":"Rate ID","schema":{"type":"string"}},{"name":"per_page","in":"query","description":"Points per page (1-1000).","schema":{"type":"integer","default":100,"minimum":1,"maximum":1000}},{"name":"start","in":"query","description":"Start time","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","description":"End time","schema":{"type":"string","format":"date-time"}},{"name":"interval","in":"query","description":"Time bucket interval (daily, 1day also accepted as aliases for 1d)","schema":{"type":"string","enum":["1min","5min","1hour","1d"],"default":"5min"}},{"name":"order","in":"query","description":"Sort direction by timestamp","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"page","in":"query","description":"1-based page number.","schema":{"type":"integer","default":1,"minimum":1}},{"name":"sources","in":"query","description":"Include source components in each price point","schema":{"type":"boolean","default":true}}],"responses":[{"status":"200","description":"Paginated price history","schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"Start of the aggregation bucket this point covers, in UTC. Daily buckets are anchored to midnight US Eastern, so a `1d` point's timestamp is 04:00 or 05:00 UTC depending on daylight saving."},"price":{"type":"number","description":"Value of the series for this bucket: the last price recorded within it. Equals `ohlc.close` on the same point where OHLC is returned, and is the same statistic the `previous_close_*` baselines are measured against. The scale is 0-100 for market and rate series, and the index level (roughly 50-150) for index series."},"price_raw":{"type":["number","null"],"description":"Not currently reachable on any tier, and always absent. The unsmoothed value exists only on the un-bucketed series, but every accepted interval (and the default) maps to a bucketed one, so no request can return it."},"volume":{"type":["number","null"],"description":"Not currently populated on any price series, on any tier, and always absent. Reserved: use the market volume fields for traded volume."},"ohlc":{"description":"Open, high, low and close for the bucket, on the same 0-100 scale as `price`. Returned on the market and rate price series only (index series omit it), and on a daily series a gap-filled day repeats the previous day's values rather than reporting new trading.","allOf":[{"type":"object","required":["open","high","low","close"],"properties":{"open":{"type":"number","description":"Price of the first trade in the bucket, in cents (0-100)."},"high":{"type":"number","description":"Highest traded price in the bucket, in cents (0-100)."},"low":{"type":"number","description":"Lowest traded price in the bucket, in cents (0-100)."},"close":{"type":"number","description":"Price of the last trade in the bucket, in cents (0-100). The same value the point's `price` field carries."}}}],"nullable":true},"spread":{"type":["number","null"],"description":"Dispersion across the source markets behind a reference-rate value: the highest source price minus the lowest, in the same 0-100 points as `price`. Meaningful only on rate series, and currently not populated on any price-series response, so it is always absent."},"sources":{"type":["object","null"],"description":"Provenance for a reference-rate value: the blending method used, plus the per-source prices and weights behind it. Currently not populated on any price-series response, so it is always absent; use `constituents` for the per-source breakdown.","additionalProperties":true},"constituents":{"type":["array","null"],"description":"The source markets behind a reference-rate value at this timestamp, each with its probability (0-100) and its weight renormalized to sum to 1 across the markets listed. Returned on the authenticated rate price series only, covering markets that were active at the timestamp and traded in that bucket; pass `sources=false` to omit it.","items":{"type":"object","properties":{"market_id":{"type":"string"},"price":{"type":"number"},"weight":{"type":"number"}}}}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"example":{"data":[{"timestamp":"2026-06-20T19:00:00Z","price":77.5},{"timestamp":"2026-06-20T18:00:00Z","price":77.2}],"meta":{"total":420,"page":1,"per_page":100,"total_pages":5,"has_next":true,"has_prev":false}},"examples":[{"name":"default","value":{"data":[{"timestamp":"2026-06-20T19:00:00Z","price":77.5},{"timestamp":"2026-06-20T18:00:00Z","price":77.2}],"meta":{"total":420,"page":1,"per_page":100,"total_pages":5,"has_next":true,"has_prev":false}}}]},{"status":"403","description":"The organization has no paid plan, so the realtime read scopes are refused. Distinct from a 429, which means a plan's budget ran out: nothing here resets on a timer, and the request succeeds only once the organization holds a plan.","schema":{"type":"object","required":["error","status"],"properties":{"error":{"type":"string","description":"Human-readable reason the request was refused."},"status":{"type":"integer","description":"HTTP status code, repeated in the body."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying access. Absent when no plan is available for purchase."}}},"example":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"},"examples":[{"name":"default","value":{"error":"Insufficient scope: a Pro or Premium API plan is required","status":403,"upgrade_url":"https://adjacent.markets/subscribe"}}]},{"status":"429","description":"The organization's minute or UTC-day request budget is exhausted, or the organization has reached its cap on requests running at the same time (`limit: \"concurrency\"`). Wait `Retry-After` seconds before retrying; for a concurrency 429, reduce parallelism.","schema":{"type":"object","required":["error","limit","message"],"properties":{"error":{"type":"string","description":"Always `rate_limited`. Branch on this to detect a throttled request.","enum":["rate_limited"]},"limit":{"type":"string","description":"Which limit was hit: `rpm` for the per-minute cap, `daily` for the daily one, or `concurrency` for the cap on requests running at the same time.","enum":["rpm","daily","concurrency"]},"message":{"type":"string","description":"Human-readable explanation naming the limit that was exceeded."},"upgrade_url":{"type":"string","format":"uri","description":"Page listing the plans and their request allowances, for buying a larger budget. Absent when no plan is available for purchase."}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List recent industry filings
url: "https://docs.adjacent.markets/api/get-api-v1-public-filings.md"
description: "CFTC industry filings whose status date is in the last 90 days, newest first."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/filings"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/filings","summary":"List recent industry filings","description":"CFTC industry filings whose status date is in the last 90 days, newest first.","parameters":[{"name":"feed","in":"query","schema":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]}},{"name":"org","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","description":"Relevance-ranked text search over the organization, description, product name and type, affected products, and filing id.","schema":{"type":"string"}},{"name":"last_seen_days","in":"query","description":"Only filings not observed on a CFTC listing in this many days.","schema":{"type":"integer","minimum":1}},{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}},{"name":"sort","in":"query","description":"Sort key.","schema":{"type":"string","enum":["status_date","received","first_seen","last_seen","org"],"default":"status_date"}},{"name":"sort_dir","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}],"responses":[{"status":"200","description":"Paged filings","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","required":["id","title","feed","org_code","status","status_date","doc_count"],"properties":{"id":{"type":"integer","format":"int64","description":"CFTC filing id."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"feed":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"org_code":{"type":"string"},"description":{"type":"string","description":"Rules-feed description. Omitted on DCM product and DCO rows; use title."},"product_name":{"type":"string","description":"DCM product name. Omitted on rules and DCO rows; use title."},"product_type":{"type":"string","description":"DCM product type. Omitted on feeds that do not list one."},"category":{"type":"string","description":"DCM product category. Omitted on rules and DCO rows."},"subcategory":{"type":"string","description":"DCM product subcategory. Omitted on rules and DCO rows."},"products_affected":{"type":"string","description":"PTC listing column. CFTC leaves it blank; omitted when empty."},"remarks":{"type":"string","description":"Present on DCO registrations. Omitted when CFTC published none."},"receipt_date":{"type":"string","format":"date","description":"Official receipt date on rules feeds. Omitted on DCM products and DCO rows; CFTC does not publish one there."},"status":{"type":"string"},"status_date":{"type":"string","format":"date"},"doc_count":{"type":"integer"},"predicted_effective_date":{"type":"string","format":"date","description":"Business-day estimate for a pending rules filing that has a receipt date. Omitted once the filing is no longer pending, and on feeds with no receipt date."},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Recent filing filter values
url: "https://docs.adjacent.markets/api/get-api-v1-public-filings-filters.md"
description: "Feeds, organizations, and statuses present among filings from the last 90 days."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/filings/filters"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/filings/filters","summary":"Recent filing filter values","description":"Feeds, organizations, and statuses present among filings from the last 90 days.","parameters":[],"responses":[{"status":"200","description":"The distinct feed, organization, and status values present.","schema":{"type":"object","required":["feeds","orgs","statuses"],"properties":{"feeds":{"type":"array","items":{"type":"string"}},"orgs":{"type":"array","items":{"type":"string"}},"statuses":{"type":"array","items":{"type":"string"}}}},"examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get a recent filing
url: "https://docs.adjacent.markets/api/get-api-v1-public-filings-id.md"
description: One CFTC filing whose status date is in the last 90 days.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/filings/0"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/filings/{id}","summary":"Get a recent filing","description":"One CFTC filing whose status date is in the last 90 days.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":[{"status":"200","description":"Filing","schema":{"type":"object","required":["id","title","feed","org_code","status","status_date","doc_count"],"properties":{"id":{"type":"integer","format":"int64","description":"CFTC filing id."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"feed":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"org_code":{"type":"string"},"description":{"type":"string","description":"Rules-feed description. Omitted on DCM product and DCO rows; use title."},"product_name":{"type":"string","description":"DCM product name. Omitted on rules and DCO rows; use title."},"product_type":{"type":"string","description":"DCM product type. Omitted on feeds that do not list one."},"category":{"type":"string","description":"DCM product category. Omitted on rules and DCO rows."},"subcategory":{"type":"string","description":"DCM product subcategory. Omitted on rules and DCO rows."},"products_affected":{"type":"string","description":"PTC listing column. CFTC leaves it blank; omitted when empty."},"remarks":{"type":"string","description":"Present on DCO registrations. Omitted when CFTC published none."},"receipt_date":{"type":"string","format":"date","description":"Official receipt date on rules feeds. Omitted on DCM products and DCO rows; CFTC does not publish one there."},"status":{"type":"string"},"status_date":{"type":"string","format":"date"},"doc_count":{"type":"integer"},"predicted_effective_date":{"type":"string","format":"date","description":"Business-day estimate for a pending rules filing that has a receipt date. Omitted once the filing is no longer pending, and on feeds with no receipt date."},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}},"examples":[]},{"status":"404","description":"Unknown or older than 90 days","examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Recent filing attachment text
url: "https://docs.adjacent.markets/api/get-api-v1-public-filings-id-markdown.md"
description: The filing plus extracted markdown from each stored attachment.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/public/filings/0/markdown"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/public/filings/{id}/markdown","summary":"Recent filing attachment text","description":"The filing plus extracted markdown from each stored attachment.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":[{"status":"200","description":"Markdown body and attachment list","schema":{"type":"object","required":["filing","markdown","documents","source_url"],"properties":{"filing":{"type":"object","required":["id","title","feed","org_code","status","status_date","doc_count"],"properties":{"id":{"type":"integer","format":"int64","description":"CFTC filing id."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"feed":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"org_code":{"type":"string"},"description":{"type":"string","description":"Rules-feed description. Omitted on DCM product and DCO rows; use title."},"product_name":{"type":"string","description":"DCM product name. Omitted on rules and DCO rows; use title."},"product_type":{"type":"string","description":"DCM product type. Omitted on feeds that do not list one."},"category":{"type":"string","description":"DCM product category. Omitted on rules and DCO rows."},"subcategory":{"type":"string","description":"DCM product subcategory. Omitted on rules and DCO rows."},"products_affected":{"type":"string","description":"PTC listing column. CFTC leaves it blank; omitted when empty."},"remarks":{"type":"string","description":"Present on DCO registrations. Omitted when CFTC published none."},"receipt_date":{"type":"string","format":"date","description":"Official receipt date on rules feeds. Omitted on DCM products and DCO rows; CFTC does not publish one there."},"status":{"type":"string"},"status_date":{"type":"string","format":"date"},"doc_count":{"type":"integer"},"predicted_effective_date":{"type":"string","format":"date","description":"Business-day estimate for a pending rules filing that has a receipt date. Omitted once the filing is no longer pending, and on feeds with no receipt date."},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}},"markdown":{"type":"string","description":"Filing detail and converted attachment text."},"documents":{"type":"array","items":{"type":"object","required":["url","title"],"properties":{"url":{"type":"string","format":"uri"},"title":{"type":"string"}}}},"source_url":{"type":"string","format":"uri"}}},"examples":[]},{"status":"404","description":"Unknown or older than 90 days","examples":[]}],"security":[],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List industry filings
url: "https://docs.adjacent.markets/api/get-api-v1-filings.md"
description: "Full CFTC industry-filings catalog, newest status date first, or by sort/sortdir."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/filings" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/filings","summary":"List industry filings","description":"Full CFTC industry-filings catalog, newest status date first, or by `sort`/`sort_dir`.","parameters":[{"name":"feed","in":"query","schema":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]}},{"name":"org","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","description":"Relevance-ranked text search over the organization, description, product name and type, affected products, and filing id.","schema":{"type":"string"}},{"name":"last_seen_days","in":"query","description":"Only filings not observed on a CFTC listing in this many days.","schema":{"type":"integer","minimum":1}},{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}},{"name":"sort","in":"query","description":"Sort key.","schema":{"type":"string","enum":["status_date","received","first_seen","last_seen","org"],"default":"status_date"}},{"name":"sort_dir","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}],"responses":[{"status":"200","description":"Paged filings","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","required":["id","title","feed","org_code","status","status_date","doc_count"],"properties":{"id":{"type":"integer","format":"int64","description":"CFTC filing id."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"feed":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"org_code":{"type":"string"},"description":{"type":"string","description":"Rules-feed description. Omitted on DCM product and DCO rows; use title."},"product_name":{"type":"string","description":"DCM product name. Omitted on rules and DCO rows; use title."},"product_type":{"type":"string","description":"DCM product type. Omitted on feeds that do not list one."},"category":{"type":"string","description":"DCM product category. Omitted on rules and DCO rows."},"subcategory":{"type":"string","description":"DCM product subcategory. Omitted on rules and DCO rows."},"products_affected":{"type":"string","description":"PTC listing column. CFTC leaves it blank; omitted when empty."},"remarks":{"type":"string","description":"Present on DCO registrations. Omitted when CFTC published none."},"receipt_date":{"type":"string","format":"date","description":"Official receipt date on rules feeds. Omitted on DCM products and DCO rows; CFTC does not publish one there."},"status":{"type":"string"},"status_date":{"type":"string","format":"date"},"doc_count":{"type":"integer"},"predicted_effective_date":{"type":"string","format":"date","description":"Business-day estimate for a pending rules filing that has a receipt date. Omitted once the filing is no longer pending, and on feeds with no receipt date."},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: List filing events
url: "https://docs.adjacent.markets/api/get-api-v1-filings-events.md"
description: "Every observed change across the filings tape, oldest first: first sightings, status flips, and later attachments."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/filings/events" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/filings/events","summary":"List filing events","description":"Every observed change across the filings tape, oldest first: first sightings, status flips, and later attachments.","parameters":[{"name":"since_seq","in":"query","description":"Return only events after this tape position.","schema":{"type":"integer","format":"int64"}},{"name":"since","in":"query","description":"Return only events observed at or after this RFC 3339 timestamp.","schema":{"type":"string","format":"date-time"}},{"name":"kind","in":"query","description":"Return only events of this kind.","schema":{"type":"string","enum":["received","status_changed","documents_added"]}},{"name":"feed","in":"query","description":"Return only events on filings in this registry.","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"maximum":500}}],"responses":[{"status":"200","description":"A page of filing events, oldest first.","schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","description":"One observed change to a filing, joined to the filing it happened to.","required":["seq","filing_id","kind","observed_at","filing"],"properties":{"seq":{"type":"integer","format":"int64","description":"Position on the tape. Send the highest value a page returned back as since_seq to read only later events."},"filing_id":{"type":"integer","format":"int64"},"kind":{"type":"string","description":"received is the first sighting, status_changed a listing status flip, documents_added a later attachment.","enum":["received","status_changed","documents_added"]},"from_status":{"type":"string","description":"Status before the flip. Present on status_changed."},"to_status":{"type":"string","description":"Status after the flip. Present on status_changed."},"from_doc_count":{"type":"integer","description":"Attachment count before the addition. Present on documents_added."},"to_doc_count":{"type":"integer","description":"Attachment count after the addition. Present on documents_added."},"date":{"type":"string","format":"date","description":"CFTC-published date for the action. Present on received and status_changed. Absent on documents_added, which the CFTC listing does not date; order those by observed_at."},"observed_at":{"type":"string","format":"date-time","description":"When the poll cycle saw the change."},"filing":{"type":"object","required":["id","title","feed","org_code","status","status_date","doc_count"],"properties":{"id":{"type":"integer","format":"int64","description":"CFTC filing id."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"feed":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"org_code":{"type":"string"},"description":{"type":"string","description":"Rules-feed description. Omitted on DCM product and DCO rows; use title."},"product_name":{"type":"string","description":"DCM product name. Omitted on rules and DCO rows; use title."},"product_type":{"type":"string","description":"DCM product type. Omitted on feeds that do not list one."},"category":{"type":"string","description":"DCM product category. Omitted on rules and DCO rows."},"subcategory":{"type":"string","description":"DCM product subcategory. Omitted on rules and DCO rows."},"products_affected":{"type":"string","description":"PTC listing column. CFTC leaves it blank; omitted when empty."},"remarks":{"type":"string","description":"Present on DCO registrations. Omitted when CFTC published none."},"receipt_date":{"type":"string","format":"date","description":"Official receipt date on rules feeds. Omitted on DCM products and DCO rows; CFTC does not publish one there."},"status":{"type":"string"},"status_date":{"type":"string","format":"date"},"doc_count":{"type":"integer"},"predicted_effective_date":{"type":"string","format":"date","description":"Business-day estimate for a pending rules filing that has a receipt date. Omitted once the filing is no longer pending, and on feeds with no receipt date."},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Filing filter values
url: "https://docs.adjacent.markets/api/get-api-v1-filings-filters.md"
description: "Distinct feeds, organizations, and statuses present in the catalog."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/filings/filters" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/filings/filters","summary":"Filing filter values","description":"Distinct feeds, organizations, and statuses present in the catalog.","parameters":[],"responses":[{"status":"200","description":"The distinct feed, organization, and status values present.","schema":{"type":"object","required":["feeds","orgs","statuses"],"properties":{"feeds":{"type":"array","items":{"type":"string"}},"orgs":{"type":"array","items":{"type":"string"}},"statuses":{"type":"array","items":{"type":"string"}}}},"examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Get a filing
url: "https://docs.adjacent.markets/api/get-api-v1-filings-id.md"
description: One stored CFTC filing by id.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/filings/0" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/filings/{id}","summary":"Get a filing","description":"One stored CFTC filing by id.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":[{"status":"200","description":"Filing","schema":{"type":"object","required":["id","title","feed","org_code","status","status_date","doc_count"],"properties":{"id":{"type":"integer","format":"int64","description":"CFTC filing id."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"feed":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"org_code":{"type":"string"},"description":{"type":"string","description":"Rules-feed description. Omitted on DCM product and DCO rows; use title."},"product_name":{"type":"string","description":"DCM product name. Omitted on rules and DCO rows; use title."},"product_type":{"type":"string","description":"DCM product type. Omitted on feeds that do not list one."},"category":{"type":"string","description":"DCM product category. Omitted on rules and DCO rows."},"subcategory":{"type":"string","description":"DCM product subcategory. Omitted on rules and DCO rows."},"products_affected":{"type":"string","description":"PTC listing column. CFTC leaves it blank; omitted when empty."},"remarks":{"type":"string","description":"Present on DCO registrations. Omitted when CFTC published none."},"receipt_date":{"type":"string","format":"date","description":"Official receipt date on rules feeds. Omitted on DCM products and DCO rows; CFTC does not publish one there."},"status":{"type":"string"},"status_date":{"type":"string","format":"date"},"doc_count":{"type":"integer"},"predicted_effective_date":{"type":"string","format":"date","description":"Business-day estimate for a pending rules filing that has a receipt date. Omitted once the filing is no longer pending, and on feeds with no receipt date."},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}},"examples":[]},{"status":"404","description":"Unknown filing id","examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Filing actions
url: "https://docs.adjacent.markets/api/get-api-v1-filings-id-actions.md"
description: "Receipt, status changes, and later attachments for one filing, oldest first."
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/filings/0/actions" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/filings/{id}/actions","summary":"Filing actions","description":"Receipt, status changes, and later attachments for one filing, oldest first.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":[{"status":"200","description":"The source filing and its actions","schema":{"type":"object","required":["filing","data","meta"],"properties":{"filing":{"type":"object","required":["id","title","feed","org_code","status","status_date","doc_count"],"properties":{"id":{"type":"integer","format":"int64","description":"CFTC filing id."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"feed":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"org_code":{"type":"string"},"description":{"type":"string","description":"Rules-feed description. Omitted on DCM product and DCO rows; use title."},"product_name":{"type":"string","description":"DCM product name. Omitted on rules and DCO rows; use title."},"product_type":{"type":"string","description":"DCM product type. Omitted on feeds that do not list one."},"category":{"type":"string","description":"DCM product category. Omitted on rules and DCO rows."},"subcategory":{"type":"string","description":"DCM product subcategory. Omitted on rules and DCO rows."},"products_affected":{"type":"string","description":"PTC listing column. CFTC leaves it blank; omitted when empty."},"remarks":{"type":"string","description":"Present on DCO registrations. Omitted when CFTC published none."},"receipt_date":{"type":"string","format":"date","description":"Official receipt date on rules feeds. Omitted on DCM products and DCO rows; CFTC does not publish one there."},"status":{"type":"string"},"status_date":{"type":"string","format":"date"},"doc_count":{"type":"integer"},"predicted_effective_date":{"type":"string","format":"date","description":"Business-day estimate for a pending rules filing that has a receipt date. Omitted once the filing is no longer pending, and on feeds with no receipt date."},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}},"data":{"type":"array","items":{"type":"object","required":["kind","observed_at"],"properties":{"seq":{"type":["integer","null"],"format":"int64","description":"Observed-tape row id. Null when the current published status is included without a recorded transition."},"kind":{"type":"string","description":"received is first sighting (date is the official receipt when present). status_changed is a recorded flip. documents_added is a later attachment. status is the current published action when no recorded flip reaches it.","enum":["received","status_changed","documents_added","status"]},"from_status":{"type":["string","null"]},"to_status":{"type":["string","null"],"description":"New status on a status_changed row, or the current published status on a status row. Listing labels such as Certified or Withdrawn."},"from_doc_count":{"type":["integer","null"]},"to_doc_count":{"type":["integer","null"]},"date":{"type":["string","null"],"format":"date","description":"CFTC-published date when known: official receipt for received, the status date recorded with that flip for status_changed, the current status date for a synthesized status row. Null for document additions."},"observed_at":{"type":"string","format":"date-time","description":"When this row was recorded. On a status row with no tape id, this is first_seen_at."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]},{"status":"404","description":"Unknown filing id","examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Filing attachment text
url: "https://docs.adjacent.markets/api/get-api-v1-filings-id-markdown.md"
description: The filing plus extracted markdown from each stored attachment.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/filings/0/markdown" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/filings/{id}/markdown","summary":"Filing attachment text","description":"The filing plus extracted markdown from each stored attachment.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":[{"status":"200","description":"Markdown body and attachment list","schema":{"type":"object","required":["filing","markdown","documents","source_url"],"properties":{"filing":{"type":"object","required":["id","title","feed","org_code","status","status_date","doc_count"],"properties":{"id":{"type":"integer","format":"int64","description":"CFTC filing id."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"feed":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"org_code":{"type":"string"},"description":{"type":"string","description":"Rules-feed description. Omitted on DCM product and DCO rows; use title."},"product_name":{"type":"string","description":"DCM product name. Omitted on rules and DCO rows; use title."},"product_type":{"type":"string","description":"DCM product type. Omitted on feeds that do not list one."},"category":{"type":"string","description":"DCM product category. Omitted on rules and DCO rows."},"subcategory":{"type":"string","description":"DCM product subcategory. Omitted on rules and DCO rows."},"products_affected":{"type":"string","description":"PTC listing column. CFTC leaves it blank; omitted when empty."},"remarks":{"type":"string","description":"Present on DCO registrations. Omitted when CFTC published none."},"receipt_date":{"type":"string","format":"date","description":"Official receipt date on rules feeds. Omitted on DCM products and DCO rows; CFTC does not publish one there."},"status":{"type":"string"},"status_date":{"type":"string","format":"date"},"doc_count":{"type":"integer"},"predicted_effective_date":{"type":"string","format":"date","description":"Business-day estimate for a pending rules filing that has a receipt date. Omitted once the filing is no longer pending, and on feeds with no receipt date."},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}},"markdown":{"type":"string","description":"Filing detail and converted attachment text."},"documents":{"type":"array","items":{"type":"object","required":["url","title"],"properties":{"url":{"type":"string","format":"uri"},"title":{"type":"string"}}}},"source_url":{"type":"string","format":"uri"}}},"examples":[]},{"status":"404","description":"Unknown filing id","examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Similar filings
url: "https://docs.adjacent.markets/api/get-api-v1-filings-id-similar.md"
description: The named filing plus other filings whose titles are close to it.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/filings/0/similar" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/filings/{id}/similar","summary":"Similar filings","description":"The named filing plus other filings whose titles are close to it.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"min_similarity","in":"query","schema":{"type":"number","minimum":0,"maximum":1}},{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":[{"status":"200","description":"The source filing and similar filings","schema":{"type":"object","required":["filing","data","meta"],"properties":{"filing":{"type":"object","required":["id","title","feed","org_code","status","status_date","doc_count"],"properties":{"id":{"type":"integer","format":"int64","description":"CFTC filing id."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"feed":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"org_code":{"type":"string"},"description":{"type":"string","description":"Rules-feed description. Omitted on DCM product and DCO rows; use title."},"product_name":{"type":"string","description":"DCM product name. Omitted on rules and DCO rows; use title."},"product_type":{"type":"string","description":"DCM product type. Omitted on feeds that do not list one."},"category":{"type":"string","description":"DCM product category. Omitted on rules and DCO rows."},"subcategory":{"type":"string","description":"DCM product subcategory. Omitted on rules and DCO rows."},"products_affected":{"type":"string","description":"PTC listing column. CFTC leaves it blank; omitted when empty."},"remarks":{"type":"string","description":"Present on DCO registrations. Omitted when CFTC published none."},"receipt_date":{"type":"string","format":"date","description":"Official receipt date on rules feeds. Omitted on DCM products and DCO rows; CFTC does not publish one there."},"status":{"type":"string"},"status_date":{"type":"string","format":"date"},"doc_count":{"type":"integer"},"predicted_effective_date":{"type":"string","format":"date","description":"Business-day estimate for a pending rules filing that has a receipt date. Omitted once the filing is no longer pending, and on feeds with no receipt date."},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}},"data":{"type":"array","items":{"type":"object","required":["filing_id","similarity","title","org_code","feed","status","status_date"],"properties":{"filing_id":{"type":"integer","format":"int64","description":"CFTC filing id."},"similarity":{"type":"number","format":"double","description":"Cosine similarity of the title embedding match."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"org_code":{"type":"string","description":"Submitting organization code, for example KEX or CME."},"feed":{"type":"string","description":"CFTC registry this filing belongs to.","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"status":{"type":"string","description":"Current CFTC status, for example Certified or 10 Day Review."},"status_date":{"type":"string","format":"date","description":"Date of the current status."},"description":{"type":["string","null"],"description":"Filing description from the CFTC listing."},"product_name":{"type":["string","null"],"description":"Product name, when the registry carries one."},"product_type":{"type":["string","null"]},"category":{"type":["string","null"]},"subcategory":{"type":["string","null"]},"products_affected":{"type":["string","null"]},"remarks":{"type":["string","null"]},"receipt_date":{"type":["string","null"],"format":"date"},"doc_count":{"type":"integer","description":"Number of attachments listed on the filing."},"predicted_effective_date":{"type":["string","null"],"format":"date"},"via_market_id":{"type":["string","null"],"description":"The constituent market this filing matched most closely. Present only on index filings, where results are drawn from the index's constituent markets."},"via_market_question":{"type":["string","null"],"description":"The question text of that market."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]},{"status":"404","description":"Unknown filing id","examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Markets related to a filing
url: "https://docs.adjacent.markets/api/get-api-v1-filings-id-markets.md"
description: The named filing plus markets whose questions sit near its title.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/filings/0/markets" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/filings/{id}/markets","summary":"Markets related to a filing","description":"The named filing plus markets whose questions sit near its title.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"min_similarity","in":"query","schema":{"type":"number","minimum":0,"maximum":1}},{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":[{"status":"200","description":"The source filing and related markets","schema":{"type":"object","required":["filing","data","meta"],"properties":{"filing":{"type":"object","required":["id","title","feed","org_code","status","status_date","doc_count"],"properties":{"id":{"type":"integer","format":"int64","description":"CFTC filing id."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"feed":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"org_code":{"type":"string"},"description":{"type":"string","description":"Rules-feed description. Omitted on DCM product and DCO rows; use title."},"product_name":{"type":"string","description":"DCM product name. Omitted on rules and DCO rows; use title."},"product_type":{"type":"string","description":"DCM product type. Omitted on feeds that do not list one."},"category":{"type":"string","description":"DCM product category. Omitted on rules and DCO rows."},"subcategory":{"type":"string","description":"DCM product subcategory. Omitted on rules and DCO rows."},"products_affected":{"type":"string","description":"PTC listing column. CFTC leaves it blank; omitted when empty."},"remarks":{"type":"string","description":"Present on DCO registrations. Omitted when CFTC published none."},"receipt_date":{"type":"string","format":"date","description":"Official receipt date on rules feeds. Omitted on DCM products and DCO rows; CFTC does not publish one there."},"status":{"type":"string"},"status_date":{"type":"string","format":"date"},"doc_count":{"type":"integer"},"predicted_effective_date":{"type":"string","format":"date","description":"Business-day estimate for a pending rules filing that has a receipt date. Omitted once the filing is no longer pending, and on feeds with no receipt date."},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}},"data":{"type":"array","items":{"type":"object","required":["market_id","similarity"],"properties":{"market_id":{"type":"string"},"similarity":{"type":"number","format":"double"},"question":{"type":["string","null"]},"description":{"type":["string","null"]},"platform":{"type":["string","null"]},"latest_price":{"type":["number","null"]}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]},{"status":"404","description":"Unknown filing id","examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: News related to a filing
url: "https://docs.adjacent.markets/api/get-api-v1-filings-id-news.md"
description: The named filing plus articles whose text sits near its title.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/filings/0/news" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/filings/{id}/news","summary":"News related to a filing","description":"The named filing plus articles whose text sits near its title.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"min_similarity","in":"query","schema":{"type":"number","minimum":0,"maximum":1}},{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}},{"name":"recency_half_life_days","in":"query","description":"Recency half-life in days for the relevance-recency blend applied to the ranking: a result's score is its similarity times 0.5^(age_days / this).","schema":{"type":"number","minimum":0}}],"responses":[{"status":"200","description":"The source filing and related articles","schema":{"type":"object","required":["filing","data","meta"],"properties":{"filing":{"type":"object","required":["id","title","feed","org_code","status","status_date","doc_count"],"properties":{"id":{"type":"integer","format":"int64","description":"CFTC filing id."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"feed":{"type":"string","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"org_code":{"type":"string"},"description":{"type":"string","description":"Rules-feed description. Omitted on DCM product and DCO rows; use title."},"product_name":{"type":"string","description":"DCM product name. Omitted on rules and DCO rows; use title."},"product_type":{"type":"string","description":"DCM product type. Omitted on feeds that do not list one."},"category":{"type":"string","description":"DCM product category. Omitted on rules and DCO rows."},"subcategory":{"type":"string","description":"DCM product subcategory. Omitted on rules and DCO rows."},"products_affected":{"type":"string","description":"PTC listing column. CFTC leaves it blank; omitted when empty."},"remarks":{"type":"string","description":"Present on DCO registrations. Omitted when CFTC published none."},"receipt_date":{"type":"string","format":"date","description":"Official receipt date on rules feeds. Omitted on DCM products and DCO rows; CFTC does not publish one there."},"status":{"type":"string"},"status_date":{"type":"string","format":"date"},"doc_count":{"type":"integer"},"predicted_effective_date":{"type":"string","format":"date","description":"Business-day estimate for a pending rules filing that has a receipt date. Omitted once the filing is no longer pending, and on feeds with no receipt date."},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}},"data":{"type":"array","items":{"type":"object","required":["article_id","similarity"],"properties":{"article_id":{"type":"string"},"similarity":{"type":"number","format":"double","description":"Cosine similarity of the best embedding match."},"title":{"type":["string","null"]},"url":{"type":["string","null"]},"image_url":{"type":["string","null"]},"published_date":{"type":["string","null"],"format":"date-time"},"source":{"type":["string","null"],"description":"Where the article was published: the publisher's name when known, otherwise the site's hostname."},"via_market_id":{"type":["string","null"],"description":"The market this article matched most closely. Present on index news (the winning constituent market, including a constituent rate's source market) and on rate news when a source market beat the rate itself."},"via_market_question":{"type":["string","null"],"description":"The question text of that market."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]},{"status":"404","description":"Unknown filing id","examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Filings related to a market
url: "https://docs.adjacent.markets/api/get-api-v1-markets-id-filings.md"
description: The named market plus CFTC filings whose titles sit near its question.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/markets/<id>/filings" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/markets/{id}/filings","summary":"Filings related to a market","description":"The named market plus CFTC filings whose titles sit near its question.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"min_similarity","in":"query","schema":{"type":"number","minimum":0,"maximum":1}},{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":[{"status":"200","description":"Related filings","schema":{"type":"object","required":["market","data","meta"],"properties":{"market":{"type":"object","required":["market_id","question","display_ticker"],"properties":{"market_id":{"type":"string"},"question":{"type":"string"},"platform":{"type":["string","null"]},"display_ticker":{"type":"string"}}},"data":{"type":"array","items":{"type":"object","required":["filing_id","similarity","title","org_code","feed","status","status_date"],"properties":{"filing_id":{"type":"integer","format":"int64","description":"CFTC filing id."},"similarity":{"type":"number","format":"double","description":"Cosine similarity of the title embedding match."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"org_code":{"type":"string","description":"Submitting organization code, for example KEX or CME."},"feed":{"type":"string","description":"CFTC registry this filing belongs to.","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"status":{"type":"string","description":"Current CFTC status, for example Certified or 10 Day Review."},"status_date":{"type":"string","format":"date","description":"Date of the current status."},"description":{"type":["string","null"],"description":"Filing description from the CFTC listing."},"product_name":{"type":["string","null"],"description":"Product name, when the registry carries one."},"product_type":{"type":["string","null"]},"category":{"type":["string","null"]},"subcategory":{"type":["string","null"]},"products_affected":{"type":["string","null"]},"remarks":{"type":["string","null"]},"receipt_date":{"type":["string","null"],"format":"date"},"doc_count":{"type":"integer","description":"Number of attachments listed on the filing."},"predicted_effective_date":{"type":["string","null"],"format":"date"},"via_market_id":{"type":["string","null"],"description":"The constituent market this filing matched most closely. Present only on index filings, where results are drawn from the index's constituent markets."},"via_market_question":{"type":["string","null"],"description":"The question text of that market."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]},{"status":"404","description":"Unknown market id","examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Filings related to an article
url: "https://docs.adjacent.markets/api/get-api-v1-news-id-filings.md"
description: The named article plus CFTC filings whose titles sit near it.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/news/<id>/filings" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/news/{id}/filings","summary":"Filings related to an article","description":"The named article plus CFTC filings whose titles sit near it.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"min_similarity","in":"query","schema":{"type":"number","minimum":0,"maximum":1}},{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":[{"status":"200","description":"Related filings","schema":{"type":"object","required":["article","data","meta"],"properties":{"article":{"type":"object","required":["article_id","url","source"],"properties":{"article_id":{"type":"string"},"title":{"type":["string","null"]},"url":{"type":"string"},"source":{"type":"string"},"published_date":{"type":["string","null"],"format":"date-time"}}},"data":{"type":"array","items":{"type":"object","required":["filing_id","similarity","title","org_code","feed","status","status_date"],"properties":{"filing_id":{"type":"integer","format":"int64","description":"CFTC filing id."},"similarity":{"type":"number","format":"double","description":"Cosine similarity of the title embedding match."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"org_code":{"type":"string","description":"Submitting organization code, for example KEX or CME."},"feed":{"type":"string","description":"CFTC registry this filing belongs to.","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"status":{"type":"string","description":"Current CFTC status, for example Certified or 10 Day Review."},"status_date":{"type":"string","format":"date","description":"Date of the current status."},"description":{"type":["string","null"],"description":"Filing description from the CFTC listing."},"product_name":{"type":["string","null"],"description":"Product name, when the registry carries one."},"product_type":{"type":["string","null"]},"category":{"type":["string","null"]},"subcategory":{"type":["string","null"]},"products_affected":{"type":["string","null"]},"remarks":{"type":["string","null"]},"receipt_date":{"type":["string","null"],"format":"date"},"doc_count":{"type":"integer","description":"Number of attachments listed on the filing."},"predicted_effective_date":{"type":["string","null"],"format":"date"},"via_market_id":{"type":["string","null"],"description":"The constituent market this filing matched most closely. Present only on index filings, where results are drawn from the index's constituent markets."},"via_market_question":{"type":["string","null"],"description":"The question text of that market."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]},{"status":"404","description":"Unknown article id","examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Filings related to an index
url: "https://docs.adjacent.markets/api/get-api-v1-indices-id-filings.md"
description: The named index plus CFTC filings related through its constituent markets.
---

<Aside full>
  <RequestExample>
    ```bash title="cURL" lines=false
    curl -X GET "https://api.adjacent.markets/api/v1/indices/<id>/filings" \
      -H "Authorization: Bearer <token>"
    ```
  </RequestExample>
</Aside>

<OpenAPIEndpoint {...{"method":"get","path":"/api/v1/indices/{id}/filings","summary":"Filings related to an index","description":"The named index plus CFTC filings related through its constituent markets.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"min_similarity","in":"query","schema":{"type":"number","minimum":0,"maximum":1}},{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":[{"status":"200","description":"The source index and related filings","schema":{"type":"object","required":["index","data","meta"],"properties":{"index":{"type":"object","required":["index_id","name"],"properties":{"index_id":{"type":"string"},"name":{"type":"string"}}},"data":{"type":"array","items":{"type":"object","required":["filing_id","similarity","title","org_code","feed","status","status_date"],"properties":{"filing_id":{"type":"integer","format":"int64","description":"CFTC filing id."},"similarity":{"type":"number","format":"double","description":"Cosine similarity of the title embedding match."},"title":{"type":"string","description":"Product name on DCM product filings, otherwise the filing description."},"org_code":{"type":"string","description":"Submitting organization code, for example KEX or CME."},"feed":{"type":"string","description":"CFTC registry this filing belongs to.","enum":["ptc_dcm_rules","dcm_products","dco","dco_rules"]},"status":{"type":"string","description":"Current CFTC status, for example Certified or 10 Day Review."},"status_date":{"type":"string","format":"date","description":"Date of the current status."},"description":{"type":["string","null"],"description":"Filing description from the CFTC listing."},"product_name":{"type":["string","null"],"description":"Product name, when the registry carries one."},"product_type":{"type":["string","null"]},"category":{"type":["string","null"]},"subcategory":{"type":["string","null"]},"products_affected":{"type":["string","null"]},"remarks":{"type":["string","null"]},"receipt_date":{"type":["string","null"],"format":"date"},"doc_count":{"type":"integer","description":"Number of attachments listed on the filing."},"predicted_effective_date":{"type":["string","null"],"format":"date"},"via_market_id":{"type":["string","null"],"description":"The constituent market this filing matched most closely. Present only on index filings, where results are drawn from the index's constituent markets."},"via_market_question":{"type":["string","null"],"description":"The question text of that market."}}}},"meta":{"type":"object","properties":{"total":{"type":["integer","null"],"description":"Total number of records matching the request across every page, not just the current one. null on an uncounted list; page using has_next. A relevance-ranked search is uncounted, and a searched events list stays uncounted even with sort. A searched markets list with sort returns a total over the ranked matches (at most 10,000)."},"page":{"type":"integer","description":"The 1-based page number this response covers."},"per_page":{"type":"integer","description":"Maximum number of items on a page. The last page may hold fewer."},"total_pages":{"type":["integer","null"],"description":"Total number of pages available at the current per_page. null whenever total is null; page using has_next."},"has_next":{"type":"boolean","description":"True when a page exists after this one."},"has_prev":{"type":"boolean","description":"True when this is not the first page."},"total_capped":{"type":"boolean","description":"True when `total` and `total_pages` reflect the server's counting ceiling rather than the exact matched count: the real set is at least `total` large. Render such totals as a lower bound (for example \"10,000+\"). Omitted when the count is exact. A sorted markets search that fills the 10,000-candidate ceiling sets this flag."}}}}},"examples":[]},{"status":"404","description":"Unknown index id","examples":[]}],"security":[{"name":"bearerAuth","type":"http","scheme":"bearer","in":"header","description":"Session token from the app, or an API key (the `ak_` prefix), sent as a Bearer token or an `?api_key=` query parameter."}],"servers":[{"url":"https://api.adjacent.markets","description":"API server"}]}} />


---
title: Changelog
url: "https://docs.adjacent.markets/changelog.md"
description: Updates to the Adjacent API.
---

{/* Add customer-facing entries under the Unreleased block below. At release, `just changelog-release` stamps it with the date (docs-deploy-prod fires on the release tag). */}

<Update label="September 4, 2026" tags={["REST"]}>
  **NFL Team Index reads.** Index detail for an NFL team index (`methodology` `nti`) includes `sleeves` (four seats: Super Bowl, conference, division, next game) and `official_daily_value`. `quote_convention` is `points` and the level starts at 1000. `GET /api/v1/indices/{id}/daily-values` and `GET /api/v1/indices/{id}/membership-events` (and the `/api/v1/public/indices/...` twins) return the official daily series and recent sleeve admissions or settlements. Other families return empty lists.
</Update>

<Update label="September 4, 2026" tags={["REST"]}>
  **Filings list by last listing observation.** `GET /api/v1/filings` and `GET /api/v1/public/filings` accept `last_seen_days` (integer, at least 1) to return only filings not observed on a CFTC listing in that many days. Pass `sort=last_seen` with `sort_dir` to order by when a filing last appeared on a listing.

  **Public indices list stays complete when the catalog is large.** `GET /api/v1/public/indices` returns every public index when the catalog includes dozens of NFL team series. `GET /api/v1/public/indices/{id}` quotes the same stamped `latest_price`. A quiet index still omits `latest_price` when its last print is older than seven days.

  **Public rates list stays complete when the catalog is large.** `GET /api/v1/public/rates` returns every public rate when the catalog has hundreds of rows (NFL team sleeve rates). A quiet rate still omits `latest_price` when its last print is older than seven days.

  **NTI sleeve members include each contract's mark.** On `GET /api/v1/indices/{id}` and `GET /api/v1/public/indices/{id}`, each `sleeves.members[]` entry has `mark_price` (0-1) for that contract. A win-total pair therefore carries both marks.

  **Event-contract rates treat a 0¢ bid or ask as missing.** When only one side of the book is present, `GET /api/v1/rates/{id}` (and the public twin) uses last trade, then the remaining quote, then the half-cent floor. A prior half-cent print does not stick once last trade or a one-sided quote is available.

  **Rate constituents in component returns.** Index detail (`GET /api/v1/indices/{id}` and the public tier) labels a rate-backed constituent in `constituent_returns` with `kind` `rate`. Link those rows to the rate page.
</Update>

<Update label="September 3, 2026" tags={["REST"]}>
  **Rate news includes source-market matches.** `GET /api/v1/rates/{id}/news` and `GET /api/v1/public/rates/{id}/news` return articles that match the rate itself or any of its source markets. `via_market_id` names the source market when that match wins; it is omitted when the rate itself matched more closely.

  **Index news includes constituent rate sources.** `GET /api/v1/indices/{id}/news` and `GET /api/v1/public/indices/{id}/news` draw related articles from the index's constituent markets, including the source markets of any constituent rates. `via_market_id` names the closest market. `GET /api/v1/indices/{id}/filings` uses the same market set.

  **Wins-sleeve members follow the wrapping pair before the first print.** On `GET /api/v1/indices/{id}` and `GET /api/v1/public/indices/{id}`, an NTI index's wins `sleeves.members` lists the wrapping win-total rates from the latest prints. After the first mark, members continue to follow the printed pair.

  **Quiet rates omit the latest price.** `GET /api/v1/rates` and the rates CSV export look back seven days when you omit `start`: a rate whose last print is older than that window returns `latest_price` and `spread` as null. Pass an earlier `start` to include older prints. `GET /api/v1/public/rates`, `GET /api/v1/rates/{id}`, and `GET /api/v1/public/rates/{id}` use the same seven-day window.

  **Rate sources stay on the detail page when the print did not use a two-sided book.** `GET /api/v1/public/rates/{id}` (and the list's inlined `sources`) includes every configured source market. A source that did not enter the latest print omits `latest_price`.

  **Inactive rates drop off the public list.** `GET /api/v1/public/rates` omits a rate when every source is inactive (`is_active` is false). The rate detail URL still returns the rate. The authenticated catalog is unchanged.
</Update>

<Update label="August 28, 2026" tags={["REST"]}>
  **Searched event lists stay uncounted with sort.** `GET /api/v1/events` and `GET /api/v1/public/events` return `total` and `total_pages` as `null` when `search` is set, including when you also pass `sort`; page with `has_next`. A searched markets list is uncounted on relevance ranking, but passing `sort` on `GET /api/v1/markets` or `GET /api/v1/public/markets` returns a total over the ranked matches (at most 10,000). Events have no stable number for that request shape.

  **Sorted market-search totals at the ceiling are a floor.** When `search` and `sort` are both set on a markets list and `meta.total` is 10,000, `meta.total_capped` is `true`. Render that as "10,000+", not as an exact count. Below the ceiling the total is exact.
</Update>

<Update label="August 27, 2026" tags={["REST"]}>
  **Searched event lists are uncounted.** `GET /api/v1/events` and `GET /api/v1/public/events` return `total` and `total_pages` as `null` when `search` is set; page with `has_next` instead. Unsearched lists are unchanged and still carry an exact total. This matches `GET /api/v1/markets`, which has always been uncounted on a searched page. The previous total was bounded by the search's internal candidate window rather than the matched set, so it under-reported broad queries and changed as you paged through the same result set.
</Update>

<Update label="August 26, 2026" tags={["REST"]}>
  **CFTC industry filings.** A new catalog of product certifications and rule submissions from the four CFTC industry-filing registries (PTC/DCM rules, DCM products, DCO, DCO rules). `GET /api/v1/public/filings` returns filings whose CFTC status date falls in the last 90 days, with `GET /api/v1/public/filings/filters` for the feed, organization, and status values present, `GET /api/v1/public/filings/{id}` for one filing, and `GET /api/v1/public/filings/{id}/markdown` for the extracted text of its attachments. Filtering, relevance-ranked search, and sorting work on this tier too, within that window. Filings older than it, the change feed, and related records require the `org:filings:read` scope.

  **Full filings history.** `GET /api/v1/filings` returns the whole catalog, filtered by `feed`, `org`, `status`, and a relevance-ranked `search` across the organization, description, product name and type, affected products, and filing id. A searched page is uncounted, so page with `has_next` rather than a total, the same as the markets list. Pass `sort` (`status_date`, `received`, `first_seen`, `org`) with `sort_dir` to order by a field instead. `GET /api/v1/filings/{id}/actions` returns one filing's dated history: its receipt, each status change, and each later attachment.

  **Filing change feed.** `GET /api/v1/filings/events` returns every observed change across the catalog, oldest first, each row carrying the filing it happened to. Poll it with `since_seq` set to the highest `seq` of the previous page to receive only what has changed since. Filter by `kind` (`received`, `status_changed`, `documents_added`), by `feed`, or by a `since` timestamp for a first poll that has no cursor yet.

  **Filings alongside markets, news, and indices.** `GET /api/v1/filings/{id}/markets`, `/news`, and `/similar` return records related to a filing. `GET /api/v1/markets/{id}/filings`, `GET /api/v1/news/{id}/filings`, and `GET /api/v1/indices/{id}/filings` return the same relationships from the other side.
</Update>

<Update label="August 20, 2026" tags={["REST"]}>
  **Filter events by venue and market close window.** `GET /api/v1/events` and `GET /api/v1/export/events/{ext}` accept `venue` (for example `kalshi` or `polymarket`), `expires_after`, and `expires_before`. `start` and `end` are deprecated; use `expires_after` and `expires_before` instead. Events are returned newest-added first, or by relevance when `search` is set.

  **Filter events by listing time.** `GET /api/v1/events` (and `GET /api/v1/export/events/{ext}`) accept `created_since` and `created_until` (ISO date or datetime), which filter events by when they were first listed on the platform. The anonymous public events list does not implement those parameters; use an API key. `expires_after` / `expires_before` bound the resolution window instead.

  **Grouped constituent returns with percent change.** Index detail (`GET /api/v1/indices/{id}` and the public tier) returns `constituent_returns` grouped by a dimension (`group_by`, for example `state`); each group carries its weight and both its point change and `percent_change`.

  **Index visibility.** Indices carry a `visibility` field on authenticated responses (`public` or `organization`; other values are reserved). The anonymous public tier returns only public indices and omits the field.
</Update>

<Update label="August 17, 2026" tags={["REST"]}>
  **Relevance-ranked market search.** `search` on `GET /api/v1/markets` and `GET /api/v1/public/markets` ranks results by relevance and matches a market's slug. A relevance-ranked search is uncounted: `meta.total` is `null`, so page with `meta.has_next` rather than a total count.

  **Explicit sort on searched lists.** `GET /api/v1/public/events` and `GET /api/v1/public/markets` honor an explicit `sort` and `sort_dir` when a `search` query is present.

  **Capped list totals.** List responses carry `meta.total_capped`. When `true`, `meta.total` and `meta.total_pages` are a lower bound rather than an exact count, so render them as, for example, "10,000+". The field is omitted when the count is exact.
</Update>
