Market data

Live Crypto Markets

Discover recurring crypto windows, live depth, and fresh reference prices for partner apps

sufwan-local-test's live crypto market API lets prediction market apps discover recurring crypto markets, inspect visible-window orderbook depth, and fetch fresh underlying reference prices through one integration. Build BTC, ETH, SOL, XRP, DOGE, HYPE, and other crypto market views without wiring every venue's market format and reference-price source separately. Use it for crypto prediction market pages, trading dashboards, agent workflows, and cross-venue price comparison.

Recurring crypto markets are short-window markets such as "BTC up or down in the next 15 minutes". They usually need three separate data shapes:

  1. Market discovery tells you which venue markets exist for an asset and window.
  2. Orderbook depth tells you how much liquidity sits behind the displayed Yes/No odds.
  3. Reference prices tell you the current underlying asset price used to evaluate the market.

Use discovery responses to build cards, tables, and filters. Opt into orderbook depth for the visible rows where you need executable context, then poll the reference-price endpoint when you need the current BTC/USD, ETH/USD, or other underlying price.

Endpoint map

Use caseAPI Reference
Browse all recurring crypto windowsList recurring crypto window markets
Add depth for visible recurring marketsList recurring crypto window markets
Poll current underlying pricesGet live crypto reference prices
Browse all venue events by cadenceList venue events
Fetch live venue orderbooksGet live orderbooks for multiple markets

Reference prices are underlying asset prices, not prediction-market prices. A BTC/USD reference price belongs next to market odds; it should not be treated as a Yes/No midpoint. Orderbook depth is prediction-market liquidity for an outcome, not an underlying asset price.

What you get

  • Deterministic windows grouped by asset, quoteAsset, duration, windowStart, and windowEnd.
  • Venue market rows for each window, including outcomes, midpoint-style market odds, metrics, routeability flags, and reference-price metadata.
  • Optional per-outcome orderbookDepth with buy/sell levels, notional totals, average and worst sweep prices, and fill-completeness fields.
  • Fresh USD reference prices with softRefreshMs, hardMaxAgeMs, ageMs, stale, and target-level error fields so your UI can degrade cleanly.
  • Cross-venue comparison fields for reference prices and up/down outcome prices.

Cadence filters

sufwan-local-test exposes recurrence filters as fixed enum values. There is no separate cadence catalog endpoint to call from your frontend. Venue event discovery accepts the full recurrence enum, while recurring crypto discovery currently supports the short-window crypto durations listed below.

Crypto market durationAPI value
5 minutesPT5M
15 minutesPT15M
30 minutesPT30M
1 hourPT1H
4 hoursPT4H
DailyP1D

durations and interval also accept the friendly aliases 5m, 15m, 30m, 1h, 4h, and 1d for those same windows. Venue-event recurrence is a wider enum and is not this alias list.

Venue event discovery also accepts broader recurrence filters:

LabelAPI value
5 minutesPT5M
10 minutesPT10M
15 minutesPT15M
30 minutesPT30M
1 hourPT1H
4 hoursPT4H
DailyP1D
WeeklyP1W
MonthlyP1M
YearlyP1Y
One-off eventsnull

The SDK exports the supported cadence list:

import { RECURRENCE_CADENCES, MarketStatus } from "@agg-build/sdk";

console.log(RECURRENCE_CADENCES);
// ["PT5M", "PT10M", "PT15M", "PT30M", "PT1H", "PT4H", "P1D", "P1W", "P1M", "P1Y"]

For listRecurringCryptoMarkets, use the RecurringCryptoDuration values PT5M, PT15M, PT30M, PT1H, PT4H, and P1D.

Use these same ISO values with venue event discovery. Calls List venue events.

const { data: events } = await client.getVenueEvents({
  status: [MarketStatus.open],
  recurrence: ["PT5M", "PT15M", "PT30M", "PT1H", "PT4H"],
  limit: 50,
});

