AArtery
On this page

Streaming Quickstart

This recipe walks through:

  1. Creating a stream-scoped API key
  2. Connecting to /v1/stream
  3. Subscribing to Hyperliquid allMids + Polymarket book on one connection
  4. Handling pings and reconnecting cleanly

You'll need websocat or any WS client.

  1. Mint a stream-scoped key
    bashTOKEN=$(curl -sS -X POST https://api.artery.questflow.ai/keys \
      -H "Content-Type: application/json" \
      -d '{"name":"stream-recipe","userId":"u-1","scopes":["stream"]}' \
      | jq -r .plaintext)

    The token must include the stream scope or the WS upgrade returns 403 forbidden_scope.

  2. Connect
    bashwebsocat "wss://api.artery.questflow.ai/v1/stream?token=$TOKEN"

    Artery accepts the token via either the token query param or the Authorization: Bearer <token> header. Query is convenient for browser WebSocket which can't set headers.

    On a successful upgrade you'll see no immediate frame — the server waits for your first subscribe.

  3. Subscribe to multiple providers

    Channels are flat strings of the form artery:stream:{provider}:{marketKey}. Use * to match every market under a provider/feed.

    json{
      "type": "subscribe",
      "channels": [
        "artery:stream:hyperliquid_perp:*",
        "artery:stream:polymarket:0xCONDITION_ID"
      ]
    }

    Server reply:

    json{ "type": "subscribed", "subscription_id": "sub_01HMPK..." }

    From this point you'll receive event frames whenever the upstream provider emits a matching update.

  4. Parse events

    Every event carries type = "<provider>.<native_event_type>":

    json{
      "type": "event",
      "subscription_id": "sub_01HMPK...",
      "data": {
        "type": "hyperliquid.allMids",
        "provider": "hyperliquid",
        "marketId": "*",
        "payload": {
          "BTC": "67542.0",
          "ETH": "3201.7",
          "100000421": "0.625"
        },
        "receivedAt": 1714928400123
      }
    }

    The payload is the upstream feed's raw shape. For HL allMids, keys are coin tickers + numeric asset ids (HIP-3 + HIP-4). For Polymarket book it's { bids, asks, hash, market }.

  5. Handle the heartbeat

    Every 30 seconds the server pushes a JSON keepalive:

    json{ "type": "pong" }

    You can ignore it — the server only closes the connection (code 1001) if there's been no inbound frame from your client for >60s. Sending any subscribe / unsubscribe / {"type":"ping"} resets that timer.

  6. Reconnect with backoff

    On any close, reconnect with exponential backoff capped at 30s. Re-issue your subscriptions on the new connection — there is no server-side resumption (deliberately, to keep the gateway stateless).

    tslet delay = 500;
    while (true) {
      try {
        await connectAndSubscribe();
        delay = 500;
      } catch (e) {
        await sleep(delay);
        delay = Math.min(delay * 2, 30_000);
      }
    }

Full Node.js example

jsimport WebSocket from 'ws';
 
const TOKEN = process.env.ART_TOKEN;
const ws = new WebSocket(`wss://api.artery.questflow.ai/v1/stream?token=${TOKEN}`);
 
ws.on('open', () => {
  ws.send(
    JSON.stringify({
      type: 'subscribe',
      channels: ['artery:stream:hyperliquid_perp:*'],
    }),
  );
});
 
ws.on('message', (raw) => {
  const msg = JSON.parse(raw.toString());
  // Server pushes {type:"pong"} every 30s as a keepalive — ignore.
  if (msg.type === 'pong') return;
  if (msg.type === 'event') {
    const mids = msg.data?.payload?.data ?? msg.data?.payload;
    console.log('mid update:', Object.keys(mids ?? {}).length, 'assets');
  }
});
 
ws.on('close', () => {
  console.log('closed — reconnect with backoff');
});

Subscription patterns

You wantChannel string
All HL mids one update at a timeartery:stream:hyperliquid_perp:*
Single HL coin orderbookartery:stream:hyperliquid_perp:BTC
HIP-4 outcome marketartery:stream:hyperliquid_perp:100000421
Polymarket book by token idartery:stream:polymarket:<token_id>
Kalshi market deltas (planned — needs RSA)artery:stream:kalshi:<ticker>
Warning

Kalshi streaming is RSA-gated. Even public Kalshi channels return HTTP 401 on connect unless the handshake carries RSA-PSS signed headers. Artery will surface this as subscription_error with code: rsa_required until M3-4 ships.

See also

Edit this page on GitHubLast updated
Streaming Quickstart · Artery API Docs