Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.simplefunctions.dev/llms.txt

Use this file to discover all available pages before exploring further.

Use the Real-Time Data API when you need raw market data for a terminal, dashboard, bot, or trading agent. This surface is separate from simplefunctions.dev/api/public/*. The public API is for analytical objects and agent workflows. The data API is for fast market data. Last verified: 2026-04-30.

Base URLs

REST:
https://data.simplefunctions.dev/v1
Current public WebSocket:
wss://app.simplefunctions.dev/ws
Do not use wss://data.simplefunctions.dev/v1/ws yet. It is the intended canonical data-domain WebSocket name, but current routing can return 426 Upgrade Required. Use wss://app.simplefunctions.dev/ws until the WS route is moved off Vercel or a direct WS CNAME is configured.

Data conventions

FieldConvention
PricesProbabilities in [0, 1], not cents.
generated_atUnix seconds.
closeTimeUnix seconds.
tsUnix milliseconds.
CompressionLarge REST responses are gzip-compressed by the origin.

REST endpoints

EndpointUseCache
GET /v1/heartbeatHealth/status payload.max-age=10
GET /v1/markets?q=&venue=Top tracked markets or registry search.max-age=3
GET /v1/markets/featured?n=50Heat-ranked featured markets.max-age=3
GET /v1/markets/{ticker}One market snapshot.max-age=2
GET /v1/search?q=&limit=&venue=&strict=Autocomplete-grade ticker/title search.max-age=5
GET /v1/snapshotCompact full active-universe price snapshot.max-age=2
GET /v1/movers?window=&n=&minVol=&dir=Top price movers over a recent window.max-age=5
GET /v1/orderbook/{ticker}Top-of-book/depth snapshot.max-age=1
GET /v1/candles/{ticker}?tf=1h&limit=500OHLCV candles.max-age=5 or 15 for 1d
GET /v1/trades/{ticker}?limit=50Recent trade prints.max-age=1

Heartbeat

curl "https://data.simplefunctions.dev/v1/heartbeat"
{
  "markets_tracked": 9333,
  "ws_clients": 3,
  "top_volume_market": "KXPRESNOMD-28-GN",
  "uptime_s": 12345,
  "generated_at": 1777553300
}

Markets

curl "https://data.simplefunctions.dev/v1/markets"
curl "https://data.simplefunctions.dev/v1/markets?q=newsom&venue=kalshi"
curl "https://data.simplefunctions.dev/v1/markets/featured?n=50"
curl "https://data.simplefunctions.dev/v1/markets/KXPRESNOMD-28-GN"
Market object:
{
  "ticker": "KXPRESNOMD-28-GN",
  "venue": "kalshi",
  "title": "Will Gavin Newsom be the Democratic Presidential nominee in 2028?",
  "lastPrice": 0.26,
  "volume24h": 12345,
  "closeTime": 1853884800,
  "bestBid": 0.25,
  "bestAsk": 0.27,
  "heat": 81.4
}
curl "https://data.simplefunctions.dev/v1/search?q=newsom&limit=10"
curl "https://data.simplefunctions.dev/v1/search?q=rate%20cut&venue=kalshi&strict=0"
Parameters:
ParameterValuesUse
qstringRequired query.
limit1 to 50Result cap. Default 10.
venuekalshi, polymarketOptional venue filter.
strict1, 0strict=0 enables looser substring matching for short tokens.
Response:
{
  "query": "newsom",
  "results": [
    {
      "ticker": "KXPRESNOMD-28-GN",
      "venue": "kalshi",
      "title": "Will Gavin Newsom be the Democratic Presidential nominee in 2028?",
      "lastPrice": 0.26,
      "volume24h": 12345,
      "score": 400
    }
  ]
}

Raw snapshot

curl "https://data.simplefunctions.dev/v1/snapshot"
Use this for bot cold-start. It intentionally omits title, close time, and heat to keep the payload small. Markets pinned outside [0.01, 0.99] are excluded.
{
  "generated_at": 1777553300,
  "count": 9000,
  "markets": [
    {
      "ticker": "KXPRESNOMD-28-GN",
      "venue": "kalshi",
      "last": 0.26,
      "bid": 0.25,
      "ask": 0.27,
      "vol24h": 12345
    }
  ]
}

Movers

curl "https://data.simplefunctions.dev/v1/movers?window=1h&n=50&minVol=1000&dir=both"
Parameters:
ParameterValuesUse
window1m, 5m, 15m, 1h, 4h, 24h, 1dMove window. Default 1h.
n10 to 200Result cap. Default 50.
minVolnumber24h volume floor. Default 1000.
dirup, down, bothDirection filter. Default both.
/v1/movers is powered by in-memory tick/trade samples. After deploy or reconnect, short windows can return count: 0 until samples accumulate.

Orderbook, candles, trades

curl "https://data.simplefunctions.dev/v1/orderbook/KXPRESNOMD-28-GN"
curl "https://data.simplefunctions.dev/v1/candles/KXPRESNOMD-28-GN?tf=1h&limit=500"
curl "https://data.simplefunctions.dev/v1/trades/KXPRESNOMD-28-GN?limit=50"
Orderbook:
{
  "ticker": "KXPRESNOMD-28-GN",
  "bids": [[0.25, 1200]],
  "asks": [[0.27, 700]],
  "ts": 1777553300123
}
Candles:
{
  "ticker": "KXPRESNOMD-28-GN",
  "timeframe": "1h",
  "candles": [
    { "t": 1777550400000, "o": 0.25, "h": 0.27, "l": 0.24, "c": 0.26, "v": 900 }
  ]
}
Trades:
{
  "ticker": "KXPRESNOMD-28-GN",
  "trades": [
    {
      "ticker": "KXPRESNOMD-28-GN",
      "venue": "kalshi",
      "price": 0.26,
      "size": 10,
      "side": "buy",
      "ts": 1777553300123
    }
  ]
}

WebSocket

const ws = new WebSocket('wss://app.simplefunctions.dev/ws')

ws.addEventListener('open', () => {
  ws.send(JSON.stringify({
    action: 'subscribe',
    topics: [
      'featured',
      'ticker:KXPRESNOMD-28-GN',
      'orderbook:KXPRESNOMD-28-GN',
      'trade:KXPRESNOMD-28-GN',
      'candle:KXPRESNOMD-28-GN:1m'
    ],
  }))
})

ws.addEventListener('message', (event) => {
  const frame = JSON.parse(event.data)
  console.log(frame.type, frame)
})
Subscribe:
{
  "action": "subscribe",
  "topics": [
    "featured",
    "ticker:KXPRESNOMD-28-GN",
    "orderbook:KXPRESNOMD-28-GN",
    "trade:KXPRESNOMD-28-GN",
    "candle:KXPRESNOMD-28-GN:1m"
  ]
}
Unsubscribe:
{
  "action": "unsubscribe",
  "topics": ["ticker:KXPRESNOMD-28-GN"]
}
Legacy single-topic subscribe is also accepted:
{ "action": "subscribe", "ticker": "KXPRESNOMD-28-GN" }

WebSocket topics

TopicFrame typeUse
featuredfeaturedTop-50 heat-ranked list.
ticker:{ticker}ticker_infoLatest price/quote metadata.
orderbook:{ticker}orderbookSorted book snapshot.
trade:{ticker}tradeTrade prints from venue WS.
candle:{ticker}:{tf}candleCandle updates for one timeframe.
{ticker}mixedLegacy topic with ticker/orderbook/trade/candle fan-out.
When subscribing to a ticker topic, the server may send initial cached ticker_info and orderbook frames if available.

Frame shapes

featured:
{
  "type": "featured",
  "markets": [],
  "generated_at": 1777553300
}
ticker_info:
{
  "type": "ticker_info",
  "ticker": "KXPRESNOMD-28-GN",
  "venue": "kalshi",
  "title": "Will Gavin Newsom be the Democratic Presidential nominee in 2028?",
  "last": 0.26,
  "bid": 0.25,
  "ask": 0.27,
  "volume24h": 12345,
  "closeTime": 1853884800
}
orderbook, trade, and candle use the same shapes as the REST examples above, with a top-level type.

Operational notes

  • Public REST callers use https://data.simplefunctions.dev/v1; the edge proxy injects the internal origin token.
  • Direct origin routes at https://app.simplefunctions.dev/api/data/v1/* are edge-token gated and return 403 without the internal token.
  • Anonymous WebSocket connections are capped per IP.
  • The server pings WebSocket clients every 30 seconds and closes stale connections after a failed pong.
  • Kalshi and Polymarket are normalized into one ticker namespace, but not all fields are available from both venues.