Welcome to API Academy

Module 04 · API basics · ~20 min

Markets.

By the end of this module, your bot will be able to scan every market on Limitless and pick out the few worth trading, the same filter a human trader runs in their head before risking a dollar.

To get there, you’ll list, filter, and inspect every market on Limitless, then map each response into a typed model. Point your bot at exactly the markets you care about instead of scanning thousands of rows you’ll never trade.

API basics tier · Reference card
Quick answer

How do you list markets on the Limitless API?

GET /markets/active, wrapped by the SDK’s MarketFetcher.getActiveMarkets(), returns the catalogue a page at a time with typed params: limit, page, sortBy (newest, trending, or ending-soon), and tradeType (clob or amm). Push filters to the server instead of scanning everything: adding categoryId or tradeType to the query turns a 2,000-row scan into a 50-row page, and you walk pages until one comes back short. Once you have a slug, GET /markets/{slug} returns the full object, resolution source, outcome tokens, and the rest, to map into a typed model your bot can reason about. One trap: status “active” doesn’t mean tradeable, so filter on the explicit tradingEnabled field and refresh your cached list on a 60s cadence. Prefer the slug over the numeric id in most calls; slugs are stable and keep logs readable.

Endpoints verified 2026-06-09 against the OpenAPI spec + SDK.

Section 01

Listing markets.

GET /markets/active is the first endpoint any bot touches. Page through the catalogue, sort by newest or most-traded, and filter by the shape of market you care about. The SDK’s MarketFetcher wraps it with typed params.

How to run this

  1. Make sure LIMITLESS_API_KEY is set in your environment (same one from Module 03).
  2. Save the snippet as list-markets.ts, then run npx tsx list-markets.ts.
  3. You see a count of fetched markets followed by one line per market showing its slug, volume, and liquidity.
// Module 04, Listing Markets
// Fetch the first page of active markets, sorted by newest.

import { HttpClient, MarketFetcher } from '@limitless-exchange/sdk';

const httpClient = new HttpClient({
  baseURL: 'https://api.limitless.exchange',
  apiKey:  process.env.LIMITLESS_API_KEY,
});

async function listMarkets() {
  const marketFetcher = new MarketFetcher(httpClient);

  const markets = await marketFetcher.getActiveMarkets({
    limit:    25,
    page:     1,
    sortBy:   'newest',          // 'newest' | 'trending' | 'ending-soon'
    tradeType: 'clob',           // 'clob' | 'amm'
  });

  console.log(`Fetched ${markets.length} active markets`);
  for (const m of markets) {
    console.log(`${m.slug.padEnd(40)} vol=${m.volume} liq=${m.liquidity}`);
  }
}

listMarkets().catch(console.error);

Section 02

Market metadata.

Every market object you get back carries the same shape. Understand these fields once and you can write code against any endpoint without guessing.

Identity

  • id · numeric primary key
  • slug · human URL (use this in most calls)
  • address · on-chain contract address
  • conditionId · CTF condition hash
  • title · the human-readable question

State & economics

  • status · active · closed · resolved
  • expired · boolean past-deadline flag
  • tradeType · clob · amm
  • marketType · binary · categorical · group
  • volume · lifetime traded USDC
  • openInterest · outstanding notional
  • liquidity · quoted depth at touch

Prefer slug over id in most calls.

Slugs are stable and human-readable; logs and bug reports stay sane. The id field is fine for local caches or when you need a compact key.

Section 03

Filtering & pagination.

Don’t fetch the whole catalogue just to find one subset. Push filters to the server and walk pages with page + limit until the last page comes back short, or until you’ve got enough.

// Module 04, Filtering & Pagination
// Page through every active CLOB market in a category.

import { HttpClient, MarketFetcher } from '@limitless-exchange/sdk';

const httpClient = new HttpClient({ apiKey: process.env.LIMITLESS_API_KEY });
const marketFetcher = new MarketFetcher(httpClient);

async function* iterateMarkets(categoryId: number) {
  let page = 1;
  const limit = 50;

  while (true) {
    const markets = await marketFetcher.getActiveMarkets({
      page,
      limit,
      categoryId,
      tradeType: 'clob',
      sortBy:    'trending',
    });

    if (markets.length === 0) return;
    for (const m of markets) yield m;
    if (markets.length < limit) return; // last page
    page += 1;
  }
}

async function main() {
  let seen = 0;
  for await (const m of iterateMarkets(7 /* crypto */)) {
    seen += 1;
    if (m.liquidity > 10_000) console.log(m.slug, m.liquidity);
  }
  console.log(`Scanned ${seen} markets`);
}

main().catch(console.error);

How to run this

  1. Keep LIMITLESS_API_KEY in your environment. Pick a real categoryId, 7 is the illustrative crypto value; check GET /markets/categories/count for live ids.
  2. Save the snippet above as iterate-markets.ts, then run npx tsx iterate-markets.ts.
  3. Any market with liquidity above $10k prints its slug and depth, followed by a final Scanned N markets count.

