Skip to main content
During development, the developer endpoints work without an API key. Access to the book stream in production is gated: request an API key with book stream access, or have an existing key upgraded.
This recipe connects to the book stream and reads ten levels of order book depth per side for a single pair. See Market Data Streams for how the book is built.
1

Set up

Import a WebSocket client, read the endpoint from the environment, and pick the pair to watch.
import "dotenv/config";
import WebSocket from "ws";

const DFLOW_TRADE_API_WS_URL =
  process.env.DFLOW_TRADE_API_WS_URL ?? "wss://dev-quote-api.dflow.net";
const DFLOW_API_KEY = process.env.DFLOW_API_KEY; // optional; not needed for dev

const SOL_MINT = "So11111111111111111111111111111111111111112";
const USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
2

Connect and subscribe

Open the connection to /book-stream and send a subscribe op once it is open. The book stream covers direct routes only.
const ws = new WebSocket(
  `${DFLOW_TRADE_API_WS_URL}/book-stream`,
  DFLOW_API_KEY ? { headers: { "x-api-key": DFLOW_API_KEY } } : undefined
);

ws.on("open", () => {
  ws.send(
    JSON.stringify({ op: "subscribe", base_mint: SOL_MINT, quote_mint: USDC_MINT })
  );
});
3

Render the book

Each update carries mid, tick, and ten levels per side. b and a are arrays of { price, cumulative_size_human }, ordered nearest to spot outward, where the size is cumulative base from the spot to that level.
ws.on("message", (data) => {
  const frame = JSON.parse(data.toString());
  for (const book of frame.updates ?? []) {
    if (book.e) {
      console.log(`${book.sb} / ${book.sq}: ${book.e}`);
      continue;
    }
    console.log(`\nslot ${frame.u}  mid ${book.mid}  tick ${book.tick}`);
    console.log("asks (low to high):");
    for (const level of [...book.a].reverse()) {
      console.log(`  ${level.price}\t${level.cumulative_size_human}`);
    }
    console.log("bids (high to low):");
    for (const level of book.b) {
      console.log(`  ${level.price}\t${level.cumulative_size_human}`);
    }
  }
});

ws.on("error", (err) => console.error("WebSocket error:", err));
ws.on("close", () => console.log("Connection closed"));

// demo only: stop after the first updates
setTimeout(() => ws.close(), 6000);
Book levels are approximations computed at runtime. The cumulative_size_human at each level is the total base size available from the spot out to that price.

Market Data Streams

How the streams work and when to use each.

Book Stream API

Messages, fields, and the depth format.

Stream Top-of-Book Quotes

Read live bid and ask for a pair.

Authenticate Requests

Authenticate requests for production rate limits.