tastytradeDeveloper Docs
Legacy ↗

Stream market data

This guide walks you through streaming live quotes from tastytrade's quote provider (dxFeed) over the DXLink WebSocket. You mint a short-lived token from the REST API, open the socket, run the handshake, subscribe to symbols, and read the feed.

For background on how the two tastytrade streamers differ and the full event catalog, see the concept page at /docs/concepts/streaming. This guide is the step-by-step task.

1. Get an API quote token

Call GET /api-quote-tokens with your OAuth access token. Access tokens last 15 minutes — mint a fresh one with POST /oauth/token if needed — and remember the required User-Agent: product/version header on every REST call. See /docs/get-started for the auth flow.

curl https://api.tastyworks.com/api-quote-tokens \
  -H "Authorization: Bearer <access token>" \
  -H "User-Agent: my-app/1.0.0"

The response gives you the token and the dxlink-url to connect to:

{
  "data": {
    "token": "<redacted>",
    "dxlink-url": "wss://tasty-openapi-ws.dxfeed.com/realtime",
    "level": "api"
  },
  "context": "/api-quote-tokens"
}

API quote tokens expire after 24 hours — refresh before they lapse. You must be a fully onboarded tastytrade customer; a username/password-only registration is rejected with quote_streamer.customer_not_found_error. (Sandbox uses https://api.cert.tastyworks.com; production uses https://api.tastyworks.com.)

2. Open the DXLink WebSocket

Open a WebSocket connection to the dxlink-url returned above. Message order matters — send the frames below in sequence.

3. SETUP

This is the first frame. It negotiates the protocol version and keepalive timeout on channel 0.

{ "type": "SETUP", "channel": 0, "version": "0.1-DXF-JS/0.3.0", "keepaliveTimeout": 60, "acceptKeepaliveTimeout": 60 }

DXLink replies with its own SETUP, then sends an AUTH_STATE with state: UNAUTHORIZED.

4. AUTH

When you see AUTH_STATE / UNAUTHORIZED, send your API quote token. DXLink replies with AUTH_STATE / AUTHORIZED.

{ "type": "AUTH", "channel": 0, "token": "<redacted>" }

5. CHANNEL_REQUEST — open a channel

A channel is a virtual sub-connection. Use separate channels to organize subscriptions (for example, equities on one channel, futures on another). Pick any number to identify it.

{ "type": "CHANNEL_REQUEST", "channel": 3, "service": "FEED", "parameters": { "contract": "AUTO" } }

DXLink replies with CHANNEL_OPENED for that channel.

6. FEED_SETUP — configure fields

Tell DXLink which fields you want for each event type, and request COMPACT data so events arrive as positional arrays rather than verbose objects.

{
  "type": "FEED_SETUP",
  "channel": 3,
  "acceptAggregationPeriod": 0.1,
  "acceptDataFormat": "COMPACT",
  "acceptEventFields": {
    "Quote": ["eventType", "eventSymbol", "bidPrice", "askPrice", "bidSize", "askSize"],
    "Trade": ["eventType", "eventSymbol", "price", "dayVolume", "size"],
    "Greeks": ["eventType", "eventSymbol", "volatility", "delta", "gamma", "theta", "rho", "vega"],
    "Summary": ["eventType", "eventSymbol", "openInterest", "dayOpenPrice", "dayHighPrice", "dayLowPrice", "prevDayClosePrice"]
  }
}

DXLink replies with FEED_CONFIG confirming the format and aggregation period.

7. FEED_SUBSCRIPTION — subscribe to symbols

Subscribe to one or more event types for one or more symbols in a single frame. Common event types are Quote, Trade, Greeks, Summary, and Candle. DXLink keeps streaming these until you unsubscribe.

{
  "type": "FEED_SUBSCRIPTION",
  "channel": 3,
  "reset": true,
  "add": [
    { "type": "Quote", "symbol": "SPY" },
    { "type": "Trade", "symbol": "SPY" },
    { "type": "Summary", "symbol": "SPY" }
  ]
}

Subscribe with DXLink-formatted symbols. tastytrade provides these in the streamer-symbol field on instrument responses (for example, futures /6AM3 exposes streamer-symbol: "/6AM23:XCME"). Prefer that field over hand-building symbols. To stop a symbol, send another FEED_SUBSCRIPTION with a remove array of the same event/symbol pairs.

8. Parse FEED_DATA

In COMPACT form, data is a flat array: an event-type label followed by one positional row per event, with values in the order you requested in FEED_SETUP.

{ "type": "FEED_DATA", "channel": 3, "data": [ "Trade", [ "Trade", "SPY", 559.36, 13743299, 100.0 ] ] }

DXLink publishes events only as they occur. A connected, heartbeating socket that receives nothing usually means the symbol has no current trading activity — that is normal, not a bug.

9. Keep the connection alive

If DXLink does not receive a keepalive within its 60-second timeout, it closes the connection. Send a KEEPALIVE on channel 0 about every 30 seconds to hold it open indefinitely.

{ "type": "KEEPALIVE", "channel": 0 }

Next steps

  • Reconnect with backoff on drops and respect the 60-second keepalive timeout — see /docs/guides/rate-limits-and-backoff.
  • For Candle (historical aggregate) events, symbology details, and the account streamer, see /docs/concepts/streaming.
  • Token-endpoint errors (401/429) are documented in /reference/errors; browse all endpoints in /reference.
  • For an agent integration that hands off to both streamers (quote-token tool + streaming protocol reference), see /docs/sdks-and-tools/mcp-server.