Tradovate API

Tradovate API 401 Unauthorized (Expired Token)

About 90 minutes into a session, every Tradovate API call suddenly returns 401 Unauthorized. Here's why the access token expires on a clock and how to renew it before it ever drops your orders.

Reviewed by the PickMyTrade Trading Systems Team Last updated
· 7 min read
Tradovate API 401 Unauthorized response shown in a REST client

You wire up a Tradovate API bot, fire off a few demo orders, and everything hums along, then, about an hour and a half in, every call slams into a 401 Unauthorized. It's one of the most common and most misread Tradovate API failures, and the cause is almost always the same: your access token quietly expired. Tradovate access tokens live for roughly 90 minutes. Once that clock runs out, both the REST API and the market-data WebSocket stop trusting you. You'll see it as a bare 401 Unauthorized HTTP status, an "Access is denied" message, or a WebSocket that abruptly sends a close frame and drops. The fix isn't to hammer the login endpoint again, it's to renew the token before it dies. Automation bridges like PickMyTrade manage that token lifecycle for you, so your alerts keep firing even when a raw script would've gone dark.

Quick Checklist for the 401 Unauthorized Error

  • Check the clock. If the 401 starts around the 75–90 minute mark, it's a token-expiry problem, not a credentials problem.
  • Renew, don't re-login. Call /auth/renewAccessToken with your still-valid token about 15 minutes before it expires.
  • Track expirationTime. Store the timestamp returned at login and schedule a renewal against it, not against a guessed interval.
  • Verify the header. The token must be sent as Authorization: Bearer <token> on every request.
  • Match the environment. A demo token only authorizes demo hosts; a live token only authorizes live hosts.
  • One session per token. Re-requesting a fresh token elsewhere can invalidate the token your bot is still using.

What “401 Unauthorized” Means

A 401 Unauthorized from the Tradovate API means the server got your request but refused to act on it because it couldn't verify a valid, current access token. This is an authentication failure, not a permissions problem, not an order-logic problem. The API is basically saying, “I don't know who you are right now.” On the REST side you see it as an HTTP 401 status. On the market-data and trading WebSocket it usually arrives as a frame carrying "s":401 with the text "Access is denied", often followed by the socket closing.

Here's the part that trips people up: a Tradovate access token is short-lived by design. When you authenticate through /auth/accessTokenRequest, the response hands you an accessToken plus an expirationTime, and that expiration sits roughly 90 minutes out. During that window the token is your key to every protected endpoint. The moment it lapses, the exact same request that worked a minute ago returns a 401, because the key no longer opens the lock.

That's why the error is so baffling the first time you hit it. Nothing in your code changed, your API key and secret are still correct, and yet the calls fail. The problem is time, not configuration. A 401 that only shows up after your app has been running for over an hour is the fingerprint of an expired token.

Top Causes of Tradovate API 401 Unauthorized in 2026

1. The access token expired (the 90-minute limit)

This is by far the most common cause. Tradovate access tokens have a documented lifetime of about 90 minutes from creation. If your bot grabs a token once at startup and never refreshes it, every request after that 90-minute mark returns a 401. In practice the failure tends to land around the 80-minute mark, right where a token that was never renewed gives out.

Tradovate access token response showing the expirationTime field and 90-minute window

2. Renewing too late, after the token already expired

/auth/renewAccessToken only works while your current token is still valid. Wait until after expiry to renew, and the renewal call itself fails with a 401, you're trying to authenticate a renewal with a dead key. Once a token has fully expired, you have to run a fresh /auth/accessTokenRequest, not a renewal.

3. A malformed Authorization header

Even a perfectly valid token gets rejected if you present it wrong. On REST calls the header must read Authorization: Bearer <token>, a missing Bearer prefix or a stray space is enough to trigger a 401. On the WebSocket, the authorize frame has to be formatted exactly as the current docs specify (endpoint, id, then the token, with the correct blank-line separators). A formatting slip there produces the same "Access is denied" response.

4. Wrong environment (demo token on live host, or vice versa)

Tradovate runs separate demo and live environments. A token issued against the demo host won't authorize requests sent to the live host, and the reverse holds too. Point a valid demo token at a live endpoint (or a live token at demo) and it surfaces as a 401 / access-denied even though the token itself is genuine.

5. The token was invalidated by a second login

Access tokens are tied to a session. If another process, a second script, a manual test, or a re-run of your own login flow, requests a fresh token for the same account, it can invalidate the token your bot is still holding. The bot then starts collecting 401s mid-run even though “nothing changed” on its side. And repeatedly hammering the login endpoint can trip Tradovate's request penalty, which delays you even further.

How to Fix the 401 Unauthorized Error: Step-by-Step

Fixing an Expired Token: Renew Before It Dies

1

Store the expiration on login

When you authenticate, read the expirationTime value from the login response and store it alongside your accessToken.

