> ## Documentation Index
> Fetch the complete documentation index at: https://molelcule.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Market Data: Search, Order Books, and Candles | Molecule

> Search prediction market instruments, retrieve order books, query historical candles, and stream real-time price updates using the Molecule markets API.

The `client.markets` namespace gives you complete access to Molecule's market data layer. Use it to discover instruments across Demo, Polymarket, and Kalshi; fetch live order books; pull historical candles and trade prints; and check venue connectivity — all through a single authenticated client.

## Searching Markets

Use `client.markets.search()` to run a filtered keyword search across venues and categories. The shortcut `client.search_markets()` calls the same endpoint.

```python theme={"dark"}
import os
from molecule import Molecule

client = Molecule(
    base_url=os.environ["MOLECULE_BASE_URL"],
    key_id=os.environ["MOLECULE_KEY_ID"],
    private_key=os.environ["MOLECULE_PRIVATE_KEY"],
)

# Keyword search, scoped to Polymarket
results = client.search_markets(q="election", venue="Polymarket")
for market in results:
    print(market["instrument_id"], market["title"])
```

To list all instruments available on a venue without a keyword filter, use `client.markets.list()`:

```python theme={"dark"}
# List all active markets on Kalshi
markets = client.markets.list(venue="Kalshi")
```

To resolve a known ticker or slug directly, use `client.markets.match()`:

```python theme={"dark"}
# Match by ticker
market = client.markets.match(ticker="FAKE-HOUSE-DEM")

# Match by slug
market = client.markets.match(slug="will-the-fed-cut-rates-in-december")
print(market["instrument_id"], market["title"])
```

### Search parameters

<ParamField query="q" type="string">
  Free-text keyword query. Matches against market title, description, and ticker.
</ParamField>

<ParamField query="venue" type="string">
  Filter by venue name. One of `Demo`, `Polymarket`, or `Kalshi`.
</ParamField>

<ParamField query="status" type="string">
  Filter by market status — for example `OPEN` or `CLOSED`. Omit to return all statuses.
</ParamField>

<ParamField query="category" type="string">
  Filter by category label such as `Politics` or `Economics`.
</ParamField>

<ParamField query="cursor" type="string">
  Pagination cursor returned in the previous response. Pass it to fetch the next page.
</ParamField>

***

## Getting a Specific Market

Fetch a single instrument by its venue-specific ID, or look up a batch of instruments in one round trip.

<CodeGroup>
  ```python Single instrument theme={"dark"}
  # GET /v1/markets/{id}
  instrument = client.markets.get(instrument_id=98712)
  print(instrument["title"], instrument["status"])
  ```

  ```python Batch lookup theme={"dark"}
  # POST /v1/markets/lookup
  instruments = client.markets.lookup(instrument_ids=[98712, 98713, 98714])
  for inst in instruments:
      print(inst["instrument_id"], inst["title"])
  ```
</CodeGroup>

<Note>
  `markets.lookup()` issues a `POST` to `/v1/markets/lookup` and accepts up to the API's configured batch limit per request. Use it instead of issuing multiple individual `get()` calls.
</Note>

***

## Order Book

Molecule exposes two order book endpoints. Use `markets.book()` or `markets.orderbook()` for a single venue-specific instrument. Use `markets.generic_asset_orderbook()` to retrieve an aggregated book across all venues for the same underlying asset.

<CodeGroup>
  ```python Single-venue book theme={"dark"}
  # GET /v1/markets/{id}/book  — lightweight snapshot
  book = client.markets.book(instrument_id=98712)
  print("Bids:", book["bids"][:3])
  print("Asks:", book["asks"][:3])
  ```

  ```python Full orderbook theme={"dark"}
  # GET /v1/orderbooks/{id}
  orderbook = client.markets.orderbook(instrument_id=98712)
  for level in orderbook["bids"]:
      print(f"  {level['price']} x {level['qty']}")
  ```

  ```python Cross-venue aggregated book theme={"dark"}
  # GET /v1/orderbooks/generic-asset/{id}
  agg = client.markets.generic_asset_orderbook(
      generic_asset_id=4401,
      subaccount_id=os.environ["MOLECULE_SUBACCOUNT_ID"],
  )
  print("Best bid:", agg["bids"][0] if agg["bids"] else "—")
  print("Best ask:", agg["asks"][0] if agg["asks"] else "—")
  ```
