Sequence/docs

Real-Time Streams

Sequence streams every kind of real-time event through a single multiplexed WebSocket: /v1/stream. You subscribe to topics, you get JSON envelopes, you cancel by topic, you keep one connection open.

For consumers who only want one specific feed (TCA reports, alert triggers, prediction-market lifecycle), there are dedicated endpoints listed near the bottom of this page.

Tip

If you're integrating for the first time, start with /v1/stream and subscribe to the topics you need. One connection serves prices, books, orders, fills, routing decisions, TCA, fair price, traces, and funding rates.


Authentication

All streams require Authorization: Bearer seq_live_....

For browser clients that can't set headers on a WebSocket connect, exchange your bearer token for a short-lived ticket first:

code
GET /v1/ws/ticket
→ {"ticket": "wst_abcd1234..."}

# Then connect:
wss://api.sequencemkts.com/v1/stream?ticket=wst_abcd1234...

Tickets expire after 30 seconds and are consumed on first use.

Warning

Query-parameter auth (?api_key=...) was removed for security. Use the Authorization: Bearer header for non-browser clients, or ?ticket= for browsers.


Unified Stream

GET/v1/stream

A single WebSocket. Subscribe to topics. Receive JSON envelopes shaped:

json
{"channel": "<topic>", "data": { ... }}

Subscribe / unsubscribe

json
// Subscribe to one or more topics
{"subscribe": ["prices:BTC-USD", "book:BTC-USDT", "orders", "fair_price:BTC"]}
 
// Unsubscribe
{"unsubscribe": ["prices:BTC-USD"]}

The server responds with an ack listing accepted topics and any rejections:

json
{"subscribed": ["prices:BTC-USD", "book:BTC-USDT", "orders", "fair_price:BTC"], "rejected": []}

Topic catalog

TopicSourcePayload
prices:<symbol>NBBO updates (best bid/ask across all venues)One mid + best per side, per update
book:<symbol>TopBook L2 updates per venueUp to 10 levels per side, per venue, per update
ordersParent-order lifecycle (snapshots when state changes)Full order shape: id, status, qty, fills, etc.
fillsPer-fill events from every venueqty, price, fee, venue, timestamps, TCA breakdown
routingSOR routing decisions when CC allocates an orderAllocation per child venue, score, version
tcaPost-completion TCA report per parent orderSlippage, IS, savings, achieved vs benchmark
traces:<deployment_id>Per-callback traces from a hosted strategy or WASM algoFunction/payload/timing, scoped to one deployment
funding / funding:<venue> / funding:<venue>:<symbol>Perp funding rate updatesRate bps/hr, predicted, mark, OI, next-settlement
fair_price / fair_price:<underlying>Cross-venue Chainlink-style consolidated reference pricecomposite mid, spot/perp legs, basis_bps, contributors

prices:, book:, funding:, fair_price:, traces: accept a suffix to filter; subscribing to funding (no suffix) means "all venues, all symbols", subscribing to fair_price means "all underlyings".

Example: prices + book + fair_price

python
import asyncio, json, websockets
 
async def main():
    headers = {"Authorization": f"Bearer {API_KEY}"}
    async with websockets.connect(
        "wss://api.sequencemkts.com/v1/stream",
        additional_headers=headers,
    ) as ws:
        await ws.send(json.dumps({
            "subscribe": ["prices:BTC-USD", "book:BTC-USDT", "fair_price:BTC"]
        }))
        async for msg in ws:
            evt = json.loads(msg)
            print(evt["channel"], evt["data"])
 
asyncio.run(main())

Topic payload shapes

prices:<symbol> — NBBO updates:

json
{
  "channel": "prices:BTC-USD",
  "data": {
    "symbol": "BTC-USD",
    "instrument_type": "spot",
    "best_bid_px_1e9": 76410000000000,
    "best_bid_sz_1e8": 12000000,
    "best_bid_venue": "coinbase",
    "best_ask_px_1e9": 76411000000000,
    "best_ask_sz_1e8": 8000000,
    "best_ask_venue": "kraken",
    "spread_bps": 1,
    "ts_ns": 1745979000123456789
  }
}

book:<symbol> — per-venue L2 updates (top 10 levels):

json
{
  "channel": "book:BTC-USDT",
  "data": {
    "symbol": "BTC-USDT",
    "venue": "binance",
    "instrument_type": "spot",
    "bids": [["76410.50", "0.421"], ["76410.40", "1.2"], ...],
    "asks": [["76411.00", "0.155"], ["76411.10", "0.8"], ...],
    "ts_ns": 1745979000123456789,
    "is_snapshot": false,
    "checksum": 1448524378
  }
}