2

Set a timer to fire early

Set a timer or scheduler to fire about 15 minutes before that expiration, with a 90-minute token, that lands you near the 75-minute mark.

3

Call renewAccessToken

When the timer fires, send a POST to /auth/renewAccessToken with your current, still-valid token in the Authorization: Bearer <token> header and no request body.

4

Replace and repeat

Replace your stored accessToken and expirationTime with the fresh values returned, then reset the timer. Repeat for as long as the bot runs.

Tradovate /auth/renewAccessToken POST returning a fresh accessToken and new expirationTime

Fixing a Token That Already Expired

If your token has already lapsed and renewal returns a 401, stop trying to renew. Run a full /auth/accessTokenRequest again to get a brand-new token and expiration, then resume the renew-before-expiry loop above. Build your client so a 401 on any call triggers a single re-authentication and one automatic retry, not an infinite loop, which can trip request-limit penalties.

Fixing the Authorization Header

Log the exact header your client sends and confirm it reads Authorization: Bearer <token> with a single space after Bearer. For WebSocket connections, verify the authorize frame matches the current documented format before you assume your token is bad. The fastest way to isolate this is to make the same call in a REST client, Postman or curl, with a freshly issued token. If that succeeds, the problem is in how your code builds the request, not the token.

Fixing Environment and Credential Mismatches

Confirm the host you're calling matches the environment your token was issued for (demo vs. live). Then double-check that your API key, secret, and app credentials are current in the Tradovate API management area, regenerating them or losing sync will also produce authentication failures. Sign in to your Tradovate account, open the API access / add-on section, and confirm your key is active before blaming the token.

Tradovate API Access management screen showing active API key and add-on status

Troubleshooting Table

Error Meaning Fix
401 Unauthorized (REST, after ~90 min)Access token expiredRenew via /auth/renewAccessToken ~15 min before expiry
"s":401 ... "Access is denied" (WebSocket)Token expired or authorize frame rejectedRe-authenticate and re-open the socket with a valid token
401 on the renewal call itselfYou renewed after the token already expiredRun a fresh /auth/accessTokenRequest, then resume renewing
401 immediately on every callMalformed Authorization headerEnsure Authorization: Bearer <token> with correct spacing
401 / access denied on live onlyDemo token used against a live host (or vice versa)Use a token issued for the environment you are calling
401 mid-run after another loginPrior token invalidated by a second sessionShare one token per account; avoid duplicate logins

Prevent This with PickMyTrade

Managing a 90-minute token clock by hand is fragile, miss one renewal and your automation goes silent right when a signal fires. PickMyTrade sits between TradingView and Tradovate and handles the token lifecycle for you:

  • Automatic Token Renewal, the connection is refreshed on schedule, so a 90-minute expiry never drops your orders.
  • Session-Safe Routing, one managed connection per account avoids the duplicate-login invalidation that causes mid-run 401s.
  • Rate-Limit-Safe Requests, calls are spaced to respect Tradovate's request limits, so you never trade a fixed 401 for a penalty timeout.
  • Environment Awareness, demo and live stay distinct, so a token is never sent to the wrong host.

The upshot: your TradingView alerts reach Tradovate without you writing or babysitting a single line of authentication code.

Trade Rejection-Free

PickMyTrade manages the 90-minute token lifecycle for you, renewing on schedule so a Tradovate API 401 never drops your orders mid-session.

Start Your Free 5-Day Trial

Frequently Asked Questions

A Tradovate access token has a documented lifetime of about 90 minutes from the moment it's issued. After that it stops authenticating requests and you get a 401 until you renew or re-authenticate.

/auth/accessTokenRequest logs you in from scratch using your credentials and returns a brand-new token. /auth/renewAccessToken extends your session by issuing a fresh token while your current one is still valid, it doesn't require re-sending your credentials.

About 15 minutes before it expires. With a 90-minute token that means renewing near the 75-minute mark, which leaves a safe buffer before the clock runs out.

No. Renewal only works on a still-valid token. If it has already expired, the renewal call returns 401 and you must run a full accessTokenRequest to get a new token.

That's the classic signature of an expired token. Nothing in your code is wrong, the token simply reached its ~90-minute limit and needs to be renewed on a timer.

An instant 401 usually means a malformed Authorization header, a token issued for the wrong environment (demo vs. live), or invalid API credentials, not expiry. Verify the header format and the host first.

It can. Access tokens are tied to a session, so authenticating again elsewhere may invalidate the token your bot is holding and cause mid-run 401s. Use one shared token per account, or a bridge that manages the session for you.

Renewing on a sensible schedule, once every ~75 minutes, is fine. Trouble comes from re-calling the login endpoint in a tight loop after a 401, which can trigger Tradovate's request penalty. Renew proactively instead of retrying blindly.

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. or Bookmap. 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 platform documentation before acting.