AArtery
On this page

WebSocket Streaming

Artery multiplexes four upstream WebSocket feeds onto a single client connection. You subscribe by provider + market_id, and Artery routes matching events to your client.

Endpoint

wss://api.artery.questflow.ai/v1/stream?token=<your-api-key>

Pass the API key as token= in the query string — the WS spec doesn't carry headers, so this is the standard way to authenticate a browser-initiated connection.

Quick test

bash# Generate a stream-scoped key
TOKEN=$(curl -sS -X POST https://api.artery.questflow.ai/keys \
  -H "Content-Type: application/json" \
  -d '{"name":"ws-test","userId":"u1","scopes":["stream"]}' \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['plaintext'])")
 
# Connect and subscribe (using websocat or wscat)
wscat -c "wss://api.artery.questflow.ai/v1/stream?token=$TOKEN" \
  -x '{"type":"subscribe","channels":["artery:stream:hyperliquid_perp:*"]}'
# → {"type":"subscribed","subscription_id":"..."}
# → {"type":"event","subscription_id":"...","data":{...}}  (every ~50ms)

Wire protocol

Channels are identified by flat strings of the form artery:stream:{provider}:{marketKey}. Use * as marketKey to match all markets for that provider/feed.

json// → server
{
  "type": "subscribe",
  "channels": [
    "artery:stream:polymarket:0xCONDITION_ID",
    "artery:stream:kalshi:KX-T",
    "artery:stream:hyperliquid_perp:BTC",
    "artery:stream:hyperliquid_perp:*"
  ]
}
 
// ← server
{ "type": "subscribed", "subscription_id": "uuid-1" }
 
// streamed events
{
  "type": "event",
  "subscription_id": "uuid-1",
  "data": {
    "type": "hyperliquid.allMids",
    "provider": "hyperliquid_perp",
    "marketId": "BTC",
    "payload": { /* native upstream JSON */ },
    "receivedAt": 1714928400123
  }
}

Each event's type is {provider}.{native_event_type} — for example polymarket.price_change, kalshi.orderbook_delta, hyperliquid.l2Book.

ChannelWhat it carries
artery:stream:hyperliquid_perp:*All HL allMids updates (every ~50ms)
artery:stream:hyperliquid_perp:BTCHL l2Book for BTC perp (when l2Book worker is enabled)
artery:stream:hyperliquid_perp:100000421HIP-4 outcome asset id
artery:stream:polymarket:<token_id>Polymarket price_change / last_trade_price for one token
artery:stream:kalshi:<ticker>Kalshi orderbook_delta (planned — RSA-gated)

Subscription limits

TierConcurrent WS connections
free1
builder5
pro50
enterpriseunlimited

Each connection can hold up to 1000 active subscriptions.

Heartbeat

Every 30 seconds the server pushes a JSON keepalive frame:

json{ "type": "pong" }

Clients don't have to reply — the server tracks the timestamp of any inbound frame as proof-of-life. Connections with no inbound frame for >60 seconds are closed (close code 1001).

Clients can send {"type":"ping"} to bump their last-seen counter and will get back {"type":"pong"} as ack.

json// → server (optional, only if you want to be explicit)
{ "type": "ping" }
 
// ← server
{ "type": "pong" }

Per-provider notes

  • Polymarket: V2 protocol ({ type: 'market', assets_ids, custom_feature_enabled: true })
  • Kalshi: public channels only for now (private channels require RSA upload — planned)
  • Hyperliquid: 1000 subs/conn limit; 10 unique users across user-scoped subs
  • HyperEVM DEX: no WebSocket (HyperEVM RPC doesn't expose WS JSON-RPC) — use polling
Edit this page on GitHubLast updated
WebSocket Streaming · Artery API Docs