Developers

Developer API

Read live market data and trade your practice account programmatically. Every order is simulated with virtual funds.

Introduction

The API is a plain REST / JSON interface. Send JSON bodies with Content-Type: application/json; every response is JSON except the CSV exports. Timestamps are Unix seconds (floats) and all amounts are in USD.

Practice accounts — virtual funds. Orders placed through the API are paper trades on a simulated account. Nothing is routed to an exchange and no real money moves. Market data comes from free public feeds and may be delayed.
Rate limits. There is no hard limit, but please be reasonable: stay around 5 requests per second per account and cache market data you poll often (quotes refresh every few seconds at most). Abusive clients may have their keys revoked.

Authentication

Create a key under Account → API keys. The full key (beginning sk_demo_) is shown once — store it somewhere safe. Send it on every request as a bearer token:

Authorization: Bearer sk_demo_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  • A key acts as your account: it can read your portfolio, place and cancel orders, and download reports.
  • Keys cannot create new API keys, and they cannot reach staff / back-office endpoints (staff accounts can't use keys at all).
  • You can revoke a key at any time from the same page; revoked keys return 401 immediately.
  • Public market-data endpoints work without a key. In the browser, the site's session cookie also authenticates requests — that's what the console below uses.

Quick start

Examples in curl, Python (requests) and JavaScript (fetch). Pick a language once and every sample switches. Replace sk_demo_… with your key.

Errors

Failures use conventional HTTP status codes and a JSON body with a single human-readable error field:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{"error": "Limit price required"}
StatusMeaning
200Success. Order rejections that happen after acceptance (e.g. a market order that could not fill) come back as 200 with order.status = "rejected" and a reason.
400Invalid request — missing or malformed parameters, insufficient buying power, bracket prices on the wrong side, unknown export kind.
401Not signed in, unknown or revoked API key, wrong credentials.
403Not allowed — e.g. creating an API key with an API key, staff endpoints via a key, restricted account.
404Unknown endpoint, symbol, order or resource.
500 / 502Server error, or an upstream data source (e.g. fundamentals) is unavailable. Retry with back-off.

Order types

Send orders to POST /api/orders. Required: symbol, side (buy/sell), type, qty. Crypto and stocks accept fractional quantities; options trade in whole contracts (×100 multiplier).

Type / fieldParametersBehaviour

Try it

Run read-only GET requests against the live API right here. The console uses your logged-in browser session (the sid cookie, same-origin) rather than an API key, so account endpoints return your own account data.

GET /api/ ?
Choose an endpoint and press Run (or Enter in the query box).