Trading API
Trade the simulator from your own code, over HTTP or a WebSocket.
Get an API key
An API key is its own trading account with its own balance. It is not connected to a website login. We email a link that reveals the key once. An email address has one key: asking again replaces it, and the account, its balance and its orders stay as they are.
HTTP API
The base address is https://easyapitrade.com/api/v1. Send your key in the X-API-Key header;
Authorization: Bearer works too. Request and response bodies are JSON.
| Endpoint | What it does |
|---|---|
GET /instruments | The tradable symbols. |
GET /quotes | The latest quote for every symbol. open says whether it can be traded now. |
GET /quotes/{symbol} | The latest quote for one symbol. |
GET /account | Cash balance and what is left of today's deposit allowance. |
POST /deposits | Deposit play money, up to 1,000 a day. The limit resets at 00:00 UTC. |
GET /positions | Holdings with their value and gain or loss. |
POST /orders | Buy or sell. Fills at once at the latest quote. |
GET /orders | Order history, newest first. Page with limit and before. |
GET /orders/{id} | One order. |
Deposit, then check the account:
curl -X POST https://easyapitrade.com/api/v1/deposits \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{"amount": 500}'
curl https://easyapitrade.com/api/v1/account -H "X-API-Key: $KEY"
The machine-readable description is at /api/openapi/v1.json.
Placing orders
An order names a symbol and a side (buy or sell) and is sized by
exactly one of:
| Field | Meaning |
|---|---|
quantity | Units to trade, with up to 8 decimal places. |
amount | Dollars to spend (buy) or to receive (sell). |
all | true sells the whole holding. Sells only. |
# Buy $120 of SPY curl -X POST https://easyapitrade.com/api/v1/orders \ -H "X-API-Key: $KEY" -H "Content-Type: application/json" \ -d '{"symbol": "SPY", "side": "buy", "amount": 120}' # Sell 0.05 SPY, safely retryable curl -X POST https://easyapitrade.com/api/v1/orders \ -H "X-API-Key: $KEY" -H "Content-Type: application/json" \ -d '{"symbol": "SPY", "side": "sell", "quantity": 0.05, "client_order_id": "my-id-1"}'
Send a client_order_id to make a retry safe: the same id returns the original order
instead of placing a second one. Costs are rounded up to the cent and proceeds down. There are no fees.
Errors
Errors are problem documents (application/problem+json) with a human-readable detail and a stable code:
| Code | Status | Meaning |
|---|---|---|
unauthorized | 401 | The API key is missing or unknown. |
invalid_request | 400 | The request is malformed, for example two sizes on one order. |
unknown_symbol | 404 | The symbol is not tradable here. |
market_closed | 409 | The symbol has no live quote right now. |
insufficient_funds | 422 | The order costs more than the cash balance. |
insufficient_position | 422 | The order sells more than is held. |
amount_too_small | 422 | The order is worth less than one cent. |
deposit_limit_exceeded | 422 | The deposit would pass the daily limit. |
idempotency_conflict | 409 | The client_order_id was already used for a different order. |
order_limit_exceeded | 429 | The account has filled its orders for this minute. The detail says how long to wait. |
rate_limited | 429 | Too many requests. Slow down and retry. |
busy | 503 | The account is busy with other requests. Retry. |
WebSocket API
Connect to wss://easyapitrade.com/stream/v1/ws with the same X-API-Key header.
Messages are JSON text frames. Lines marked → are sent by you, ← by the server.
→ {"op": "subscribe", "symbols": ["SPY", "BTC-USD"]}
← {"type": "subscribed", "symbols": ["BTC-USD", "SPY"]}
← {"type": "quote", "symbol": "SPY", "price": 670.12, "volume": 1840,
"trade_ts": 1791240000123, "ts": 1791240000500}
→ {"op": "order", "id": "1", "symbol": "SPY", "side": "buy", "amount": 120}
← {"type": "order", "id": "1", "order": { … }}
← {"type": "error", "id": "1", "code": "insufficient_funds", "message": "…"}
→ {"op": "ping"}
← {"type": "pong"}
Subscribe to "*" for every symbol. Each symbol sends at most one quote per second: the last
traded price and the volume since the previous quote. ts is when the quote was published and
trade_ts the time of the last trade, both in Unix milliseconds.
Orders take the same fields as the HTTP API, plus an id of your choice that comes back on the reply.
A client that falls behind is sent the newest quotes and skips the ones it missed.
🤖 AI Agent
Working with an AI coding agent? Paste this to get it started.
You are helping me trade on Easy API Trade (https://easyapitrade.com), a trading simulator. It uses play money only: no real funds and no real market orders. Easy API Trade has live prices, an HTTP API and a WebSocket. With an API key I can deposit play money, read quotes, buy and sell at the latest price, and read my positions and orders. Read the API docs at https://easyapitrade.com/api/openapi/v1.json before writing any code. Ask me for my API key when you need it, and put that key in the X-API-Key header.
SDK
Starter scripts to copy and run. Each one connects with your API key, deposits $100 of play money and buys $25 of SPY. First make the load function return your key from wherever you keep it outside your code.
Python
# pip install requests import requests API = "https://easyapitrade.com/api/v1" def load_api_key_from_environment(): """ Read the API key out of the environment this script runs in: an environment variable, an encrypted config file, a secrets manager, and so on. The key should never be in a code file, and never committed to a repository or source control (GitHub, GitLab, etc.). """ return None # Connect client = requests.Session() client.headers["X-API-Key"] = load_api_key_from_environment() # Deposit deposit = {"amount": 100} response = client.post(API + "/deposits", json=deposit) print(response.json()) # Buy buy = {"symbol": "SPY", "side": "buy", "amount": 25} response = client.post(API + "/orders", json=buy) print(response.json())
C#
using System;
using System.Net.Http;
using System.Net.Http.Json;
class Program
{
const string Api = "https://easyapitrade.com/api/v1";
static string LoadApiKeyFromEnvironment()
{
/*
* Read the API key out of the environment this program runs in: an environment
* variable, an encrypted config file, a secrets manager, and so on.
*
* The key should never be in a code file, and never committed to a repository
* or source control (GitHub, GitLab, etc.).
*/
return null;
}
static void Main()
{
// Connect
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", LoadApiKeyFromEnvironment());
// Deposit
var deposit = new { amount = 100 };
HttpResponseMessage response = client.PostAsJsonAsync(Api + "/deposits", deposit).Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
// Buy
var buy = new { symbol = "SPY", side = "buy", amount = 25 };
response = client.PostAsJsonAsync(Api + "/orders", buy).Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
}