API reference

Overview & authentication

Base URL, auth, access levels, and conventions.

Everything you can do in the app, you can do over the HTTP + WebSocket API — create trading accounts, open sessions (practice or live), place orders, read positions, build and save strategies with their backtest results, and stream live data. This section is a practical reference; the full machine-readable specification lives at /openapi.yaml.

Base URL

https://api.0dtespx.com

A liveness probe is available at GET /health (no auth, returns 200).

GET /health

Liveness probe — answers 200 with an empty body while the API is up. Runs from this page against the real API; no account needed.

Interactive — run this request from the docs

Discovering the API

Three documents are served unauthenticated and are the canonical, always-current reference:

Document Contents
/openapi.yaml Full HTTP + WebSocket spec (OpenAPI 3.0.3)
API walkthrough End-to-end walkthrough with copy-pasteable curl
/llms.txt An llmstxt.org index for AI agents

Authentication

Authenticate with a bearer session token, obtained by logging in:

curl -s https://api.0dtespx.com/auth/sessions \
  -H 'Content-Type: application/json' \
  -d '{"email":"[email protected]","password":"…"}'
# → {"token":"8a4f3e21d6c94b0e9f2a1c5b7d8e4f60"}

Send the token as the bare value of the Authorization header — no Bearer prefix:

Authorization: 8a4f3e21d6c94b0e9f2a1c5b7d8e4f60

Auth endpoints

Method Path Purpose
POST /auth/check-email Is this email registered? (404 = free to register)
POST /auth/verify-email Send a 6-digit verification code (one request per 60 s)
POST /auth/register Create the account; returns your first session {token}
POST /auth/sessions Log in with password, or email + fresh verification code
DELETE /auth/sessions Log out (invalidate the token)
POST /auth/forgot-password Email a password-reset link (always 204; never reveals accounts)
POST /auth/reset-password Set a new password with the emailed reset token

Registration uses a 6-digit email verification code (POST /auth/verify-email then POST /auth/register). Codes expire after 15 minutes, lock after 5 failed submissions, and are single-use — registration consumes the code and returns the session token for your first session directly, so no separate login is needed (or possible with the same code). A password is optional: omit it at registration for a passwordless account that always logs in with a fresh code.

Registration is bounded two ways: one account per inbox — address aliases that deliver to the same mailbox (for Gmail, dots and +suffix variants of the local part) count as the same inbox and are rejected with 400 — and a small daily allowance of new accounts per network, rejected with 429 when exhausted. One account gives full access, so neither bound affects normal use.

Your profile is at GET /user — it reports your id, email, rate-limit usage_percent, your effective fee schedule, and your slippage setting. PATCH /user updates the email, password, fee schedule, or slippage.

GET /user

Signed in? This sends your own session token and shows your real profile.

Interactive — run this request from the docs

You can delete your account permanently: POST /user/delete-code emails a confirmation code, then POST /user/delete (with the code) permanently deletes your account — your data cannot be recovered. It needs every trading session closed first (409 session_open otherwise). Stopping a bot is not enough on its own: it halts the strategy and the session stays open holding its positions, so close them — a liquidation does it in one call — or wait for the market close, which settles whatever is still open.

Conventions

  • Content type — every request with a JSON body sends Content-Type: application/json, authenticated or not; responses are JSON unless noted.
  • Decimals — monetary values are JSON strings ("500000", "1.45") to preserve precision. Parse them with a decimal library, not a float.
  • Times — request timestamps are RFC 3339 with a timezone (2025-01-15T14:30:00Z); always include the Z or an offset. Snapshot timestamps in URL paths use YYYY-MM-DDTHH:MM:SS in UTC.
  • Errors — the status code carries the meaning; the body carries the reason. Most validation errors return a small JSON envelope ({"message": "…"}, or {"error": "<code>", …} for feature and rate-limit errors); two exceptions are relayed as short plain-text bodies: live-order rejections from the exchange and some auth-flow errors. Never parse error prose — branch on the status code (and the error code where present).

Access levels

There are exactly two levels of access — registration is free and nothing is paid:

Access Market data History Notes
Visitor 30-second Most recent completed session only Unauthenticated
Registered 1-second All dates Free account; accounts & sessions; custom fees

Today's in-progress session returns 1-second data to everyone until it closes. See Access & accounts for details.

Status codes

Status When
200 OK with body
201 Resource created
202 Accepted — queued for asynchronous processing (results updates, bot commands)
204 OK, no body
400 Validation error (reason in the body)
401 Missing or invalid auth
403 Forbidden for this account
404 Not found, or not yours
409 Conflict — the resource's current state forbids it (e.g. an order that is already terminal, or not yet live)
422 Semantically invalid (e.g. portfolio member rules, session outside RTH)
429 Rate limit or concurrency cap hit
500 Server error
503 Live trading briefly unavailable — safe to retry; no state changed
504 outcome_unknown (mutating live requests) — the exchange couldn't confirm within the deadline whether the request applied. Retry under the same Idempotency-Key (returns the original outcome; a 409 duplicate_idempotency_key while it's still in flight means keep retrying) or reconcile with a GET.

Rate limiting

Market-data endpoints are rate-limited for all authenticated accounts via a credit budget; exceeding it returns 429. Visitor traffic isn't metered because it can only reach the most recent session at coarse resolution. See rate limits for the leaky-bucket mechanism and per-endpoint costs.

Where to go next