There is no recurrence-cadence catalog endpoint. If your integration previously expected a dynamic cadence list, read RECURRENCE_CADENCES from the SDK or use the enum shown in the API reference. Use the literal null only when filtering venue events with no recurring schedule.

1. Create the client

import { createAggClient } from "@agg-build/sdk";

const client = createAggClient({
  baseUrl: "https://api.t.sufwankhalid.com",
  appId: "your-app-id",
});

2. List recurring crypto windows

listRecurringCryptoMarkets groups venue markets by asset, quote asset, duration, and window. Use it for crypto-specific market views where the user expects "current BTC 15m", "current ETH 1h", or similar rows.

SDK
const windows = await client.listRecurringCryptoMarkets({
  assets: ["BTC", "ETH"],
  durations: ["PT15M", "PT30M", "PT1H"],
  window: "current",
  status: [MarketStatus.open],
});

List recurring crypto window markets.

Each returned window includes:

  • asset, quoteAsset, duration, windowStart, and windowEnd
  • markets[], one item per venue market in that window
  • per-market outcomes[] with market odds such as midpoint, bestBid, and bestAsk
  • per-market resolution, which can be passed back when polling reference prices

includeDirectVenueMarkets is deprecated and ignored. Every recurring window is listed from sufwan-local-test's own market data before it opens, so you can drop the parameter; the response is the same with or without it.

3. Add depth for visible markets

Use includeOrderbookDepth when the user is looking at a small, active set of current windows and you need liquidity context next to the displayed odds. Keep it off for broad catalog pages, then opt in for the rows that are actually on screen. Same route as above: List recurring crypto window markets.

const windowsWithDepth = await client.listRecurringCryptoMarkets({
  assets: ["BTC", "ETH"],
  durations: ["PT5M", "PT15M"],
  window: "current",
  status: [MarketStatus.open],
  limit: 20,
  includeOrderbookDepth: true,
  orderbookDepth: 15,
  orderbookDepthAmountUsd: 1000,
});

orderbookDepth accepts 1 through 15 levels per side. orderbookDepthAmountUsd has no fixed public upper cap, but it must be positive. Use the size your UI wants to inspect or simulate. Outcomes without a live book return orderbookDepth: null, so keep the depth display optional.

for (const windowMarket of windowsWithDepth.data) {
  for (const market of windowMarket.markets) {
    for (const outcome of market.outcomes) {
      const depth = outcome.orderbookDepth;
      if (!depth) continue;

      console.log(outcome.label, {
        amountUsd: depth.amountUsd,
        buyLevels: depth.buy.levels.length,
        sellLevels: depth.sell.levels.length,
        buyAverage: depth.buy.avgPrice,
        sellAverage: depth.sell.avgPrice,
      });
    }
  }
}

Use the recurring endpoint for grouped crypto windows. For a dedicated orderbook view or a larger explicit set of venue markets, use the /orderbooks API or WebSocket orderbook stream.

4. Poll reference prices

Use getCryptoReferencePrices with the windows or markets returned by discovery. The SDK will build the correct target payload for each venue market. Calls Get live crypto reference prices.

const prices = await client.getCryptoReferencePrices({
  windowMarkets: windows.data,
});

for (const row of prices.data) {
  if (row.error) {
    console.warn(row.venueMarketId, row.error.code, row.error.message);
    continue;
  }

  console.log(row.venueMarketId, {
    asset: row.asset,
    price: row.normalized,
    fetchedAt: row.fetchedAt,
    ageMs: row.ageMs,
  });
}

The response includes softRefreshMs and hardMaxAgeMs. Use softRefreshMs as your normal poll interval for active views. Treat any row with error, stale: true, or a null normalized price as unavailable for display. Chainlink-sourced rows can be up to 2 seconds old (Chainlink publishes about once a second); judge freshness by each row's stale flag rather than comparing ageMs to hardMaxAgeMs.