</CodeGroup>

<Tip>
  `markets.generic_asset_orderbook()` is also available as `markets.aggregated_book()` — both call the same endpoint.
</Tip>

***

## Trade History

Query recent trades and market statistics for any instrument.

<CodeGroup>
  ```python Recent trades theme={"dark"}
  # GET /v1/markets/{id}/trades
  trades = client.markets.trades(instrument_id=98712, limit=50)
  for t in trades:
      print(t["price"], t["qty"], t["side"], t["timestamp"])
  ```

  ```python Trade prints theme={"dark"}
  # GET /v1/tradeprints
  prints = client.markets.prints(instrument_id=98712, limit=50)
  for p in prints:
      print(p["price"], p["qty"], p["timestamp"])
  ```

  ```python Market stats theme={"dark"}
  # GET /v1/markets/{id}/stats
  stats = client.markets.stats(instrument_id=98712)
  print("Volume 24h:", stats.get("volume_24h"))
  print("Last price:", stats.get("last_price"))
  print("Open interest:", stats.get("open_interest"))
  ```
</CodeGroup>

<Info>
  `trades()` returns exchange-confirmed fills for a specific instrument. `prints()` returns the global trade-print stream from `/v1/tradeprints` — the same feed available over WebSocket at `/v1/ws/tradeprints`.
</Info>

***

## Price History & Candles

Retrieve OHLCV candles or raw tick prices for charting and model inputs.

<CodeGroup>
  ```python Candles theme={"dark"}
  # GET /v1/candles
  # interval: "1m" | "5m" | "15m" | "1h" | "4h" | "1d"
  candles = client.markets.candles(
      instrument_id=98712,
      interval="1h",
      limit=200,
  )
  for c in candles:
      print(c["t"], c["o"], c["h"], c["l"], c["c"], c["v"])
  ```

  ```python Price ticks theme={"dark"}
  # GET /v1/prices
  prices = client.markets.prices(
      instrument_id=98712,
      type="ticks",
      limit=100,
      interval="1h",
  )
  for p in prices:
      print(p["timestamp"], p["price"])
  ```
</CodeGroup>

### Candle parameters

<ParamField query="instrument_id" type="integer | string" required>
  The venue-specific instrument to retrieve candles for.
</ParamField>

<ParamField query="interval" type="string" default="1h">
  Candle interval. Common values: `1m`, `5m`, `15m`, `1h`, `4h`, `1d`.
</ParamField>

<ParamField query="limit" type="integer" default="500">
  Maximum number of candles to return. Default is `500`.
</ParamField>

### Price parameters

<ParamField query="instrument_id" type="integer | string" required>
  The venue-specific instrument to retrieve prices for.
</ParamField>

<ParamField query="type" type="string" default="ticks">
  Price series type. Use `ticks` for individual price points.
</ParamField>

<ParamField query="limit" type="integer" default="100">
  Maximum number of data points to return.
</ParamField>

<ParamField query="interval" type="string" default="1h">
  Time bucketing interval for aggregated price series.
</ParamField>

***

## Venue Status

Check which venues are live and inspect per-venue health before routing orders.

<CodeGroup>
  ```python List venues theme={"dark"}
  # GET /v1/venues
  venues = client.markets.venues()
  for v in venues:
      print(v["name"], v["status"])
  ```

  ```python Venue health theme={"dark"}
  # GET /v1/venues/health
  health = client.markets.venue_health()
  for entry in health:
      print(entry["venue"], entry["healthy"], entry.get("latency_ms"))
  ```
</CodeGroup>

<Note>
  Live venues are **Demo**, **Polymarket**, and **Kalshi**. Any venue not in this set is unreleased — do not send live orders to it.
</Note>

<Tip>
  Use the `Demo` venue to validate your integration end-to-end — market search, order book fetches, and order submission — without touching live venues or real funds.
</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.