API reference

Spreads

Cross-venue price-dislocation events — the same spread pipeline that powers the dashboards, as a curated event stream.

A spread lifecycle emits two event types per key: an `open` event (the first fresh detection above threshold) and a `close` event (the arbiter's one-shot below-threshold signal). Filter with `events=open|close` or take both.

Filter params mirror the SpreadBot per-user config 1:1 — thresholds, type allowlists, exchange allowlists with the same leg semantics, and volume/liquidity gates.

GET recent

Last ≤500 spread events held in memory, filtered.

GET/v1/spreads/recent

Tier: machine-dev (delayed) · builder+ (live)

Query parameters

ParameterTypeDescription
min_pctfloatMinimum spread percent.
max_pctfloatMaximum spread percent.
spread_typestringOne of: futures/futures, spot/futures, spot/spot, dex/futures, spot/dex, dex/dex, internal/futures.
exchangestringMatch either leg on this exchange.
allowed_exchangescsvRestrict both legs to this allowlist.
buy_exchangestringMatch the buy (cheaper) leg only.
sell_exchangestringMatch the sell (dearer) leg only.
symbolstringExact symbol, e.g. BTC_USDT.
exclude_symbolstringBlacklist a symbol.
dexbooltrue → DEX legs only, false → exclude DEX.
min_volume_24hfloatMinimum 24h quote volume on the CEX leg.
min_dex_liquidity_usdfloatMinimum pool liquidity for DEX legs.
eventsstringopen | close — defaults to both.
delayint (s)Hide events fresher than N seconds. Your tier clamps the minimum (see Access tiers).
limitintMax events to return. Capped server-side (recent ≤ 500, history per-tier).

Response

json
{
  "meta": { "trace": "c_4f2a…", "as_of": 1781000000.42, "count": 1, "delay_seconds": 0 },
  "data": [
    {
      "received_at": 1781000000.0,
      "event": "open",
      "symbol": "ZK_USDT",
      "spread_type": "spot/futures",
      "buy_exchange": "MEXC",
      "sell_exchange": "BYBIT",
      "buy_kind": "spot",
      "sell_kind": "futures",
      "buy_price": 0.01423,
      "sell_price": 0.0194,
      "spread_percent": 36.33,
      "volume_24h": 412000.0,
      "buy_mark_price": 0.01421,
      "sell_mark_price": 0.01939
    }
  ]
}

GET history

Durable event log from the analytics store, keyset-paginated.

GET/v1/spreads/history

Tier: machine-dev (delayed) · builder+

Pages are keyset-paginated: pass the returned `meta.next_before` back as `before` to walk further back. `meta.next_before: null` (empty `data`) means you've reached the end.

Query parameters

ParameterTypeDescription
eventsstringopen | close.
allowed_exchangescsvRestrict both legs.
spread_typestringSpread type filter.
min_pctfloatMinimum spread percent.
sinceint (ts)Return events at or after this unix timestamp.
beforeint (ts)Keyset pagination cursor — return events strictly older than this unix timestamp.
limitintMax events to return. Capped server-side (recent ≤ 500, history per-tier).

Response

json
{
  "meta": { "trace": "c_4f2a…", "count": 100, "next_before": 1780990000 },
  "data": [ /* spread events, oldest-first within the page; history rows carry fired_at + is_stale */ ]
}

WS live

Filtered live event stream over WebSocket.

WS/v1/spreads/live

Tier: builder+ (OPEN events min delay ≥ 60s on builder)

Live spread OPEN frames are the most edge-sensitive surface — builder tier clamps the minimum `delay` to 60s; live-without-delay is a Contract conversation.

Query parameters

ParameterTypeDescription
min_pctfloatMinimum spread percent.
spread_typestringSpread type filter.
allowed_exchangescsvLeg allowlist.
dexboolDEX-leg gating.
exclude_symbolstringPer-connection blacklist.
eventsstringopen | close.
delayint (s)Hide events fresher than N seconds. Your tier clamps the minimum (see Access tiers).

Response

json
// Event frames are typed; the curated event is nested under "data":
{ "type": "event", "family": "spreads", "received_at": 1781000000.0,
  "data": { "event": "open", "symbol": "ZK_USDT", "spread_type": "spot/futures",
            "buy_exchange": "MEXC", "sell_exchange": "BYBIT", "spread_percent": 36.33 } }
// First frame:  { "type": "welcome", "family": "spreads", "delay_seconds": 60, "filters": { … }, "trace": "c_4f2a…" }
// Heartbeats:   { "type": "ping" }

Event fields

Payloads are curated — only the fields below are exposed. New upstream fields never leak by default (allowlist policy). Every response carries a per-consumer trace watermark.

ParameterTypeDescription
eventstringopen | close — the lifecycle discriminator (recent/live have no is_stale field).
symbolstringCanonical symbol, e.g. BTC_USDT.
spread_typestringLeg-kind pair: futures/futures · spot/futures · spot/spot · dex/futures · spot/dex · dex/dex · internal/futures.
buy_exchange / sell_exchangestringUppercase exchange of the cheaper / dearer leg.
buy_kind / sell_kindstringLeg market kind — spot | futures | dex.
buy_price / sell_pricefloatLeg prices at detection.
spread_percentfloat|p_a − p_b| / min(p_a, p_b) × 100.
buy_mark_price / sell_mark_pricefloat?Mark prices — open events only.
stale_since_msint?Close events only — when the spread fell below threshold.
dex_metadataobject?Pool address / chain / liquidity when a leg is DEX.
received_atfloatServer receive timestamp — on recent + live frames.
fired_atintDetection timestamp — history rows only (the keyset cursor).