Agent Quickstart
This is a single, self-contained walkthrough an AI agent can follow to complete a
full trade in sandbox: discover the API, mint a token, fetch a quote, dry-run an
order, submit it safely, and confirm the fill. Stay in sandbox
(https://api.cert.tastyworks.com) until the whole flow is verified; production
(https://api.tastyworks.com) is real money and requires explicit human approval.
Consider the MCP server for autonomous flows. The tastytrade MCP server is self-hosted and open source; its five order-submitting tools are gated behind a dry-run-first confirmation token, with sanity checks and rate limits on top. Note its default endpoint is production. This page shows the raw HTTP golden path so you understand what the MCP server does for you.
Two rules apply to every request below: send Authorization: Bearer <token> and
send a User-Agent header in the form <product>/<version> (e.g. my-agent/1.0).
Requests without a User-Agent are rejected. Never log, echo, or commit tokens.
1. Discover the API
Fetch /llms.txt — the machine-readable index that points to every doc
and reference page. Use it to locate endpoints instead of guessing. It is served by
this documentation site (the same origin as this page), not by the trading API
host.
# Use this documentation site's origin — not api.cert.tastyworks.com
curl 'https://<docs-site-host>/llms.txt' -H 'User-Agent: my-agent/1.0'
2. Mint a 15-minute access token
Exchange your refresh token for a short-lived access token. It is valid for 15 minutes and cannot be extended — mint a fresh one when it expires. See Get started for obtaining credentials.
curl -X POST 'https://api.cert.tastyworks.com/oauth/token' \
-H 'User-Agent: my-agent/1.0' \
-H 'Content-Type: application/json' \
-d '{
"grant_type": "refresh_token",
"refresh_token": "YOUR_REFRESH_TOKEN",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
}'
The response contains access_token. Then resolve your account number from
GET /customers/me/accounts.
3. Fetch a quote
Pull real-time market data over REST for up to 100 symbols at once. Use tastytrade
symbology: equities (AAPL), OCC equity options, futures (/-prefixed), future
options (./-prefixed), and crypto pairs (BTC/USD).
GET /market-data/by-type?equity=AAPL
Authorization: Bearer YOUR_ACCESS_TOKEN
User-Agent: my-agent/1.0
For live streaming, obtain an API quote token (GET /api-quote-tokens, 24h expiry)
and connect to the DXLink WebSocket using the COMPACT format. See
Streaming.
4. Dry-run the order first
Orders are money-moving — always dry-run first. Post the order body to the
dry-run endpoint and confirm it returns no errors; inspect buying-power-effect
and fee-calculation before going live.
POST /accounts/{account_number}/orders/dry-run
Authorization: Bearer YOUR_ACCESS_TOKEN
User-Agent: my-agent/1.0
Content-Type: application/json
{
"time-in-force": "Day",
"order-type": "Limit",
"price": "1.00",
"price-effect": "Debit",
"legs": [
{
"instrument-type": "Equity",
"symbol": "AAPL",
"quantity": 1,
"action": "Buy to Open"
}
]
}
Note the dasherized JSON keys (order-type, price-effect). A failed validation
returns a 422 with an error.code you can branch on.
5. Submit with a unique external-identifier
Once the dry-run is clean, submit to the live endpoint and include a unique
external-identifier field in the order body. tastytrade has no
idempotency-key header and does not deduplicate retried submissions, so this
id is how you recognize your order on a retry.
POST /accounts/{account_number}/orders
Authorization: Bearer YOUR_ACCESS_TOKEN
User-Agent: my-agent/1.0
Content-Type: application/json
{
"time-in-force": "Day",
"order-type": "Limit",
"price": "1.00",
"price-effect": "Debit",
"external-identifier": "my-agent-2026-06-09-aapl-001",
"legs": [
{
"instrument-type": "Equity",
"symbol": "AAPL",
"quantity": 1,
"action": "Buy to Open"
}
]
}
The external-identifier you send is echoed back on the order object. (Order
responses and account-streamer messages also carry a system-populated, read-only
ext-client-order-id — never try to set or send that field yourself.)
If the submit response is uncertain (timeout or 5xx), do not blindly resubmit —
the server will not deduplicate. List your orders first
(GET /accounts/{account_number}/orders, or /accounts/{account_number}/orders/live)
and check whether one carrying your external-identifier already exists. See
Idempotency & retries.
6. Confirm the fill
A successful submit returns an order with status Routed. Poll the order (or stream
order updates) until it reaches a terminal status. The lifecycle
flows roughly: Received → Routed → In Flight → Live → Filled.
| Status | Terminal | Meaning |
|---|---|---|
| Live | No | Working at the exchange |
| Filled | Yes | Order fully filled — a position and transaction are created |
| Cancelled | Yes | Order was cancelled |
| Rejected | Yes | Rejected by tastytrade or the exchange |
| Expired | Yes | Day order that did not fill before close |
Once Filled, confirm by fetching the account's balances and positions. tastytrade
may mark an order Filled before every leg's fills finish processing — if a leg
looks short, re-fetch after a brief delay.
Safety checklist
- Sandbox until verified; get explicit human approval before production.
- Dry-run first, then submit with a unique
external-identifier. - On
429, back off exponentially and retry — see Rate limits & backoff. - Branch on the error code, not message text — see Error reference.
Next steps
- API Reference — all operations with schemas and samples.
- Orders reference — full order JSON, complex orders, fractional.
- MCP Server — the safe way to drive trading autonomously.