Each tick is one venue's L2 update. The same symbol can stream from multiple venues, multiplexed on the same book:<symbol> topic — differentiate by the venue and instrument_type fields.

FieldSemantics
is_snapshottrue only on the initial book frame after subscribe / reconnect (a fresh full state). false for every subsequent delta. Clients tracking their own L2 state should reset on true and apply incrementally on false.
checksumOptional 32-bit integrity fingerprint, populated for venues that publish one (Polymarket today; truncated SHA-1 of the venue's book hash). Use as an opaque equality check for divergence detection across consecutive ticks of the same state. null for venues that don't report.

fair_price:<underlying> — Chainlink-style consolidated reference (see Market Data → Fair Price for the full payload shape).

json
{
  "channel": "fair_price:BTC",
  "data": {
    "underlying": "BTC",
    "fair_mid_1e9": 76405095000000,
    "spot_mid_1e9": 76407250000000,
    "perp_mid_1e9": 76357950000000,
    "basis_bps": -6,
    "confidence": 0.665,
    "contributors": [
      {"venue": "binance", "instrument_type": "spot", "mid_1e9": 76407250000000, "weight": 0.84, "staleness_ms": 96},
      {"venue": "binance", "instrument_type": "perp", "mid_1e9": 76357950000000, "weight": 0.81, "staleness_ms": 79},
      {"venue": "okx", "instrument_type": "spot", "mid_1e9": 76406500000000, "weight": 0.78, "staleness_ms": 156},
      {"venue": "hyperliquid", "instrument_type": "perp", "mid_1e9": 76354500000000, "weight": 0.65, "staleness_ms": 226}
    ],
    "cc_ts_ns": 1745979000123456789
  }
}

orders — parent-order snapshots:

json
{
  "channel": "orders",
  "data": {
    "parent_id": "P-a1b2c3d4-...",
    "client_order_id": "order-001",
    "symbol": "BTC-USD",
    "side": "BUY",
    "qty_1e8": 1000000,
    "filled_qty_1e8": 1000000,
    "status": "COMPLETED",
    "created_unix_ns": 1745979000000000000,
    "updated_unix_ns": 1745979001200000000
  }
}

fills — per-fill events with embedded TCA breakdown:

json
{
  "channel": "fills",
  "data": {
    "parent_id": "P-a1b2c3d4-...",
    "child_id": "C-...",
    "edge_id": "venue-edge-kraken",
    "symbol": "BTC-USD",
    "side": "BUY",
    "qty_1e8": 700000,
    "price_1e9": 76410000000000,
    "fee_1e9": 100000000,
    "exchange_ts_ns": 1745979000498000000
  }
}

routing — SOR allocation decisions:

json
{
  "channel": "routing",
  "data": {
    "ts_unix_ns": 1745979000100000000,
    "parent_id": "P-a1b2c3d4-...",
    "symbol": "BTC-USD",
    "routing_version": 2,
    "children": [
      {"child_id": "C-...", "edge_id": "venue-edge-kraken", "qty_1e8": 700000, "status": "PENDING"}
    ]
  }
}

tca — post-completion TCA report (also exposed as a dedicated SSE at /v1/tca/stream):

json
{
  "channel": "tca",
  "data": {
    "node_order_id": "graph:graph_…:kalshi_yes:1",
    "client_id": "muhammad",
    "symbol": "BTC-USD",
    "side": "BUY",
    "achieved_vwap_1e9": 76411000000000,
    "expected_fill_1e9": 76410500000000,
    "total_fees_1e9": 7641000,
    "fee_cost_bps": 1,
    "expected_fee_bps": 2,
    "fee_prediction_error_bps": -1,
    "spread_cost_bps": 0,
    "market_impact_bps": -1,
    "implementation_shortfall_bps": 0,
    "savings_vs_benchmark_bps": 1,
    "is_prediction": false,
    "execution_time_ms": 124,
    "num_fills": 1
  }
}

Prediction-market fills carry four extra fields:

FieldMeaning
is_predictiontrue for any prediction-venue fill, false (or omitted) otherwise
achieved_implied_prob_bpsAchieved fill price translated to implied probability (e.g. 300 = 3.00%)
arrival_implied_prob_bpsArrival mid translated the same way
probability_slippage_bpsarrival_implied_prob_bps - achieved_implied_prob_bps (sign-flipped for sells)

funding / funding:<venue> / funding:<venue>:<symbol> — perp funding rate updates:

json
{
  "channel": "funding:binance",
  "data": {
    "venue": "binance",
    "symbol": "BTC-USDT",
    "rate_bps_per_hour": 1,
    "predicted_rate_bps_per_hour": 1,
    "mark_price_1e9": 76410000000000,
    "open_interest_1e8": 12000000000,
    "next_settlement_ns": 1745982600000000000,
    "ts_ns": 1745979000000000000
  }
}

traces:<deployment_id> — per-callback traces from a hosted strategy or WASM algo, scoped to one deployment.

Lagged-client semantics

Each client gets a 4096-entry per-topic buffer. A slow consumer that backs up will receive a Gap event indicating how many messages were dropped, then resume from current. Don't write retry-on-gap loops — bring your own ordering or watermark and re-snapshot via REST if you fell behind.


Dedicated SSE Endpoints

These are kept for one-off integrations that don't want a WS connection. Every event published on these is also available as a topic on /v1/stream — prefer the unified WS unless you have a specific reason to use the SSE.

TCA Reports

GET/v1/tca/stream

Same payload as the tca topic on /v1/stream. SSE event name: tca_report.

Alert Triggers

GET/v1/alerts/stream

User-defined rule triggers. SSE event name: alert.


Prediction-Market Lifecycle WebSocket

A separate WebSocket that emits prediction-market lifecycle events as they happen on Polymarket and Kalshi. No subscribe message — connecting is the subscription. Each connection first replays the last 128 events, then streams live.

Events are deduped across multi-region edges by (venue, condition_id). The server sends a WS ping every 30 s so idle proxies don't close the connection.

Auth: Authorization: Bearer seq_live_... on the WS upgrade, or ?ticket=... for browsers.

New Markets

GET/v1/ws/new_markets

Every freshly-minted prediction market. For Polymarket, frames are enriched asynchronously via the CLOB /markets/<conditionId> endpoint before broadcast — slug, start_ts_s, end_ts_s, neg_risk, and fee_schedule arrive populated.

json
{
  "kind": "new_market",
  "venue": "polymarket",
  "slug": "will-btc-close-above-100k-on-2026-04-30",
  "condition_id": "0xabc123...",
  "question": "Will BTC close above $100k on April 30, 2026?",
  "outcomes": ["Yes", "No"],
  "outcome_token_ids": ["7342...", "8913..."],
  "neg_risk": false,
  "tick_1e9": 10000000,
  "fee_schedule": {
    "exponent": -4,
    "rate_1e8": 0,
    "taker_only": false,
    "rebate_rate_1e8": 0
  },
  "start_ts_s": 1745971200,
  "end_ts_s": 1746057600,
  "observed_at_ns": 1745971205123456789
}

Minimal Consumer Example

python
import asyncio, json, websockets
 
async def main():
    url = "wss://api.sequencemkts.com/v1/ws/new_markets"
    async with websockets.connect(
        url, additional_headers={"Authorization": f"Bearer {API_KEY}"}
    ) as ws:
        async for raw in ws:
            evt = json.loads(raw)
            print(evt["venue"], evt["slug"], evt["question"])
 
asyncio.run(main())

SDK wrappers: seq.stream_new_markets() (Python) · stream_new_markets() (Rust).


End-to-End Order Lifecycle Example

Submit an order, then watch its full lifecycle on one WebSocket connection:

python
import asyncio, json, websockets, requests
 
API_BASE = "https://api.sequencemkts.com"
API_KEY = "seq_live_..."
 
# 1. Submit
order = requests.post(
    f"{API_BASE}/v1/orders",
    headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
    json={"client_order_id": "demo-001", "side": "buy", "symbol": "BTC-USD", "qty_1e8": 1_000_000},
).json()
parent_id = order["parent_id"]
 
# 2. Watch the lifecycle on one connection
async def watch():
    async with websockets.connect(
        f"{API_BASE.replace('https', 'wss')}/v1/stream",
        additional_headers={"Authorization": f"Bearer {API_KEY}"},
    ) as ws:
        await ws.send(json.dumps({"subscribe": ["orders", "routing", "fills", "tca"]}))
        async for raw in ws:
            evt = json.loads(raw)
            ch, data = evt["channel"], evt["data"]
            if data.get("parent_id") != parent_id:
                continue
            print(ch, data.get("status") or data)
            if ch == "tca":  # final report — we're done
                return
 
asyncio.run(watch())