A trading account is a persistent, named, cash-only container with a continuous balance that carries day to day. Each account has a fixed engine, and you trade it one trading day at a time — a day that opens by itself on your first order, never through a call of its own. See Accounts & trading days for the concepts. All endpoints require authentication.
Replaying past trading days is account-less — it lives under /practice/sessions, not under an account. Accounts are for live and bot trading only.
Engines
| Engine | What it does |
|---|---|
live_sim |
Paper-trades today's real session against the live tick stream. Past trading days are frozen. The only engine that ships now. |
broker_* |
Reserved for upcoming broker integrations — not yet available. Creating one returns 409 engine_not_available. |
Every account on /accounts is a live (manual) account — the type field is always manual. Trading bots are a separate surface, created and managed via the Bots API; they never appear in the /accounts list or resolve through /accounts/{id}. Trading is 0DTE SPX-index options only: cash-only, no equities, no overnight positions, so the carried balance is a single number.
Account endpoints
| Method | Path | Purpose |
|---|---|---|
GET |
/accounts |
List your live accounts |
POST |
/accounts |
Create an account |
GET |
/accounts/{id} |
Get one account |
PATCH |
/accounts/{id} |
Rename or archive an account |
DELETE |
/accounts/{id} |
Delete an account |
GET |
/accounts/{id}/analytics |
Trade-level analytics over settled days |
GET /accounts
Lists your accounts and saves the first one's id as {{account_id}} for the blocks below.
Interactive — run this request from the docs
Create an account
curl -s https://api.0dtespx.com/accounts \
-X POST -H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
-d '{
"name": "Iron condors",
"engine": "live_sim",
"description": "Defined-risk study account"
}'
POST /accounts
Creates a real paper-trading account on your profile. Names are unique among your active accounts, so edit `name` before a second run (409 name_taken otherwise).
Interactive — run this request from the docs
Every account starts with a fixed $100,000 — there is no capital to choose. name is required (≤ 80 chars) and must be unique among your active accounts. description is optional free-form text (≤ 1000 chars). engine is fixed for the account's life. type defaults to manual. The response is the account object:
{
"id": "f3c88e1a-…",
"name": "Iron condors",
"description": "Defined-risk study account",
"engine": "live_sim",
"type": "manual",
"starting_capital": "100000",
"cash_balance": "100000",
"current_value": "100000",
"status": "active",
"created_at": "2026-06-21T12:00:00Z"
}
cash_balanceis the settled carry — it never folds in unsettled intraday P&L.current_valueis the live net-liquidation value while a trading day is open on the account, otherwise it equalscash_balance.
GET /accounts/{{account_id}}
Reads one account back. {{account_id}} is filled in by either block above.
Interactive — run this request from the docs
Creating a broker_* account returns 409 engine_not_available; a bot type returns 400.
Edit or archive an account
PATCH accepts any of name, description, status — only the fields you send are applied.
# rename
curl -s -X PATCH https://api.0dtespx.com/accounts/$ACCT \
-H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"Condors — 2025"}'
# archive (blocked while a trading day is open)
curl -s -X PATCH https://api.0dtespx.com/accounts/$ACCT \
-H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
-d '{"status":"archived"}'
PATCH /accounts/{{account_id}}
Renames the account {{account_id}} points at. Only the fields you send are applied.
Interactive — run this request from the docs
DELETE /accounts/{id} soft-deletes the account and returns 204. It is blocked while a trading day is open (409 day_open) — cash carry is driven by settlement, never by deletion. PATCHing the account to archived is refused the same way.
Trading analytics
GET /accounts/{id}/analytics reviews the account's settled trading days: it folds their transactions into round-trip trades and returns trade-level aggregate metrics, per-day trade counts, and the trade log. Read-only and unmetered.
curl -s "https://api.0dtespx.com/accounts/$ACCT/analytics" \
-H "Authorization: $TOKEN" \
| jq '{trades: .summary.total_trades, win_rate: .summary.win_rate_pct, pf: .summary.profit_factor, net: .summary.total_net_profit_loss}'
GET /accounts/{{account_id}}/analytics
Folds this account's settled trading days into round-trip trades and returns the aggregate metrics, per-day counts, and trade log. Read-only and unmetered — an account with no settled days answers with empty aggregates.
Interactive — run this request from the docs
{
"summary": {
"total_trades": 42,
"win_count": 25,
"loss_count": 15,
"scratch_count": 2,
"win_rate_pct": 62.5,
"profit_factor": "1.84",
"total_net_profit_loss": "1234.56",
"total_fees": "94.67",
"average_winner": "180.2",
"average_loser": "-210.1",
"largest_winner": "540",
"largest_loser": "-410",
"average_hold_seconds": 3841,
"sessions_analyzed": 17
},
"days": [{ "date": "2026-07-10", "trade_count": 3 }],
"trades_truncated": false,
"trades": [
{
"date": "2026-07-10",
"session_id": "…",
"opened_at": "2026-07-10T13:35:02Z",
"closed_at": "2026-07-10T15:12:44Z",
"hold_seconds": 5862,
"direction": "short",
"legs": [{ "instrument": "SPXW 260710C06300000", "quantity": "1", "open_side": "sell to open" }],
"net_profit_loss": "125.4",
"fees": "4.51",
"outcome": "win"
}
]
}
Round trips. A trade is a position opened and flattened within one settled day. Legs opened by a single order are grouped as one trade — a vertical or condor placed as one combo order is one trade — and additions to an already-open position count toward that position's trade. Legs legged in under separate orders, and a re-open after a position went flat, are separate trades.
net_profit_loss(per trade) andtotal_net_profit_loss(summary) are net of fees — the gross figure isnet_profit_loss + fees.outcomeiswin,loss, orscratchon the sign ofnet_profit_loss(scratchis exactly zero).win_rate_pctis100 × win_count / (win_count + loss_count)— scratches are excluded — and isnullwhen there are no decided (win or loss) trades.profit_factoris the winners' net P&L over the absolute losers' net P&L,nullwhen there are no losers.average_winner/average_loser/largest_winner/largest_loserarenullwhen their set is empty. These nullable fields are always present, carryingnullrather than being omitted.summaryanddaysalways cover every trade. Thetradeslog is newest first and capped at the most recent 1000;trades_truncatedistruewhen older trades were cut (the aggregates still count them).
Only manual live accounts have analytics here; a settled day appears once it has settled after the 4:00 PM ET close. Use Replay to scrub any single settled day moment by moment.
Trading days
A trading day is one day of one account. Orders, positions, transactions, and history all belong to a day — but you rarely name one: the account-level routes resolve it for you, and the day itself opens on your first order. The full trading surface is on the live-trading page; this is the day resource.
| Method | Path | Purpose |
|---|---|---|
GET |
/accounts/{id}/days |
Every trading day, newest date first |
GET |
/accounts/{id}/days/current |
The open day, or null |
GET |
/accounts/{id}/days/{date} |
One day, by YYYY-MM-DD |
GET |
/accounts/{id}/days/{date}/history |
Per-second financial history for that day |
GET |
/accounts/{id}/history |
The same series, for the active day |
/days is the settled archive plus the open day, if one is open. /days/current is the "is this account tradeable right now" probe: it answers the open day while one is open and null the moment that day settles. /days/{date} answers 400 for a malformed date and 404 day_not_found for a date this account never traded.
There is no call that opens a day, and none that closes one. A live_sim account's day opens by itself inside your first order of the day — a dry-run opens it too — and it settles at the 4:00 PM ET close. The day is opened by that call alone: the exchange is told about it in the background, so the placement never waits on the exchange to acknowledge the day. A broker engine refuses the placement with 409 engine_not_available; an archived account with 409 account_archived; and an account whose earlier day is still open and unsettled with 409 previous_session_unsettled — today's opening balance is not final until that day settles, so retry later.
To replay a past trading day, use the account-less /practice/sessions endpoints instead.
The trading day object
{
"id": "9a1b…",
"account_id": "f3c88e1a-…",
"date": "2025-01-15",
"opening_balance": "100000",
"starting_capital": "100000",
"status": "open",
"ended": false,
"time": "2025-01-15T14:30:00Z",
"start_time": "2025-01-15T14:30:00Z",
"end_time": "2025-01-15T21:00:00Z",
"available_buying_power": "100000",
"net_liquidation_value": "100000",
"unrealized_profit_loss": "0",
"realized_profit_loss": "0",
"profit_loss": "0"
}
opening_balanceis the carried cash the day opened with;starting_capitalmirrors it for wire continuity (net_liquidation_value = starting_capital + intraday P&L).statusis the authoritative lifecycle field —open,settled, orabandoned.endedis a convenience flag that istrueonce the day is terminal (settledorabandoned);closing_balanceandsettled_atare present only after a successful settlement.- A settled day also carries
closing_balance(the cash it settled to, carried into the account) andsettled_at. - While a day is
openit carriessettles_at— when it is expected to settle (end_timeplus a few minutes). After the close, that's when the settled, replayable day should appear in the list.
The full object also breaks financials out into equities vs equity-options components — the equities half is always zero for SPX-only trading, the equity-options half carries the numbers.
A live day's clock is the real clock — it has no clock control. Advancing or rewinding a replay is a practice-only feature (PATCH /practice/sessions/{sid}); a trading day exposes no clock endpoint. Once it settles you can review it read-only with the ?at= query parameter (see live trading).
Per-second history
curl -s "https://api.0dtespx.com/accounts/$ACCT/days/2025-01-15/history?interval=5" \
-H "Authorization: $TOKEN"
# …or the active day, without naming a date
curl -s "https://api.0dtespx.com/accounts/$ACCT/history?interval=5" -H "Authorization: $TOKEN"
Returns an array of per-second snapshots (net liquidation value, P&L, buying power, fees, …) for charting. Sampled at 1-second resolution; pass ?interval=<seconds> to down-sample. The series extends as the trading day progresses; on a practice session it is rebuilt whenever you place or delete an order.
Practice sessions (account-less)
Replaying past trading days doesn't use an account. Practice is a one-click, account-less $100,000 sandbox: each day opens at the market open (9:30 AM ET) with a fixed $100,000. The endpoints mirror the trading-day shapes but carry no account_id — there is no account object to create or carry a balance between days.
| Method | Path | Purpose |
|---|---|---|
GET |
/practice/sessions |
List your practice days (newest first) |
POST |
/practice/sessions |
Open a new practice day |
GET |
/practice/sessions/{sid} |
Get one session |
PATCH |
/practice/sessions/{sid} |
Advance/rewind the replay clock |
DELETE |
/practice/sessions/{sid} |
Delete a practice day |
GET |
/practice/sessions/{sid}/history |
Per-second financial history |
GET |
/practice/sessions/{sid}/orders |
List orders |
POST |
/practice/sessions/{sid}/orders |
Place an order |
GET |
/practice/sessions/{sid}/orders/{orderId} |
Get one order |
DELETE |
/practice/sessions/{sid}/orders/{orderId} |
Delete an order (and its trades) |
GET |
/practice/sessions/{sid}/positions |
List positions |
GET |
/practice/sessions/{sid}/transactions |
List transactions |
Open a practice day
curl -s https://api.0dtespx.com/practice/sessions \
-X POST -H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
-d '{"date":"2025-01-15"}'
date can be any past trading date, opened in any order. Each POST opens a new, independent session, so a day can hold multiple simulations (each returns 201). Practice days don't carry into one another, so deleting one never disturbs the others. To edit a previously settled day, rewind its clock with PATCH (below).
The response is a session object without account_id, with the fixed $100,000:
{
"id": "9a1b…",
"date": "2025-01-15",
"opening_balance": "100000",
"starting_capital": "100000",
"status": "open",
"ended": false,
"time": "2025-01-15T14:30:00Z",
"start_time": "2025-01-15T14:30:00Z",
"end_time": "2025-01-15T21:00:00Z",
"available_buying_power": "100000",
"net_liquidation_value": "100000",
"unrealized_profit_loss": "0",
"realized_profit_loss": "0",
"profit_loss": "0"
}
Advance the clock
A fresh practice session is parked at start_time. Move the clock with PATCH:
curl -s https://api.0dtespx.com/practice/sessions/$SID \
-X PATCH -H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
-d '{"time":"2025-01-15T17:00:00Z"}'
The response is the same shape, with time filled in and all financials recomputed at the new moment. time must satisfy start_time ≤ time ≤ end_time, or you get 400. Moving time never trades for you — it saves the new clock, then recomputes positions, delta, P&L, and buying power from existing trades; it never writes orders or transactions. Setting it backward reverts not-yet-filled orders to live and hides later trades; rewinding a settled day back before the close re-opens it for editing.
Setting the clock to end_time (the 4:00 PM ET close) finalizes the day: it settles, status becomes settled (ended flips to true).
Orders, positions, transactions, and history
The /practice/sessions/{sid}/orders, /positions, and /transactions sub-resources are identical in shape to their account-session counterparts — see orders and positions & transactions for the request/response bodies; only the path prefix differs (/practice/sessions/{sid}/… instead of /accounts/{id}/…). Per-second history behaves the same as above and accepts ?interval=<seconds> to down-sample.
Next: place orders and read positions. For today's real-time trading day, see live trading.