{
  "asyncapi": "2.6.0",
  "info": {
    "title": "tastytrade Streaming WebSockets",
    "version": "1.0.0",
    "description": "Machine-readable description of tastytrade's two independent WebSocket streamers:\n\n- **DXLink market-data streamer** — live quotes, trades, Greeks, summaries, profiles, and candle history, delivered by tastytrade's quote provider (dxFeed) over the DXLink protocol. You authenticate with an **API quote token** (`GET /api-quote-tokens`), which expires after 24 hours.\n- **Account streamer** — a one-directional WebSocket that pushes notifications about your own account state (orders, balances, positions) plus public watchlists and quote alerts. You authenticate with your tastytrade **OAuth access token** (the same value sent in the REST `Authorization` header).\n\nThis document is grounded in the tastytrade streaming guides. Where DXLink defers to dxFeed (event field catalogs, candle symbology, the full DXLink protocol), this spec stays general and links to dxFeed's documentation rather than inventing message types.\n\n> Tokens, hosts, and message ordering matter. Read the prose guides at /docs/concepts/streaming, /docs/guides/stream-market-data, and /docs/guides/stream-account-updates alongside this spec.",
    "contact": {
      "name": "tastytrade Open API docs",
      "url": "https://developer.tastytrade.com/"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "defaultContentType": "application/json",
  "tags": [
    {
      "name": "market-data",
      "description": "DXLink market-data streamer (quotes, trades, Greeks, candles)."
    },
    {
      "name": "account",
      "description": "Account streamer (orders, balances, positions, watchlists, quote alerts)."
    }
  ],
  "externalDocs": {
    "description": "DXLink protocol documentation and interactive debugger (dxFeed)",
    "url": "https://demo.dxfeed.com/dxlink-ws/debug/#/protocol"
  },
  "servers": {
    "dxlink": {
      "url": "tasty-openapi-ws.dxfeed.com/realtime",
      "protocol": "wss",
      "description": "DXLink market-data streamer. Do not hardcode this host: the exact `dxlink-url` is returned in the `GET /api-quote-tokens` response (for example `wss://tasty-openapi-ws.dxfeed.com/realtime`). Connect to whatever URL the token endpoint gives you.",
      "tags": [
        { "name": "market-data" }
      ]
    },
    "account-sandbox": {
      "url": "streamer.cert.tastyworks.com",
      "protocol": "wss",
      "description": "Account streamer — sandbox (certification) environment. Pairs with the REST host https://api.cert.tastyworks.com.",
      "tags": [
        { "name": "account" }
      ]
    },
    "account-production": {
      "url": "streamer.tastyworks.com",
      "protocol": "wss",
      "description": "Account streamer — production environment. Pairs with the REST host https://api.tastyworks.com.",
      "tags": [
        { "name": "account" }
      ]
    }
  },
  "channels": {
    "/realtime": {
      "description": "The single DXLink WebSocket connection. All DXLink messages are JSON objects carrying a `type` and a `channel`. Channel 0 is the control channel (SETUP, AUTH, KEEPALIVE); other channel numbers are virtual sub-connections you open with CHANNEL_REQUEST to carry feed data. Send messages in order: SETUP, AUTH, CHANNEL_REQUEST, FEED_SETUP, FEED_SUBSCRIPTION, then KEEPALIVE periodically.",
      "servers": ["dxlink"],
      "publish": {
        "operationId": "dxlinkClientSend",
        "summary": "Messages the client sends to DXLink.",
        "description": "The client-to-server half of the DXLink protocol: connection setup, authorization with the API quote token, channel management, feed configuration, subscription changes, and keepalives.",
        "tags": [
          { "name": "market-data" }
        ],
        "message": {
          "oneOf": [
            { "$ref": "#/components/messages/DxlinkSetup" },
            { "$ref": "#/components/messages/DxlinkAuth" },
            { "$ref": "#/components/messages/DxlinkChannelRequest" },
            { "$ref": "#/components/messages/DxlinkFeedSetup" },
            { "$ref": "#/components/messages/DxlinkFeedSubscription" },
            { "$ref": "#/components/messages/DxlinkKeepalive" }
          ]
        }
      },
      "subscribe": {
        "operationId": "dxlinkClientReceive",
        "summary": "Messages DXLink sends to the client.",
        "description": "The server-to-client half of the DXLink protocol: setup acknowledgement, authorization state, channel-opened acknowledgement, feed configuration acknowledgement, and the feed data itself.",
        "tags": [
          { "name": "market-data" }
        ],
        "message": {
          "oneOf": [
            { "$ref": "#/components/messages/DxlinkSetupAck" },
            { "$ref": "#/components/messages/DxlinkAuthState" },
            { "$ref": "#/components/messages/DxlinkChannelOpened" },
            { "$ref": "#/components/messages/DxlinkFeedConfig" },
            { "$ref": "#/components/messages/DxlinkFeedData" }
          ]
        }
      }
    },
    "/": {
      "description": "The account streamer WebSocket connection. The client sends control messages (`connect`, `heartbeat`, `public-watchlists-subscribe`, `quote-alerts-subscribe`), each carrying an `auth-token` (your OAuth access token). The server replies with status acknowledgements and pushes one-directional notification messages whose `type` matches the class of data (for example `Order`).",
      "servers": ["account-sandbox", "account-production"],
      "publish": {
        "operationId": "accountClientSend",
        "summary": "Messages the client sends to the account streamer.",
        "description": "Subscribe and keepalive actions. Open the socket, send a `connect` message first, then begin sending `heartbeat` messages on a 2s-1m interval. Sending a heartbeat before connecting may return a `not implemented` error.",
        "tags": [
          { "name": "account" }
        ],
        "message": {
          "oneOf": [
            { "$ref": "#/components/messages/AccountConnect" },
            { "$ref": "#/components/messages/AccountHeartbeat" },
            { "$ref": "#/components/messages/AccountPublicWatchlistsSubscribe" },
            { "$ref": "#/components/messages/AccountQuoteAlertsSubscribe" }
          ]
        }
      },
      "subscribe": {
        "operationId": "accountClientReceive",
        "summary": "Messages the account streamer sends to the client.",
        "description": "Status acknowledgements echoing the action (and any `request-id`), plus the one-directional state-change notifications. Every notification contains the full object representation, never a partial or differential update.",
        "tags": [
          { "name": "account" }
        ],
        "message": {
          "oneOf": [
            { "$ref": "#/components/messages/AccountStatusResponse" },
            { "$ref": "#/components/messages/AccountNotification" }
          ]
        }
      }
    }
  },
  "components": {
    "messages": {
      "DxlinkSetup": {
        "name": "SETUP",
        "title": "SETUP",
        "summary": "The first message the client sends to initiate a DXLink connection. Negotiates protocol version and keepalive timeout on the control channel (0).",
        "contentType": "application/json",
        "tags": [{ "name": "market-data" }],
        "payload": { "$ref": "#/components/schemas/DxlinkSetup" },
        "examples": [
          {
            "name": "setup",
            "summary": "Open the connection on channel 0.",
            "payload": {
              "type": "SETUP",
              "channel": 0,
              "version": "0.1-DXF-JS/0.3.0",
              "keepaliveTimeout": 60,
              "acceptKeepaliveTimeout": 60
            }
          }
        ]
      },
      "DxlinkAuth": {
        "name": "AUTH",
        "title": "AUTH",
        "summary": "Authorize the connection with your API quote token after the server reports AUTH_STATE UNAUTHORIZED.",
        "contentType": "application/json",
        "tags": [{ "name": "market-data" }],
        "payload": { "$ref": "#/components/schemas/DxlinkAuth" },
        "examples": [
          {
            "name": "auth",
            "summary": "Send the API quote token from GET /api-quote-tokens.",
            "payload": {
              "type": "AUTH",
              "channel": 0,
              "token": "<redacted>"
            }
          }
        ]
      },
      "DxlinkChannelRequest": {
        "name": "CHANNEL_REQUEST",
        "title": "CHANNEL_REQUEST",
        "summary": "Open a virtual channel for feed data. The channel number is any non-zero number you choose to identify the channel (for example, one channel for equities and another for futures).",
        "contentType": "application/json",
        "tags": [{ "name": "market-data" }],
        "payload": { "$ref": "#/components/schemas/DxlinkChannelRequest" },
        "examples": [
          {
            "name": "channel-request",
            "summary": "Open channel 3 as a FEED service with automatic contract handling.",
            "payload": {
              "type": "CHANNEL_REQUEST",
              "channel": 3,
              "service": "FEED",
              "parameters": { "contract": "AUTO" }
            }
          }
        ]
      },
      "DxlinkFeedSetup": {
        "name": "FEED_SETUP",
        "title": "FEED_SETUP",
        "summary": "Configure which event fields to receive on an opened channel and the accepted data format and aggregation period. The exact event types and their field names are defined by dxFeed; the example mirrors the subset the tastytrade web platform subscribes to.",
        "contentType": "application/json",
        "tags": [{ "name": "market-data" }],
        "payload": { "$ref": "#/components/schemas/DxlinkFeedSetup" },
        "examples": [
          {
            "name": "feed-setup",
            "summary": "Request COMPACT data and a subset of fields per event type on channel 3.",
            "payload": {
              "type": "FEED_SETUP",
              "channel": 3,
              "acceptAggregationPeriod": 0.1,
              "acceptDataFormat": "COMPACT",
              "acceptEventFields": {
                "Trade": ["eventType", "eventSymbol", "price", "dayVolume", "size"],
                "TradeETH": ["eventType", "eventSymbol", "price", "dayVolume", "size"],
                "Quote": ["eventType", "eventSymbol", "bidPrice", "askPrice", "bidSize", "askSize"],
                "Greeks": ["eventType", "eventSymbol", "volatility", "delta", "gamma", "theta", "rho", "vega"],
                "Profile": ["eventType", "eventSymbol", "description", "shortSaleRestriction", "tradingStatus", "statusReason", "haltStartTime", "haltEndTime", "highLimitPrice", "lowLimitPrice", "high52WeekPrice", "low52WeekPrice"],
                "Summary": ["eventType", "eventSymbol", "openInterest", "dayOpenPrice", "dayHighPrice", "dayLowPrice", "prevDayClosePrice"]
              }
            }
          }
        ]
      },
      "DxlinkFeedSubscription": {
        "name": "FEED_SUBSCRIPTION",
        "title": "FEED_SUBSCRIPTION",
        "summary": "Add or remove event subscriptions for one or more symbols on a channel. DXLink streams matching events until you remove the subscription. Use `reset: true` to clear existing subscriptions before applying `add`.",
        "description": "Subscribe to events with `add` and unsubscribe with `remove`. Each entry is an `{ type, symbol }` pair where `type` is a dxFeed event type (Quote, Trade, Greeks, Summary, Profile, Candle, ...) and `symbol` is a DXLink-formatted symbol (use the `streamer-symbol` field from the instruments endpoints). Candle subscriptions encode period/type and require a `fromTime`; see the streaming guide and dxFeed's candle documentation.",
        "contentType": "application/json",
        "tags": [{ "name": "market-data" }],
        "payload": { "$ref": "#/components/schemas/DxlinkFeedSubscription" },
        "examples": [
          {
            "name": "subscribe-add",
            "summary": "Subscribe to multiple events for multiple symbols (resetting first).",
            "payload": {
              "type": "FEED_SUBSCRIPTION",
              "channel": 3,
              "reset": true,
              "add": [
                { "type": "Trade", "symbol": "BTC/USD:CXTALP" },
                { "type": "Quote", "symbol": "BTC/USD:CXTALP" },
                { "type": "Profile", "symbol": "BTC/USD:CXTALP" },
                { "type": "Summary", "symbol": "BTC/USD:CXTALP" },
                { "type": "Trade", "symbol": "SPY" },
                { "type": "TradeETH", "symbol": "SPY" },
                { "type": "Quote", "symbol": "SPY" },
                { "type": "Profile", "symbol": "SPY" },
                { "type": "Summary", "symbol": "SPY" }
              ]
            }
          },
          {
            "name": "unsubscribe-remove",
            "summary": "Stop receiving the listed events for SPY.",
            "payload": {
              "type": "FEED_SUBSCRIPTION",
              "channel": 3,
              "remove": [
                { "type": "Trade", "symbol": "SPY" },
                { "type": "Quote", "symbol": "SPY" },
                { "type": "Summary", "symbol": "SPY" }
              ]
            }
          }
        ]
      },
      "DxlinkKeepalive": {
        "name": "KEEPALIVE",
        "title": "KEEPALIVE",
        "summary": "Sent on the control channel (0) at regular intervals to keep the connection open. If DXLink does not receive a keepalive within the 60-second timeout it closes the connection; sending one every ~30 seconds keeps it open indefinitely.",
        "contentType": "application/json",
        "tags": [{ "name": "market-data" }],
        "payload": { "$ref": "#/components/schemas/DxlinkKeepalive" },
        "examples": [
          {
            "name": "keepalive",
            "summary": "Keepalive on channel 0.",
            "payload": { "type": "KEEPALIVE", "channel": 0 }
          }
        ]
      },
      "DxlinkSetupAck": {
        "name": "SETUP",
        "title": "SETUP (server acknowledgement)",
        "summary": "DXLink's response to the client SETUP, echoing the negotiated keepalive timeouts and reporting the server protocol version.",
        "contentType": "application/json",
        "tags": [{ "name": "market-data" }],
        "payload": { "$ref": "#/components/schemas/DxlinkSetupAck" },
        "examples": [
          {
            "name": "setup-ack",
            "summary": "Server confirms SETUP on channel 0.",
            "payload": {
              "type": "SETUP",
              "channel": 0,
              "keepaliveTimeout": 60,
              "acceptKeepaliveTimeout": 60,
              "version": "1.0-1.2.1-20240722-153442"
            }
          }
        ]
      },
      "DxlinkAuthState": {
        "name": "AUTH_STATE",
        "title": "AUTH_STATE",
        "summary": "Reports the authorization state of the connection. After SETUP the server sends UNAUTHORIZED; after a successful AUTH it sends AUTHORIZED with the userId.",
        "contentType": "application/json",
        "tags": [{ "name": "market-data" }],
        "payload": { "$ref": "#/components/schemas/DxlinkAuthState" },
        "examples": [
          {
            "name": "auth-state-unauthorized",
            "summary": "Sent right after SETUP — time to send AUTH.",
            "payload": { "type": "AUTH_STATE", "channel": 0, "state": "UNAUTHORIZED" }
          },
          {
            "name": "auth-state-authorized",
            "summary": "Sent after a successful AUTH.",
            "payload": { "type": "AUTH_STATE", "channel": 0, "state": "AUTHORIZED", "userId": "<redacted>" }
          }
        ]
      },
      "DxlinkChannelOpened": {
        "name": "CHANNEL_OPENED",
        "title": "CHANNEL_OPENED",
        "summary": "Acknowledges that the requested channel is open and ready for feed configuration and subscriptions.",
        "contentType": "application/json",
        "tags": [{ "name": "market-data" }],
        "payload": { "$ref": "#/components/schemas/DxlinkChannelOpened" },
        "examples": [
          {
            "name": "channel-opened",
            "summary": "Channel 3 opened as a FEED service.",
            "payload": {
              "type": "CHANNEL_OPENED",
              "channel": 3,
              "service": "FEED",
              "parameters": { "contract": "AUTO", "subFormat": "LIST" }
            }
          }
        ]
      },
      "DxlinkFeedConfig": {
        "name": "FEED_CONFIG",
        "title": "FEED_CONFIG",
        "summary": "Acknowledges the channel's feed configuration, reporting the effective data format and aggregation period.",
        "contentType": "application/json",
        "tags": [{ "name": "market-data" }],
        "payload": { "$ref": "#/components/schemas/DxlinkFeedConfig" },
        "examples": [
          {
            "name": "feed-config",
            "summary": "Channel 3 configured for COMPACT data at a 0.1s aggregation period.",
            "payload": {
              "type": "FEED_CONFIG",
              "channel": 3,
              "dataFormat": "COMPACT",
              "aggregationPeriod": 0.1
            }
          }
        ]
      },
      "DxlinkFeedData": {
        "name": "FEED_DATA",
        "title": "FEED_DATA",
        "summary": "Carries market event data on a channel. In COMPACT format, `data` is a list of [eventType, valuesArray] pairs; the value ordering matches the fields requested in FEED_SETUP for that event type. Field catalogs and value semantics are defined by dxFeed.",
        "contentType": "application/json",
        "tags": [{ "name": "market-data" }],
        "payload": { "$ref": "#/components/schemas/DxlinkFeedData" },
        "examples": [
          {
            "name": "feed-data-compact",
            "summary": "A COMPACT Trade batch (abridged).",
            "payload": {
              "type": "FEED_DATA",
              "channel": 3,
              "data": ["Trade", ["Trade", "SPY", 559.36, 13743299, 100.0, "Trade", "BTC/USD:CXTALP", 58356.71, "NaN", "NaN"]]
            }
          }
        ]
      },
      "AccountConnect": {
        "name": "connect",
        "title": "connect",
        "summary": "Subscribe to all account-related notifications (orders, balances, positions) for the provided account numbers. Send this first, before heartbeating.",
        "contentType": "application/json",
        "tags": [{ "name": "account" }],
        "payload": { "$ref": "#/components/schemas/AccountConnect" },
        "examples": [
          {
            "name": "connect",
            "summary": "Subscribe to two accounts.",
            "payload": {
              "action": "connect",
              "value": ["5WT00000", "5WT00001"],
              "auth-token": "your access token here",
              "request-id": 2
            }
          }
        ]
      },
      "AccountHeartbeat": {
        "name": "heartbeat",
        "title": "heartbeat",
        "summary": "Keep the account-streamer connection alive. Send on a 2s-1m interval after a successful connect. The optional request-id is echoed in the response.",
        "contentType": "application/json",
        "tags": [{ "name": "account" }],
        "payload": { "$ref": "#/components/schemas/AccountHeartbeat" },
        "examples": [
          {
            "name": "heartbeat",
            "summary": "Heartbeat with a correlating request-id.",
            "payload": {
              "action": "heartbeat",
              "auth-token": "your access token here",
              "request-id": 1
            }
          }
        ]
      },
      "AccountPublicWatchlistsSubscribe": {
        "name": "public-watchlists-subscribe",
        "title": "public-watchlists-subscribe",
        "summary": "Subscribe to public watchlist updates. An auth-token is still required; the value is blank.",
        "contentType": "application/json",
        "tags": [{ "name": "account" }],
        "payload": { "$ref": "#/components/schemas/AccountActionMessage" },
        "examples": [
          {
            "name": "public-watchlists-subscribe",
            "summary": "Subscribe to public watchlist updates.",
            "payload": {
              "action": "public-watchlists-subscribe",
              "auth-token": "your access token here",
              "request-id": 3
            }
          }
        ]
      },
      "AccountQuoteAlertsSubscribe": {
        "name": "quote-alerts-subscribe",
        "title": "quote-alerts-subscribe",
        "summary": "Subscribe to quote alert messages for alerts the user configured via POST /quote-alerts. Quote alerts are scoped to the user, not an account; the value is blank.",
        "contentType": "application/json",
        "tags": [{ "name": "account" }],
        "payload": { "$ref": "#/components/schemas/AccountActionMessage" },
        "examples": [
          {
            "name": "quote-alerts-subscribe",
            "summary": "Subscribe to quote alerts.",
            "payload": {
              "action": "quote-alerts-subscribe",
              "auth-token": "your access token here",
              "request-id": 4
            }
          }
        ]
      },
      "AccountStatusResponse": {
        "name": "statusResponse",
        "title": "Action status response",
        "summary": "The server's acknowledgement of a client action. Echoes the action, the web-socket-session-id, any request-id, and (for connect) the subscribed account numbers.",
        "contentType": "application/json",
        "tags": [{ "name": "account" }],
        "payload": { "$ref": "#/components/schemas/AccountStatusResponse" },
        "examples": [
          {
            "name": "connect-response",
            "summary": "Acknowledgement of a connect message.",
            "payload": {
              "status": "ok",
              "action": "connect",
              "web-socket-session-id": "5b6e2799",
              "value": ["5WT00000", "5WT00001"],
              "request-id": 2
            }
          },
          {
            "name": "heartbeat-response",
            "summary": "Acknowledgement of a heartbeat message.",
            "payload": {
              "status": "ok",
              "action": "heartbeat",
              "web-socket-session-id": "5b6e2799",
              "request-id": 1
            }
          }
        ]
      },
      "AccountNotification": {
        "name": "notification",
        "title": "Account notification",
        "summary": "A one-directional state-change notification. The `type` identifies the class of data; `data` carries the full object representation (same JSON shape as the REST API, never a partial update); `timestamp` is the epoch-millisecond emission time.",
        "description": "Notifications are emitted whenever subscribed account data changes — for example an order advancing through its lifecycle. The example shows an `Order` notification; other types correspond to the other account data classes (balances, positions, watchlists, quote alerts) using the same envelope and the same object shapes documented in /reference.",
        "contentType": "application/json",
        "tags": [{ "name": "account" }],
        "payload": { "$ref": "#/components/schemas/AccountNotification" },
        "examples": [
          {
            "name": "order-notification",
            "summary": "An Order notification as the order goes Live.",
            "payload": {
              "type": "Order",
              "data": {
                "id": 1,
                "account-number": "5WT00000",
                "time-in-force": "Day",
                "order-type": "Market",
                "size": 100,
                "underlying-symbol": "AAPL",
                "underlying-instrument-type": "Equity",
                "status": "Live",
                "cancellable": true,
                "editable": true,
                "edited": false,
                "legs": [
                  {
                    "instrument-type": "Equity",
                    "symbol": "AAPL",
                    "quantity": 100,
                    "remaining-quantity": 100,
                    "action": "Buy to Open",
                    "fills": []
                  }
                ]
              },
              "timestamp": 1688595114405
            }
          }
        ]
      }
    },
    "schemas": {
      "DxlinkSetup": {
        "type": "object",
        "required": ["type", "channel"],
        "additionalProperties": false,
        "properties": {
          "type": { "type": "string", "const": "SETUP" },
          "channel": { "type": "integer", "const": 0, "description": "Control channel." },
          "version": { "type": "string", "description": "Client protocol/library version string.", "example": "0.1-DXF-JS/0.3.0" },
          "keepaliveTimeout": { "type": "integer", "description": "Seconds the client will allow between inbound keepalives before considering the connection dead.", "example": 60 },
          "acceptKeepaliveTimeout": { "type": "integer", "description": "Seconds the client requests the server to allow between the client's keepalives.", "example": 60 }
        }
      },
      "DxlinkAuth": {
        "type": "object",
        "required": ["type", "channel", "token"],
        "additionalProperties": false,
        "properties": {
          "type": { "type": "string", "const": "AUTH" },
          "channel": { "type": "integer", "const": 0 },
          "token": { "type": "string", "description": "The API quote token from GET /api-quote-tokens (expires after 24 hours)." }
        }
      },
      "DxlinkChannelRequest": {
        "type": "object",
        "required": ["type", "channel", "service"],
        "additionalProperties": false,
        "properties": {
          "type": { "type": "string", "const": "CHANNEL_REQUEST" },
          "channel": { "type": "integer", "description": "Any non-zero number you choose to identify this channel.", "example": 3 },
          "service": { "type": "string", "const": "FEED", "description": "The service bound to the channel. Market data uses FEED." },
          "parameters": {
            "type": "object",
            "description": "Service parameters. For FEED, `contract` controls contract handling.",
            "properties": {
              "contract": { "type": "string", "example": "AUTO" }
            }
          }
        }
      },
      "DxlinkFeedSetup": {
        "type": "object",
        "required": ["type", "channel"],
        "additionalProperties": false,
        "properties": {
          "type": { "type": "string", "const": "FEED_SETUP" },
          "channel": { "type": "integer", "example": 3 },
          "acceptAggregationPeriod": { "type": "number", "description": "Requested aggregation period in seconds.", "example": 0.1 },
          "acceptDataFormat": { "type": "string", "enum": ["COMPACT"], "description": "COMPACT delivers events as positional value arrays.", "example": "COMPACT" },
          "acceptEventFields": {
            "type": "object",
            "description": "Map of dxFeed event type -> ordered list of field names to receive for that event type. The available event types and field names are defined by dxFeed.",
            "additionalProperties": {
              "type": "array",
              "items": { "type": "string" }
            }
          }
        }
      },
      "DxlinkFeedSubscription": {
        "type": "object",
        "required": ["type", "channel"],
        "additionalProperties": false,
        "properties": {
          "type": { "type": "string", "const": "FEED_SUBSCRIPTION" },
          "channel": { "type": "integer", "example": 3 },
          "reset": { "type": "boolean", "description": "When true, clear existing subscriptions before applying `add`." },
          "add": {
            "type": "array",
            "description": "Event subscriptions to add.",
            "items": { "$ref": "#/components/schemas/DxlinkSubscriptionEntry" }
          },
          "remove": {
            "type": "array",
            "description": "Event subscriptions to remove.",
            "items": { "$ref": "#/components/schemas/DxlinkSubscriptionEntry" }
          }
        }
      },
      "DxlinkSubscriptionEntry": {
        "type": "object",
        "required": ["type", "symbol"],
        "additionalProperties": true,
        "description": "An event subscription. `type` is a dxFeed event type (Quote, Trade, TradeETH, Greeks, Summary, Profile, Candle, ...). `symbol` is a DXLink-formatted symbol — use the `streamer-symbol` field from the instruments endpoints. Candle subscriptions additionally encode period/type in the symbol (for example `AAPL{=5m}`) and require a `fromTime` epoch-seconds timestamp; see dxFeed's candle documentation.",
        "properties": {
          "type": { "type": "string", "example": "Quote" },
          "symbol": { "type": "string", "example": "SPY" },
          "fromTime": { "type": "integer", "description": "Unix epoch seconds. Required for Candle subscriptions; the start of the historical window.", "example": 1691402400 }
        }
      },
      "DxlinkKeepalive": {
        "type": "object",
        "required": ["type", "channel"],
        "additionalProperties": false,
        "properties": {
          "type": { "type": "string", "const": "KEEPALIVE" },
          "channel": { "type": "integer", "const": 0 }
        }
      },
      "DxlinkSetupAck": {
        "type": "object",
        "required": ["type", "channel"],
        "additionalProperties": true,
        "properties": {
          "type": { "type": "string", "const": "SETUP" },
          "channel": { "type": "integer", "const": 0 },
          "keepaliveTimeout": { "type": "integer", "example": 60 },
          "acceptKeepaliveTimeout": { "type": "integer", "example": 60 },
          "version": { "type": "string", "description": "Server protocol version.", "example": "1.0-1.2.1-20240722-153442" }
        }
      },
      "DxlinkAuthState": {
        "type": "object",
        "required": ["type", "channel", "state"],
        "additionalProperties": true,
        "properties": {
          "type": { "type": "string", "const": "AUTH_STATE" },
          "channel": { "type": "integer", "const": 0 },
          "state": { "type": "string", "enum": ["UNAUTHORIZED", "AUTHORIZED"] },
          "userId": { "type": "string", "description": "Present when state is AUTHORIZED." }
        }
      },
      "DxlinkChannelOpened": {
        "type": "object",
        "required": ["type", "channel", "service"],
        "additionalProperties": true,
        "properties": {
          "type": { "type": "string", "const": "CHANNEL_OPENED" },
          "channel": { "type": "integer", "example": 3 },
          "service": { "type": "string", "const": "FEED" },
          "parameters": {
            "type": "object",
            "properties": {
              "contract": { "type": "string", "example": "AUTO" },
              "subFormat": { "type": "string", "example": "LIST" }
            }
          }
        }
      },
      "DxlinkFeedConfig": {
        "type": "object",
        "required": ["type", "channel"],
        "additionalProperties": true,
        "properties": {
          "type": { "type": "string", "const": "FEED_CONFIG" },
          "channel": { "type": "integer", "example": 3 },
          "dataFormat": { "type": "string", "enum": ["COMPACT"], "example": "COMPACT" },
          "aggregationPeriod": { "type": "number", "example": 0.1 }
        }
      },
      "DxlinkFeedData": {
        "type": "object",
        "required": ["type", "channel", "data"],
        "additionalProperties": true,
        "properties": {
          "type": { "type": "string", "const": "FEED_DATA" },
          "channel": { "type": "integer", "example": 3 },
          "data": {
            "type": "array",
            "description": "In COMPACT format, an alternating list of [eventType, valuesArray] entries. The value ordering within each array matches the fields requested for that event type in FEED_SETUP. Numeric fields may carry the string \"NaN\" when unavailable. Value semantics are defined by dxFeed.",
            "items": {}
          }
        }
      },
      "AccountConnect": {
        "type": "object",
        "required": ["action", "auth-token", "value"],
        "additionalProperties": false,
        "properties": {
          "action": { "type": "string", "const": "connect" },
          "value": {
            "type": "array",
            "description": "Account numbers to subscribe to.",
            "items": { "type": "string" },
            "example": ["5WT00000", "5WT00001"]
          },
          "auth-token": { "type": "string", "description": "Your tastytrade OAuth access token (same value as the REST Authorization header)." },
          "request-id": { "type": "integer", "description": "Optional. Echoed back in the response so you can correlate messages." }
        }
      },
      "AccountHeartbeat": {
        "type": "object",
        "required": ["action", "auth-token"],
        "additionalProperties": false,
        "properties": {
          "action": { "type": "string", "const": "heartbeat" },
          "value": { "type": "string", "description": "Blank for heartbeat." },
          "auth-token": { "type": "string", "description": "Your tastytrade OAuth access token." },
          "request-id": { "type": "integer", "description": "Optional. Echoed back in the response." }
        }
      },
      "AccountActionMessage": {
        "type": "object",
        "description": "A subscribe action whose `value` is blank. Used for public-watchlists-subscribe and quote-alerts-subscribe.",
        "required": ["action", "auth-token"],
        "additionalProperties": false,
        "properties": {
          "action": { "type": "string", "enum": ["public-watchlists-subscribe", "quote-alerts-subscribe"] },
          "value": { "type": "string", "description": "Blank for these actions." },
          "auth-token": { "type": "string", "description": "Your tastytrade OAuth access token (required even for public watchlists)." },
          "request-id": { "type": "integer", "description": "Optional. Echoed back in the response." }
        }
      },
      "AccountStatusResponse": {
        "type": "object",
        "required": ["status", "action"],
        "additionalProperties": true,
        "properties": {
          "status": { "type": "string", "example": "ok" },
          "action": { "type": "string", "description": "The action being acknowledged.", "example": "connect" },
          "web-socket-session-id": { "type": "string", "example": "5b6e2799" },
          "value": {
            "description": "For connect, the account numbers that were subscribed.",
            "type": "array",
            "items": { "type": "string" }
          },
          "request-id": { "type": "integer", "description": "Echoed from the client message when provided." }
        }
      },
      "AccountNotification": {
        "type": "object",
        "required": ["type", "data", "timestamp"],
        "additionalProperties": true,
        "properties": {
          "type": { "type": "string", "description": "The class of data this notification carries (for example Order).", "example": "Order" },
          "data": {
            "type": "object",
            "description": "The full object representation for the given type — the same JSON shape used elsewhere in the API (see /reference). Never a partial or differential update.",
            "additionalProperties": true
          },
          "timestamp": { "type": "integer", "description": "Emission time in epoch milliseconds.", "example": 1688595114405 }
        }
      }
    }
  }
}