async function pollReferencePrices() {
  const response = await client.getCryptoReferencePrices({ windowMarkets: windows.data });

  renderReferencePrices(response.data);

  window.setTimeout(pollReferencePrices, response.softRefreshMs);
}

void pollReferencePrices();

5. Match prices back to markets

Reference-price rows include the same venue-facing identifiers you already have from discovery. Index by venueMarketId for normal UI work.

const byVenueMarketId = new Map(
  prices.data
    .filter((row) => !row.error && row.venueMarketId)
    .map((row) => [row.venueMarketId!, row]),
);

for (const windowMarket of windows.data) {
  for (const market of windowMarket.markets) {
    const reference = byVenueMarketId.get(market.venueMarketId);

    console.log({
      venue: market.venue,
      question: market.question,
      underlying: reference?.normalized ?? null,
      upMidpoint: market.outcomes.find((o) => o.label.toLowerCase() === "up")?.midpoint,
      downMidpoint: market.outcomes.find((o) => o.label.toLowerCase() === "down")?.midpoint,
    });
  }
}

API reference

Use the generated API Reference for request parameters, response schemas, and try-it-out examples:

Use caseAPI Reference
Discover recurring crypto windowsList recurring crypto window markets
Add orderbook depth to visible windowsList recurring crypto window markets
Poll current underlying pricesGet live crypto reference prices
Browse venue events by recurrenceList venue events

Trading behavior

Recurring crypto discovery can include venue markets that are useful for display but not valid inputs to sufwan-local-test smart order routing. Check these fields before enabling trade controls:

  • market.routeable
  • market.splitOrdersAllowed
  • outcome.routeable
  • outcome.splitOrdersAllowed

If routeable is false, do not pass that market to smart routing. If splitOrdersAllowed is false, do not split an order across venues for that market.

Integration notes

  • Reference prices are USD-only (quoteAsset: "USD") and are separate from prediction-market odds.
  • listRecurringCryptoMarkets supports deterministic crypto durations: PT5M, PT15M, PT30M, PT1H, PT4H, and P1D, plus aliases 5m, 15m, 30m, 1h, 4h, and 1d.
  • getCryptoReferencePrices accepts up to 100 targets. For active views, pass the visible windows or venue market ids rather than polling every discovered market.
  • Prefer getCryptoReferencePrices for live reference-price polling. The discovery endpoint can include reference prices, but the dedicated polling endpoint is built for fresh active views.
  • Use includeOrderbookDepth only for visible rows that need liquidity context. Depth is capped at 15 levels per side, and orderbookDepthAmountUsd must be greater than 0.
  • Treat rows with error, stale: true, or normalized: null as unavailable for display.
  • source.confidence can be verified, inferred, or missing. Show low-confidence or missing sources conservatively in production trading experiences.
  1. Call listRecurringCryptoMarkets for the current window and render the market cards.
  2. Include orderbookDepth only for rows where the user needs liquidity or sweep context.
  3. Call getCryptoReferencePrices for the visible windows.
  4. Display market odds, orderbook depth, and reference prices as separate values.
  5. Poll reference prices using softRefreshMs while the view is visible.
  6. Stop polling when the user leaves the view or the window status is no longer open.

FAQ

Are reference prices the same as market prices?

No. Reference prices are underlying crypto prices, such as BTC/USD or ETH/USD. Market prices are the prediction market odds for outcomes such as Up or Down. Orderbook depth is liquidity behind those outcome prices.

Which crypto windows are supported?

The recurring crypto endpoint supports PT5M, PT15M, PT30M, PT1H, PT4H, and P1D, and the aliases 5m, 15m, 30m, 1h, 4h, and 1d. Venue event discovery can still filter broader recurrence cadences, but this crypto-specific endpoint is intentionally scoped to deterministic recurring crypto windows.

What should I do when a reference price is stale or unavailable?

Do not render it as a current price. Hide it, show an unavailable state, or keep the last accepted value visually distinct from live data. Always read error, stale, ageMs, and normalized before displaying a reference price.

On this page