Don’t scan everything when you want one subset.

Pushing categoryId, tradeType, or automationType into the query turns a 2,000-row scan into a 50-row page. Module 09 covers the rate-limit math; push filters now and you won’t hit them later.

Section 04

Market detail.

Once you have a slug, GET /markets/{slug} returns the full object: resolution source, outcome tokens, and everything you need to build a typed model. Map it into your domain so the rest of your bot doesn’t touch raw JSON.

// Module 04, Market Detail
// Fetch a single market and map it into a typed model.

import { HttpClient, MarketFetcher } from '@limitless-exchange/sdk';

const httpClient = new HttpClient({ apiKey: process.env.LIMITLESS_API_KEY });
const marketFetcher = new MarketFetcher(httpClient);

interface Market {
  slug:       string;
  title:      string;
  tradeType:  'clob' | 'amm';
  isLive:     boolean;
  volume:     number;
  liquidity:  number;
}

function toMarket(raw: any): Market {
  return {
    slug:      raw.slug,
    title:     raw.title,
    tradeType: raw.tradeType,
    isLive:    raw.status === 'active' && !raw.expired,
    volume:    Number(raw.volume    ?? 0),
    liquidity: Number(raw.liquidity ?? 0),
  };
}

async function main() {
  const raw    = await marketFetcher.getMarket('will-btc-close-above-100k-eoy');
  const market = toMarket(raw);
  console.log(market);
}

main().catch(console.error);

How to run this

  1. Keep LIMITLESS_API_KEY set. Swap will-btc-close-above-100k-eoy for a real slug you grabbed in Section 01.
  2. Save the snippet above as market-detail.ts, then run npx tsx market-detail.ts.
  3. A typed Market object prints with slug, title, tradeType, isLive, volume, and liquidity, all strongly typed, ready to pass into the rest of your bot.
Common questions

Limitless markets endpoints: what people ask

Each answer also ships invisibly as schema.org FAQ data for search engines and AI assistants. Tap a question to expand.

  1. What fields are on a Limitless market object?
    Identity: id (numeric primary key), slug (human URL, use this in most calls), address (on-chain contract), conditionId (CTF condition hash), and title (the human-readable question). State and economics: status (active, closed, resolved), expired, tradeType (clob or amm), marketType (binary, categorical, group), volume (lifetime traded USDC), openInterest, and liquidity (quoted depth at touch). Learn the shape once and every endpoint stops being guesswork.
  2. Does status “active” mean a Limitless market is tradeable?
    No. A market can be listed-but-inactive: pre-launch, post-resolution, or paused for compliance. Filter on status alone and your bot still quotes on rows where tradingEnabled = false; the order is rejected, the loop logs an error, and the bot keeps trying. Filter on the explicit tradingEnabled field, cache the markets-list response, and refresh on a 60s cadence, markets transition mid-session more often than you’d expect.
  3. How does pagination work on /markets/active?
    Walk page + limit until the last page comes back short (fewer rows than limit), or until you’ve got enough. Push categoryId, tradeType, or automationType into the query so the server does the filtering; that’s what turns a 2,000-row scan into a 50-row page. Check GET /markets/categories/count for live category ids instead of hard-coding one.
  4. Should your bot use the market slug or the numeric id?
    Prefer slug in most calls. Slugs are stable and human-readable, so logs and bug reports stay sane, and GET /markets/{slug} takes the slug directly. The numeric id is fine for local caches or when you need a compact key, but it tells you nothing when it shows up in a stack trace.
  5. How do you turn a raw market response into a typed model?
    Fetch the full object with getMarket(slug) and map it once into your own type, so the rest of the bot never touches raw JSON. The module’s example keeps slug, title, tradeType, volume, liquidity, and an isLive flag that collapses status-is-active and not-expired into one check. One mapping function per endpoint keeps schema drift in one place.

Section 05

Module checklist.

Tick each item once you’ve actually done it. The Continue button unlocks at 5/5.

Module 04 complete

Markets mapped.

Your bot is no longer flying blind. It can ask the exchange what’s open, what’s liquid, and what category each market falls in, the cheapest possible step to stop it from chasing markets it has no edge in.

Concretely, you can find any market on Limitless and turn its JSON into something your bot can reason about. Three things you walk away with:

01

A typed Market model you can import into any future bot, slug, tradeType, volume, liquidity, and an isLive flag that collapses status + expired into one check.

02

A paginated scanner that pushes categoryId, tradeType, and sortBy to the server instead of downloading the full catalogue every time.

03

A concrete answer to “which markets should my bot touch?”, filter by depth, category, or trade type and hand the result to your strategy.

Next up: teaching your bot to actually trade. Module 05 is limit orders that rest, FOK orders that cross, and the cancel paths your bot needs when the book moves against it.

Complete the checklist above to unlock