tastytrade OAuth2 Setup: Creating an App and Minting a Personal Grant
Setting up tastytrade OAuth2 for a personal or self-hosted client takes five steps: create an OAuth application in your tastytrade account settings, select the scopes you need, save the client ID and client secret, create a personal grant to mint a refresh token, and store the client secret and refresh token as environment variables. From then on your client exchanges the refresh token for a fifteen-minute session token automatically. The whole process takes a few minutes, and the one step that traps people is that sandbox accounts cannot use the website grant screen at all.
This is a procedural guide. It covers exactly what to click, what to save, and how to verify the result. For why OAuth2 replaced session tokens and how refresh handling should be structured under concurrency, that is a separate discussion; this one assumes you just want working credentials.
Before you start
You need a tastytrade account, and you need to decide up front whether you are setting up against production or sandbox, because the two environments have separate credentials, separate base URLs, and, importantly, different grant procedures.
Production is at api.tastyworks.com. Sandbox is at api.cert.tastyworks.com. A sandbox credential presented to production produces an invalid_credentials error, and a client that retries that error in a loop can get its IP blocked for roughly eight hours. Decide which you are building against and keep the environment selector and the credential set in the same configuration object so they cannot drift apart.
If you are setting up both, do them as two complete passes rather than interleaving. Mixing the two halfway through is the most common way to end up with a credential set nobody can identify later.
Step 1: Create the OAuth application
Go to your tastytrade account settings and open the OAuth applications screen, at my.tastytrade.com/app.html#/manage/api-access/oauth-applications. Create a new application.
You will be asked for a name, a set of scopes, and at least one redirect URI.
Scopes. The two you will care about are read and trade. Read covers account information, balances, positions, and market data. Trade covers order submission. Select only what your client actually needs. Several community guides tell you to check every scope, which is convenient and is the wrong default: a credential that can do less is a credential that costs you less when it leaks.
If your client only monitors positions and never submits orders, do not grant trade. Scope is the cheapest security control available here and it is applied once, at creation.
Redirect URI. Even a personal grant requires the application to have one registered. The SDK documentation suggests http://localhost:8000, and any local address you control is fine for a personal setup. This field matters more if you later run the full authorization-code flow; for a personal grant it is a registration formality you still cannot skip.
Step 2: Save the client ID and client secret
On creation you are shown a client ID and a client secret. Save both immediately, in a password manager or a secrets store, before navigating away.
The client secret is the one that matters and it is shown to you at creation. If you lose it, the recovery path is regenerating it, which invalidates the old one and breaks any client already using it. Copy it now rather than assuming you can come back for it.
Step 3: Create a personal grant
This is the step that produces the credential your client actually runs on.
From the OAuth application you just created, open its management view and create a grant. Depending on where you are in the interface this is labelled Create Grant or New Personal OAuth Grant. Select the scopes for the grant, and the screen returns a refresh token.
Copy the refresh token immediately. Like the client secret, this is your one clean opportunity.
The personal grant exists so that a single operator authorising their own application does not have to implement a full authorization-code flow with a callback server just to get a token for their own account. If you are building a client only you will run, this is the correct path and you can stop thinking about redirect handling entirely.
If instead you are building an application other people will connect their own tastytrade accounts to, the personal grant is not what you want. That is the full authorization-code flow, and distributing an application that trades on behalf of other people has regulatory implications well beyond the scope of a setup guide.
Step 3b: The sandbox exception
This is the step that strands people, and it is worth stating loudly because it contradicts everything above.
The website grant screen is not available for sandbox accounts. The Python SDK documentation is explicit that generating a grant from the website is the easy path for production, and that for sandbox accounts the local helper flow is the only option.
That helper opens a local web interface, prompts you to paste your client ID and client secret, walks the flow, and returns a refresh token in the browser and the console. In the Python SDK it is a login call from the oauth module with a test flag set.
If you have been clicking around the sandbox settings looking for a Create Grant button, it is not there and you have not missed it.
Step 4: Store the credentials properly
You now hold a client secret and a refresh token. Both are bearer credentials, and the refresh token in particular carries no documented expiry, which makes it closer to a private key than to a config value.
Put them in environment variables or a secrets manager. Not in source. Not in a committed environment file. Not baked into a container image layer. Not in a log line, which matters more than it sounds because authentication errors are exactly the errors people paste into issue trackers.
A minimal set for a self-hosted client:
TT_CLIENT_SECRET, TT_REFRESH_TOKEN, TT_ENVIRONMENT, and your account number.
On a self-hosted deployment these live in your own cloud environment, which means the credential never transits a vendor database and no vendor breach can expose it. It also means recovery is entirely yours: if you lose the refresh token, you mint a new grant; if it leaks, you revoke the grant, and nobody else will notice on your behalf.
Step 5: Authenticate from code
tastytrade publishes an official JavaScript SDK, which is the shortest path for a Node client. It takes the client secret, the refresh token, and the scopes, and handles access token generation and refresh internally:
import TastytradeClient from '@tastytrade/api';
const client = new TastytradeClient({ ...TastytradeClient.ProdConfig, clientSecret: process.env.TT_CLIENT_SECRET, refreshToken: process.env.TT_REFRESH_TOKEN, oauthScopes: ['read', 'trade'] });
The Python SDK is equivalent in shape, constructing a session from the client secret and refresh token, with a test flag for sandbox. From version 12 onward it checks for a soon-to-expire token on every request and refreshes automatically.
Note what the SDKs are doing for you: exchanging the refresh token for a session token that lasts fifteen minutes, and re-exchanging before it lapses. If you build the HTTP layer yourself instead, that exchange is a standard OAuth2 refresh token grant, and you should take the exact endpoint and parameter names from the OAuth2 guide in tastytrade developer documentation rather than from any article, including this one. Endpoint paths are the vendor detail most likely to be quietly wrong in third-party writeups.
One header requirement catches people regardless of SDK: tastytrade expects a User-Agent in <product>/<version> form. Without a conforming header you receive a 401 generated by nginx, which arrives as an HTML error page rather than the JSON envelope the rest of the API returns. If your client assumes JSON, that surfaces as a parse error rather than an authentication error, which sends you debugging the wrong thing.
Step 6: Verify before you trust it
Make one read-only call. Fetching your accounts is the conventional smoke test because it exercises authentication, base URL, and headers in a single request without touching anything.
If it returns your account list, the setup is correct.
Then, separately, verify that trade scope works if you granted it, using a dry run rather than a live order. The dry run calculates an order's effect on buying power and its fees without placing it, which makes it the correct way to confirm your grant carries trade permission. A grant minted without trade will read cleanly and fail only at order submission, and you would much rather discover that during setup than during a session.
Finally, confirm refresh works by leaving the client idle past the fifteen-minute session token lifetime and making another call. If it succeeds, refresh is wired correctly. If it returns an unauthorized error, your client is authenticating once and never renewing, which is the most common defect in a first tastytrade integration.
When setup fails
invalid_credentials. Almost always environment mismatch. Check the base URL against the credential set. Stop retrying while you check, because repeated failed logins are what triggers the IP block.
401 with an HTML body. Missing or malformed User-Agent.
unauthorized on a call that worked earlier. Expired session token, no refresh.
Reads work, orders fail. The grant lacks trade scope. Refreshing will not fix it; mint a new grant.
Everything times out. Per tastytrade documentation, sustained timeouts across all endpoints are consistent with an IP block from repeated failed logins, which typically lasts around eight hours and is cleared by contacting their API support address. Stop the client rather than letting it keep trying.
No Create Grant button. Sandbox account. See step 3b.
What this setup does not give you
Working credentials are the beginning of an integration, not a safe one.
A refresh token with no documented expiry is a durable credential. Possession is access, and the only remedy after a leak is revoking the grant, which requires you to notice. The 3Commas incidents demonstrated that trade-scoped keys bound the damage without preventing it: accounts were drained through market manipulation rather than withdrawals, using permissions that could not move money out.
Scope reduces blast radius. It does not eliminate it.
Sandbox proves your client authenticates and forms valid orders. It proves nothing about fills, spreads, or liquidity.
And none of this touches whether automating a given strategy is a good idea. Authentication is plumbing. The control that actually bounds loss is position sizing, upstream of every credential in this guide, which is why the divide-by-20 rule is deliberately blunt: available trading capital divided by twenty as the ceiling on any single position. It constrains the outcome rather than predicting it.
How this fits a self-hosted client
StaxInvesting is software, not signals. The platform is provisioned into the member's own cloud environment, and broker credentials are held in that environment's variables rather than in any vendor database. StaxInvesting holds no member API keys or refresh tokens and has no access to running member instances. Because the client runs on the member's own Node.js infrastructure, the credential path described above is the member's to configure and the member's to protect. Broker connections are trade-scoped; withdrawal permissions are never requested.
StaxInvesting is not a broker-dealer or a registered investment adviser and does not place trades on behalf of members.
Frequently asked questions
How do I get a tastytrade refresh token? Create an OAuth application in your account settings under API access, then create a personal grant from that application. The grant screen returns the refresh token. Copy it immediately.
Where do I create a tastytrade OAuth app? In your tastytrade account settings, on the OAuth applications screen under API access.
Why is there no Create Grant option in sandbox? The website grant screen is production-only. Sandbox accounts obtain a refresh token through the SDK local login helper flow instead.
Which scopes do I need? Read for account data and market data; trade additionally for order submission. Grant only what your client uses.
Do tastytrade refresh tokens expire? tastytrade does not publish an expiry, and the SDKs treat them as durable in normal operation. They can be revoked, which is the intended way to cut off a compromised client.
How long does a session token last? Fifteen minutes. Both official and community SDKs refresh it automatically.
Screens, scope names, endpoint paths, and header requirements are specified in the tastytrade developer documentation at developer.tastytrade.com, which is the authority. Interfaces change; verify against the current documentation before assuming a step here is still literal.
Disclaimer: This article is educational content about software engineering and API integration. It is not investment advice, financial advice, tax advice, legal advice, or a recommendation to buy or sell any security. Options trading involves substantial risk of loss and is not suitable for all investors. Please read Characteristics and Risks of Standardized Options before trading options. Automated trading systems carry additional risks including software defects, credential compromise, network and connectivity failures, broker API changes, rate limiting, access restrictions, and outages that may prevent orders from being placed, modified, or cancelled. Past performance does not indicate future results, and no configuration, position-sizing rule, or risk setting can guarantee a profit or prevent a loss.
StaxInvesting LLC sells self-hosted trading software. It is not a broker-dealer, investment adviser, or financial institution, and it does not manage accounts, hold member funds, place trades on behalf of members, or access member brokerage accounts. Members run the software in their own cloud environment, connect their own brokerage accounts under their own credentials, and are solely responsible for their configuration, their credential security, their compliance with third-party API terms of service, and every trade executed in their account. Third-party API details described here reflect publicly available documentation as of publication and are subject to change by the vendor without notice; always verify against current official documentation. Consult a qualified financial adviser and tax professional regarding your individual circumstances.