tastytradeDeveloper Docs
Legacy ↗

OAuth2 authentication

Every request to the tastytrade API is authenticated with an OAuth2 access token in the Authorization header. All API users must use OAuth2 — the legacy POST /sessions flow was decommissioned in 20260211.

Short-lived scoped tokens are the reason. A 15-minute access token limited to specific permissions gives an attacker a very small window and only the resources that token was authorized for. A 24-hour session token gives them a day with potentially full account access.

Base URLs

Sandbox and production are fully separate, with their own credentials and data.

EnvironmentBase URL
Productionhttps://api.tastyworks.com
Sandboxhttps://api.cert.tastyworks.com

A client and refresh token registered in one environment will not work in the other. See Sandbox for what else differs.

Every request needs a User-Agent

All requests, including the OAuth calls below, must send a User-Agent header or they are rejected. The format is product/version. The product and version you pick do not matter as long as the format is right — most people make it specific to their client, like tastytrade-api-client/1.0 or my-custom-client/2.0.

Step 1 — Create an OAuth application

On my.tastytrade.com, go to Manage → My Profile → API → OAuth Applications and click + New OAuth client.

  • Client Name is prefilled with your tastytrade username.
  • Redirect URI, one per environment requested. Multiple URIs are allowed, and each must be a full URI — https://www.my-redirect-uri.com is valid, my-redirect.com is not.
  • Scopes: read, trade, openid.

On creation you are shown your Client ID and Client Secret.

The client secret is shown once. Store it securely before clicking Finish Setup; it cannot be shown again. If you need a new one, use Regenerate at the top of the page — note that this invalidates any active grants.

The Regenerate button on an OAuth application's settings page

Step 2 — Generate a personal grant

For your own application you do not need the full authorization flow. Go to Manage → My Profile → API → OAuth Applications, click Manage next to your application, then Create Grant. This shows your grant's refresh token.

The Create Grant button on an OAuth application

Refresh tokens are long-lived and do not expire. If you lose one or it is compromised, delete the corresponding grant on the API page of my.tastytrade.com and create a new one — a new grant issues a new refresh token.

Step 3 — Exchange the refresh token for an access token

curl -X POST https://api.tastyworks.com/oauth/token \
  -H "User-Agent: my-custom-client/1.0" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "refresh_token",
    "refresh_token": "YOUR_REFRESH_TOKEN",
    "client_secret": "YOUR_CLIENT_SECRET"
  }'

grant_type, refresh_token and client_secret are required. client_id is optional — the server infers it from the refresh token, but if you send it, it must match. An optional space-separated scope requests a subset of your grant's scopes.

The response contains a new access_token. Refreshing does not rotate your refresh token: none is returned, and the one you hold stays valid for the life of the grant.

Access tokens are signed JWTs valid for 15 minutes. An expired token returns HTTP 401. Refresh on a schedule, or lazily just before expiry, rather than on every request.

Step 4 — Send the token on every request

GET /accounts/{account_number}/positions HTTP/1.1
Host: api.tastyworks.com
Authorization: Bearer YOUR_ACCESS_TOKEN
User-Agent: my-custom-client/1.0
Accept: application/json

Real access tokens are far longer than that placeholder.

Third-party applications

Everything above covers using your own application against your own account. A personal OAuth application is restricted to your account only — you can build and test, but other tastytrade users cannot connect to it.

To let other users authorize your application you must complete tastytrade's trusted third party verification, which reviews how your application handles data and protects users. Contact api.support@tastytrade.com to start.

The rest of this section applies only to verified third party applications.

User authorization

tastytrade supports the OAuth2 authorization code grant. Once approved, direct users to https://my.tastytrade.com/auth.html (sandbox: https://cert-my.staging-tasty.works/auth.html) with:

ParameterRequired
client_idyes
redirect_uriyes
response_typeyes
scopeno
stateno

The tastytrade authorization screen a user sees

On success the user is redirected to your redirect_uri with code (the authorization code) and state as query parameters.

Exchange the code for tokens

curl -X POST https://api.tastyworks.com/oauth/token \
  -H "User-Agent: my-custom-client/1.0" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "code": "AUTHORIZATION_CODE",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "redirect_uri": "https://www.my-redirect-uri.com"
  }'

The response contains:

FieldMeaning
access_tokenSend as a bearer token on each request
refresh_tokenNever expires
token_typeBearer
expires_inSeconds the access token remains valid
id_tokenOnly returned when using the openid scope

Refresh works the same as Step 3. If a third-party refresh token is lost or compromised, contact tastytrade API support immediately.

Two-factor authentication

For sensitive scopes — currently read and trade — customers must have 2FA enabled to grant an application access. Customers enable it under My Profile → Security with either an authenticator app or SMS.

Enabling two-factor authentication under My Profile Security

During authorization, after entering credentials and clicking Login, the customer is prompted for their 2FA code.

The two-factor prompt during the authorization step

What can go wrong

  • 401 Unauthorized — no Authorization header, or the token is missing, invalid or expired. Refresh and retry.
  • 403 Forbidden — the token is valid but not authorized for that resource: an account belonging to another customer, or a scope that does not cover the operation. Reads need read, mutations need trade.
  • 406 Not Acceptable — the Accept-Version you sent no longer exists. See API versions.
  • 429 Too Many Requests — back off and retry. See Rate limits and backoff.

Error responses carry an error object with code and message. The full status code list is at /reference/errors.

Notes for money-moving requests

Run orders as a dry-run first, then submit with a unique external-identifier so you can recognise the order later. There is no idempotency-key header and the API does not deduplicate retried submissions. If a submission's outcome is uncertain after a timeout or 5xx, check GET /accounts/{account_number}/orders (or /orders/live) for your external-identifier before resubmitting. See Idempotency and retries.

Related

  • Quickstart — your first authenticated call.
  • Sandbox — separate credentials, and how fills are simulated.
  • API versions — the Accept-Version header.
  • MCP server — let it manage tokens for you.