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 day at a time through sessions. 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 sessions 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. 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 when a session 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 session 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 session is open (409 session_open) — cash carry is driven by settlement, never by deletion.
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.
Session endpoints
A session is one trading day under an account. Orders, positions, transactions, and history all live under a session.
| Method | Path | Purpose |
|---|---|---|
GET |
/accounts/{id}/sessions |
List trading days (newest first) |
GET |
/accounts/{id}/sessions/current |
The open live session, or null |
GET |
/accounts/{id}/sessions/head |
Default landing session, or null |
GET |
/accounts/{id}/sessions/{sid} |
Get one session |
POST |
/accounts/{id}/sessions |
Open (or re-open) today's session |
GET |
/accounts/{id}/sessions/{sid}/history |
Per-second financial history |
/current returns the open live session for a live / broker account, or null. /head is the default landing session — the open day if any, else the latest settled day.
Open a session
A live_sim account opens today's session — the body is empty and the date is implicitly today:
curl -s https://api.0dtespx.com/accounts/$ACCT/sessions \
-X POST -H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
-d '{}'
- Live (
live_sim) — opens today's session at the latest tick with the carried cash balance, gated on market hours and fresh market data (400if the market is closed or live data is unavailable). Re-requesting today's session while it is open returns it (200). - Broker engines →
409 engine_not_available.
To replay a past trading day, use the account-less /practice/sessions endpoints instead.
The response is the session 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 session also carries
closing_balance(the cash it settled to, carried into the account) andsettled_at. - While a live day is
openit carriessettles_at— when the day 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 session'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}); account sessions expose no clock endpoint. Once a live day settles you can review it read-only via the ?at= query parameter (see live trading).
Per-second history
curl -s "https://api.0dtespx.com/accounts/$ACCT/sessions/$SID/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 account session 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}/sessions/{sid}/…). 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 session, see live trading.