Subscribe to Market Data Over the Tradovate API
Want live bids, offers, and trades streaming into your own code? Here's the exact path from access token to a running quote stream, plus the two mistakes that trip up almost everyone.
Want live bids, offers, and trades streaming into your own code instead of the Trader app? Tradovate hands them over through a WebSocket, but not the one most people try first. Get the endpoint wrong and every subscription comes back as a cryptic Not found: md/subscribeQuote. Here's the exact path from access token to a running quote stream, plus the two mistakes that trip up almost everyone.
Why a Separate Market Data Socket?
Tradovate splits its real-time traffic across two WebSockets. One carries your account and order events; the other carries market data, quotes, DOM depth, charts, and histograms. They speak the same frame protocol, but they live on different hosts. Market data endpoints like md/subscribeQuote only exist on the market data socket, so if you send that request to the account socket you get a "not found" error even though your token is perfectly valid.
Before You Start
- API access enabled, the API Access add-on has to be turned on for your login.
- An access token, you'll pull one in Step 1.
- A live market-data entitlement, real-time API data requires a CME market-data subscription (you become a registered sub-vendor). The fee runs a few hundred dollars a month, so check Tradovate's current rate before you commit. Without it, you'll still connect, you just get a
Symbol is inaccessiblereply.
Subscribe to Tradovate Market Data: Step-by-Step
Get an Access Token
POST your credentials to auth/accessTokenRequest. The response hands back an accessToken (and an mdAccessToken) along with an expiration time. Keep that token, the market data socket authorizes with the same access token you'd use on the REST API. If the request fails outright, confirm the API Access add-on is actually enabled on your account first.
Open the Market Data WebSocket
Point your WebSocket client at the market data host, not the account host. The moment your market data connection opens, the server sends a single o frame. That's your cue to authorize.
Authorize the Socket
Every request over the socket is a plain text frame with four fields separated by newline characters: the endpoint, a unique integer request id, an optional query string, and an optional body. To authorize, the endpoint is authorize and the body is your token. The server answers with an a frame containing a 200 status. Once you see it, the socket is live.
Subscribe With md/subscribeQuote
Now send the subscription. Same four-field frame, the endpoint is md/subscribeQuote and the body names the contract. Use the current front-month contract (swap ESU6 for whatever's active when you run this), or pass a numeric contractId instead of the symbol string. One catch: subscribe to a single symbol per request. To watch several instruments, fire md/subscribeQuote again with a new request id for each one, the same connection handles all of them.
Read the Quotes and Keep Heartbeats Alive
Quotes now stream in as a frames wrapping a md event. Each quote object carries a timestamp, a contractId, and an entries map with Bid, Offer, and Trade, each holding a price and size. One thing you can't skip: heartbeats. Send an empty-array frame, literally [], every 2.5 seconds, or the server closes the connection for inactivity and your quotes stop cold. When you're done with a feed, send md/unsubscribeQuote with the same symbol to shut it off.
| Environment | Market data URL |
|---|---|
| Demo / simulated | wss://md-demo.tradovateapi.com/v1/websocket |
| Live / funded | wss://md.tradovateapi.com/v1/websocket |

For reference, the account socket lives at wss://demo.tradovateapi.com/v1/websocket and wss://live.tradovateapi.com/v1/websocket, different hostnames entirely.
authorize
1
YOUR_ACCESS_TOKEN
That's authorize, then 1, then an empty query line, then the token, each on its own line.

md/subscribeQuote
2
{"symbol":"ESU6"}

{"e":"md","d":{"quotes":[{"contractId":123456,"entries":{"Bid":{"price":5602.25,"size":18},"Offer":{"price":5602.50,"size":24},"Trade":{"price":5602.25,"size":3}}}]}}

Common Gotchas
- "Not found: md/subscribeQuote", you're on the account socket. Reconnect to the
md-demo/mdhost from Step 2. - "Symbol is inaccessible", your login lacks a real-time data agreement for that product, or the symbol isn't a valid front-month contract.
- Feed goes silent after a few seconds, you stopped sending
[]heartbeats. Put them on a 2.5-second timer that runs for the life of the socket.
Skip the Plumbing With PickMyTrade
Standing up a market data socket, token refresh, heartbeats, reconnect logic, the CME data license, is real work before you've placed a single order. If your goal is just to automate entries and exits from your strategy, PickMyTrade wires your TradingView alerts straight to Tradovate. No WebSocket to babysit.
Skip the WebSocket Plumbing
No token refresh, heartbeats, or reconnect logic to babysit, PickMyTrade wires your TradingView alerts straight to Tradovate.
Start Your Free 5-Day TrialFrequently Asked Questions
No. Authorize the market data socket with the same access token you get from auth/accessTokenRequest. The auth response also returns an mdAccessToken field, check the current docs if a call ever rejects your token.
You're connected fine, but your account has no real-time data agreement for that product, or the symbol isn't the active contract. Add the CME market-data subscription and use a valid front-month symbol.
Yes. Send md/subscribeQuote once per symbol, each with its own request id, over the same socket. There's no array form, repeat the request instead.
This guide is for educational and informational purposes only and is not financial, investment, or trading advice. Trading futures and other leveraged products carries a substantial risk of loss and is not suitable for every investor. PickMyTrade is an independent third-party automation platform and is not affiliated with, endorsed by, or sponsored by Tradovate, Inc. "Tradovate" and all related names, logos, and trademarks are the property of their respective owners. Platform features and steps change over time, so always confirm the current process in the official Tradovate platform and documentation before acting.