Market Data

Public endpoints for market data. No authentication required for most endpoints.

Best Bid/Offer (BBO)

GET /v1/market-data/:market_id/bbo?outcome_index=0

Returns the best bid and ask for a market.

Response

{
  "market_id": "...",
  "outcome_index": 0,
  "best_bid": "0.48",
  "best_ask": "0.52",
  "spread": "0.04",
  "midpoint": "0.50",
  "timestamp": 1709136000
}

spread is best_ask - best_bid; midpoint is (best_bid + best_ask) / 2; timestamp is the Unix-second snapshot. For depth sizes, query the order book at GET /v1/orders/book/:market_id.

Batch BBO

POST /v1/market-data/bbo

Get BBO for multiple markets in a single request (up to 50). The body is a JSON array of { market_id, outcome_index } objects — one entry per (market, outcome) tuple.

Request Body

[
  { "market_id": "market-id-1", "outcome_index": 0 },
  { "market_id": "market-id-2", "outcome_index": 0 }
]
FieldTypeRequiredDescription
market_idstringYesMarket UUID
outcome_indexintYesOutcome index (0 = Yes, 1 = No)

Response

{
  "markets": [
    {
      "market_id": "market-id-1",
      "outcome_index": 0,
      "best_bid": "0.48",
      "best_ask": "0.52",
      "spread": "0.04",
      "midpoint": "0.50",
      "timestamp": 1709136000
    }
  ]
}

Spread

GET /v1/market-data/:market_id/spread?outcome_index=0

Returns the bid-ask spread for a market.

Response

{
  "market_id": "...",
  "outcome_index": 0,
  "spread": "0.04",
  "spread_bps": 400,
  "best_bid": "0.48",
  "best_ask": "0.52"
}

Midpoint

GET /v1/market-data/:market_id/midpoint?outcome_index=0

Returns the midpoint price between best bid and ask.

Response

{
  "market_id": "...",
  "outcome_index": 0,
  "midpoint": "0.50"
}

Tick Size

GET /v1/market-data/:market_id/tick-size

Returns the minimum price increment for a market.

Response

{
  "market_id": "...",
  "tick_size": "0.01"
}

Fee Rate

GET /v1/market-data/:market_id/fee-rate

Scope: read:account (Authenticated)

Returns the maker and taker fee rates for the authenticated user in a specific market.

Response

{
  "market_id": "...",
  "maker_fee_bps": 0,
  "taker_fee_bps": 50,
  "maker_fee_pct": "0.00",
  "taker_fee_pct": "0.50"
}

The *_bps fields are the on-chain integer values; the *_pct fields are pre-rendered percentage strings (basis points ÷ 100) for UI display.

Recent Fills (cross-market tape)

GET /v1/markets/fills/recent

Public — No authentication required.

Returns the most recent matched fills across every market, pseudonymized for public consumption. Powers the Sharp-money live tape on the Home page.

Query Parameters

ParameterTypeDescription
limitintNumber of fills (default 50, max 200).
sincestringRFC 3339 timestamp — return fills newer than this.
min_size_usdnumberInclusive lower bound on fill notional in USD. Default unset (no floor). Cap 1,000,000.

Default-shape requests (limit=50, no since, no min_size_usd) share a 10s Redis cache. Any filter param bypasses the cache.

Response

Example values are illustrative; a cold-start exchange returns an empty fills array.

{
  "fills": [
    {
      "market_id": "…",
      "market_title": "Will the Fed cut rates in June 2026?",
      "outcome": "Yes",
      "side": "BUY",
      "size_usd": "1245.32",
      "price_cents": "73",
      "user_handle": "anon-1A2F",
      "category": "Politics",
      "filled_at": "2026-05-22T09:58:11Z"
    }
  ],
  "next_cursor": null
}

user_handle is either the trader's opted-in public username or a stable anon-XXXX pseudonym (same user → same anon across the tape and the Top Traders leaderboard). size_usd and price_cents are strings (not floats) to preserve precision; parse price_cents as an integer for American-odds rendering.

Changelog

  • 2026-05-23: Removed trade_id from the /v1/markets/fills/recent response payload (audit P2-6, PR #5820). External consumers using this field for client-side keying should switch to the (market_id, filled_at) tuple, which is unique per fill on the public tape.

Platform Pulse (24h aggregates)

GET /v1/markets/stats/pulse

Public — No authentication required.

Three rolling-24h platform aggregates plus a 24-bucket hourly tape. Powers the Home PulseHero band. 30s Redis-cached.

Response

Example values are illustrative; a cold-start exchange returns 0 for every aggregate and a flat (all-zero) tape_24h.

{
  "volume_24h_delta_pct": 0.182,
  "active_traders_24h": 4129,
  "settled_today_usd": "284512.00",
  "volume_24h_delta": 0.182,
  "traders_online_24h": 4129,
  "settled_today_usdc": 284512.00,
  "total_volume_24h": 1438201.55,
  "active_markets": 312,
  "active_markets_delta": 0.041,
  "traders_online_delta": -0.018,
  "tape_24h": [
    { "hour": "2026-05-21T10:00:00Z", "volume_usdc": 48211.10 }
  ]
}

All *_delta* fields are signed fractions (+0.182 = +18.2% vs the prior 24h block). Cold-start (prior window zero) returns 0, never Inf. tape_24h always carries exactly 24 hourly buckets, oldest first.

Category Spotlight

GET /v1/markets/stats/category-spotlight?window=7d

Public — No authentication required.

Top categories by trade volume over the requested window with a signed delta vs the prior window of equal length. Powers the Home BentoWall category-spotlight tile. 5min Redis-cached.

Example values are illustrative; a cold-start exchange returns an empty categories array.

Query Parameters

ParameterTypeDescription
windowstring7d (v1 supports only 7d). Default 7d.

Response

{
  "window": "7d",
  "categories": [
    {
      "category": "AI",
      "volume_usdc": 412305.18,
      "volume_delta_pct": 0.143,
      "market_count": 47
    }
  ]
}

Results are sorted by volume_usdc desc and capped at 10. volume_delta_pct follows the same cold-start defense (0, never Inf) as /stats/pulse.

Top Traders Leaderboard

GET /v1/leaderboards/traders?window=7d&limit=10

Public — No authentication required.

Top traders by realized P&L over the requested window, pseudonymized for public consumption. Powers the Home Leaderboards region.

Query Parameters

ParameterTypeDescription
windowstring24h | 7d | 30d | all — default 7d. all is bounded server-side at 365d.
limitintDefault 10, max 100.

Default-shape requests (limit=10) share a 30s Redis cache per window.

Response

Example values are illustrative; a cold-start exchange returns an empty traders array.

{
  "window": "7d",
  "traders": [
    {
      "handle": "anon-9F2C",
      "user_id": null,
      "avatar_url": null,
      "pnl_usdc": 1845.21,
      "roi": 0.18,
      "trade_count": 42
    }
  ]
}

handle is the opted-in public username or a stable anon-XXXX pseudonym (consistent with the recent-fills tape). user_id is non-null only when the trader has opted into a public profile — returning it alongside an anon handle would defeat the pseudonym. roi is a fraction (0.18 = +18%).

Server Time

GET /v1/time

Public — No authentication required.

Returns the server's current Unix timestamp. Use this to synchronize your clock for HMAC signatures.

{
  "time": 1709136000
}