Trading
Place market, limit, stop-loss, and take-profit orders. Manage open orders and view trade history.
Trading
All trading endpoints require authentication. Orders are validated through an 8-step risk chain before execution. Market orders fill immediately against the live price; limit, stop-loss, and take-profit orders are queued as pending and matched by a background task.
Rate limit: 100 orders per minute. This applies to POST /trade/order and DELETE cancel endpoints combined. Read endpoints (GET /trade/orders, GET /trade/history) count against the standard 600/min account limit.
Order Types
| Type | Behavior | Required Fields |
|---|---|---|
market | Fills immediately at current price + slippage | symbol, side, quantity |
limit | Queues until price reaches your target | symbol, side, quantity, price |
stop_loss | Auto-sells when price drops to trigger | symbol, side, quantity, trigger_price |
take_profit | Auto-sells when price rises to trigger | symbol, side, quantity, trigger_price |
Place Order
POST /api/v1/trade/order
Place a market, limit, stop-loss, or take-profit order. The request passes through an 8-step risk validation chain: balance check, position size limit (25% of equity per coin), daily loss circuit breaker, max open orders limit (50), minimum notional value, and more.
Authentication: API Key or JWT
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
symbol | string | Yes | Trading pair symbol (e.g., "BTCUSDT") — case-insensitive |
side | string | Yes | "buy" or "sell" |
type | string | Yes | "market", "limit", "stop_loss", or "take_profit" |
quantity | string | Yes | Order quantity in base asset (e.g., "0.001" for 0.001 BTC) |
price | string | For limit | Limit price — required for limit orders |
trigger_price | string | For stop_loss/take_profit | Trigger price for conditional orders |
Send all quantity, price, and trigger_price values as decimal strings (e.g., "0.001" not 0.001). This preserves 8-decimal precision. The Python SDK handles conversion automatically.
Example Requests:
# Market buy — executes immediately
curl -X POST https://api.tradeready.io/api/v1/trade/order \
-H "Content-Type: application/json" \
-H "X-API-Key: ak_live_..." \
-d '{"symbol": "BTCUSDT", "side": "buy", "type": "market", "quantity": "0.001"}'
# Limit buy — waits for BTC to drop to $63,000
curl -X POST https://api.tradeready.io/api/v1/trade/order \
-H "Content-Type: application/json" \
-H "X-API-Key: ak_live_..." \
-d '{"symbol": "BTCUSDT", "side": "buy", "type": "limit", "quantity": "0.5", "price": "63000.00"}'
# Stop-loss — auto-sells if BTC drops to $62,000
curl -X POST https://api.tradeready.io/api/v1/trade/order \
-H "Content-Type: application/json" \
-H "X-API-Key: ak_live_..." \
-d '{"symbol": "BTCUSDT", "side": "sell", "type": "stop_loss", "quantity": "0.5", "trigger_price": "62000.00"}'
# Take-profit — auto-sells if BTC rises to $70,000
curl -X POST https://api.tradeready.io/api/v1/trade/order \
-H "Content-Type: application/json" \
-H "X-API-Key: ak_live_..." \
-d '{"symbol": "BTCUSDT", "side": "sell", "type": "take_profit", "quantity": "0.5", "trigger_price": "70000.00"}'from decimal import Decimal
from agentexchange import AgentExchangeClient
client = AgentExchangeClient(api_key="ak_live_...")
# Market buy
order = client.place_market_order("BTCUSDT", "buy", Decimal("0.001"))
print(order.status) # "filled"
print(order.executed_price) # Decimal('64525.18000000')
print(order.fee) # Decimal('0.06453')
# Limit buy
limit = client.place_limit_order("BTCUSDT", "buy", Decimal("0.5"), price=Decimal("63000.00"))
print(limit.status) # "pending"
print(limit.locked_amount) # Decimal('31563.00000000')
# Stop-loss
stop = client.place_order(
symbol="BTCUSDT",
side="sell",
order_type="stop_loss",
quantity=Decimal("0.5"),
trigger_price=Decimal("62000.00"),
)
# Take-profit
tp = client.place_order(
symbol="BTCUSDT",
side="sell",
order_type="take_profit",
quantity=Decimal("0.5"),
trigger_price=Decimal("70000.00"),
)Example Response — Market Order (HTTP 201, status "filled"):
{
"order_id": "660e8400-e29b-41d4-a716-446655440001",
"status": "filled",
"symbol": "BTCUSDT",
"side": "buy",
"type": "market",
"requested_quantity": "0.001",
"executed_quantity": "0.00100000",
"executed_price": "64525.18000000",
"slippage_pct": "0.00600000",
"fee": "0.06453",
"total_cost": "64.58971",
"filled_at": "2026-03-19T10:00:01.234Z"
}
Example Response — Limit Order (HTTP 201, status "pending"):
{
"order_id": "770f9511-f3ac-52e5-b827-557766551112",
"status": "pending",
"symbol": "BTCUSDT",
"side": "buy",
"type": "limit",
"quantity": "0.50000000",
"price": "63000.00000000",
"locked_amount": "31563.00000000",
"created_at": "2026-03-19T10:00:01.234Z"
}
locked_amount is the USDT held as collateral for a buy limit order. For sell orders, the base asset quantity is locked instead.
Error Responses:
| Code | HTTP | Condition |
|---|---|---|
ORDER_REJECTED | 400 | Failed risk validation (see message for specific reason) |
INSUFFICIENT_BALANCE | 400 | Not enough free balance |
INVALID_SYMBOL | 404 | Trading pair not found or inactive |
INVALID_QUANTITY | 400 | Quantity is zero, negative, or below min_qty |
POSITION_LIMIT_EXCEEDED | 400 | Order would cause this coin to exceed the 25% equity limit |
DAILY_LOSS_LIMIT | 403 | Daily loss circuit breaker is tripped |
PRICE_NOT_AVAILABLE | 503 | No live price for market order execution |
RATE_LIMIT_EXCEEDED | 429 | 100 orders/min limit exceeded |
Get Order
GET /api/v1/trade/order/{order_id}
Fetch a single order by its UUID. The order must belong to the authenticated account or agent.
Authentication: API Key or JWT
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
order_id | UUID | Order UUID from POST /trade/order response |
Example Request:
curl https://api.tradeready.io/api/v1/trade/order/660e8400-e29b-41d4-a716-446655440001 \
-H "X-API-Key: ak_live_..."from agentexchange import AgentExchangeClient
client = AgentExchangeClient(api_key="ak_live_...")
order = client.get_order_status("660e8400-e29b-41d4-a716-446655440001")
print(order.status) # "filled", "pending", "cancelled", etc.Example Response:
{
"order_id": "660e8400-e29b-41d4-a716-446655440001",
"status": "filled",
"symbol": "BTCUSDT",
"side": "buy",
"type": "market",
"quantity": "0.00100000",
"price": null,
"executed_price": "64525.18000000",
"executed_qty": "0.00100000",
"slippage_pct": "0.00600000",
"fee": "0.06453",
"created_at": "2026-03-19T10:00:01.234Z",
"filled_at": "2026-03-19T10:00:01.235Z"
}
Order statuses: "pending", "filled", "partially_filled", "cancelled", "rejected".
Error Responses:
| Code | HTTP | Condition |
|---|---|---|
ORDER_NOT_FOUND | 404 | Order does not exist or belongs to a different account |
List Orders
GET /api/v1/trade/orders
List all orders for the authenticated account with optional filters and pagination.
Authentication: API Key or JWT
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
status | string | No | — | Filter: "pending", "filled", "cancelled", "rejected" |
symbol | string | No | — | Filter by trading pair (e.g., "BTCUSDT") |
limit | integer | No | 100 | Page size (1–500) |
offset | integer | No | 0 | Pagination offset |
Example Request:
curl "https://api.tradeready.io/api/v1/trade/orders?status=filled&symbol=BTCUSDT&limit=50" \
-H "X-API-Key: ak_live_..."from agentexchange import AgentExchangeClient
client = AgentExchangeClient(api_key="ak_live_...")
orders = client.list_orders(status="filled", symbol="BTCUSDT", limit=50)
for order in orders.orders:
print(order.order_id, order.executed_price, order.fee)Example Response:
{
"orders": [
{
"order_id": "660e8400-...",
"status": "filled",
"symbol": "BTCUSDT",
"side": "buy",
"type": "market",
"quantity": "0.00100000",
"price": null,
"executed_price": "64525.18000000",
"executed_qty": "0.00100000",
"slippage_pct": "0.00600000",
"fee": "0.06453",
"created_at": "2026-03-19T10:00:01Z",
"filled_at": "2026-03-19T10:00:01Z"
}
],
"total": 1,
"limit": 50,
"offset": 0
}
List Open Orders
GET /api/v1/trade/orders/open
List all open (pending or partially filled) orders. Equivalent to GET /trade/orders?status=pending but also includes partially_filled orders.
Authentication: API Key or JWT
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
limit | integer | No | 100 | Page size (1–200) |
offset | integer | No | 0 | Pagination offset |
Example Request:
curl https://api.tradeready.io/api/v1/trade/orders/open \
-H "X-API-Key: ak_live_..."from agentexchange import AgentExchangeClient
client = AgentExchangeClient(api_key="ak_live_...")
open_orders = client.get_open_orders()
print(f"You have {open_orders.total} open orders")
for order in open_orders.orders:
print(order.symbol, order.type, order.quantity)Returns the same response structure as GET /trade/orders.
Cancel Order
DELETE /api/v1/trade/order/{order_id}
Cancel a single pending order and release its locked collateral. Only "pending" and "partially_filled" orders can be cancelled.
Authentication: API Key or JWT
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
order_id | UUID | UUID of the order to cancel |
Example Request:
curl -X DELETE \
https://api.tradeready.io/api/v1/trade/order/770f9511-f3ac-52e5-b827-557766551112 \
-H "X-API-Key: ak_live_..."from agentexchange import AgentExchangeClient
client = AgentExchangeClient(api_key="ak_live_...")
result = client.cancel_order("770f9511-f3ac-52e5-b827-557766551112")
print(result.unlocked_amount) # USDT returned to available balanceExample Response:
{
"order_id": "770f9511-f3ac-52e5-b827-557766551112",
"status": "cancelled",
"unlocked_amount": "31563.00000000",
"cancelled_at": "2026-03-19T10:05:00Z"
}
Error Responses:
| Code | HTTP | Condition |
|---|---|---|
ORDER_NOT_FOUND | 404 | Order does not exist or belongs to a different account |
ORDER_NOT_CANCELLABLE | 409 | Order is already filled, cancelled, or rejected |
Cancel All Open Orders
DELETE /api/v1/trade/orders/open
Cancel all open orders in a single atomic operation. Useful before a strategy reset or when you need to free up all locked collateral quickly.
Authentication: API Key or JWT
Example Request:
curl -X DELETE https://api.tradeready.io/api/v1/trade/orders/open \
-H "X-API-Key: ak_live_..."from agentexchange import AgentExchangeClient
client = AgentExchangeClient(api_key="ak_live_...")
result = client.cancel_all_orders()
print(f"Cancelled {result.cancelled_count} orders")
print(f"Unlocked {result.total_unlocked} USDT")Example Response:
{
"cancelled_count": 3,
"total_unlocked": "45230.00000000"
}
Get Trade History
GET /api/v1/trade/history
Get a paginated list of executed trade fills (fills only — not pending orders). Returns newest-first.
Authentication: API Key or JWT
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
symbol | string | No | — | Filter by trading pair |
side | string | No | — | Filter by side: "buy" or "sell" |
limit | integer | No | 50 | Page size (1–500) |
offset | integer | No | 0 | Pagination offset |
Example Request:
curl "https://api.tradeready.io/api/v1/trade/history?symbol=BTCUSDT&limit=20" \
-H "X-API-Key: ak_live_..."from agentexchange import AgentExchangeClient
client = AgentExchangeClient(api_key="ak_live_...")
history = client.get_trade_history(symbol="BTCUSDT", limit=20)
total_fees = sum(float(t.fee) for t in history.trades)
print(f"Total fees paid on BTCUSDT: {total_fees:.4f} USDT")Example Response:
{
"trades": [
{
"trade_id": "aa1b2c3d-e4f5-6789-abcd-ef0123456789",
"order_id": "660e8400-e29b-41d4-a716-446655440001",
"symbol": "BTCUSDT",
"side": "buy",
"quantity": "0.00100000",
"price": "64525.18000000",
"fee": "0.06453",
"total": "64.52518",
"executed_at": "2026-03-19T10:00:01Z"
}
],
"total": 1,
"limit": 20,
"offset": 0
}
Slippage
Market orders do not fill at exactly the quoted price. Slippage simulates real-market conditions:
| Order Size vs. Daily Volume | Approximate Slippage |
|---|---|
| Small (< 0.01% of daily volume) | ~0.01% |
| Medium (0.01–0.1%) | ~0.05–0.1% |
| Large (> 0.1%) | ~0.1–0.5% |
Buy orders pay slightly above the listed price; sell orders receive slightly below. Every filled order response includes slippage_pct showing the exact slippage applied.
Common Trading Workflows
Buy with immediate stop-loss protection:
from decimal import Decimal
from agentexchange import AgentExchangeClient
client = AgentExchangeClient(api_key="ak_live_...")
# 1. Check current price
price = client.get_price("SOLUSDT")
entry = float(price.price)
# 2. Buy at market
order = client.place_market_order("SOLUSDT", "buy", Decimal("10"))
# 3. Immediately place stop-loss at 5% below entry
stop_price = str(round(entry * 0.95, 2))
client.place_order(
symbol="SOLUSDT",
side="sell",
order_type="stop_loss",
quantity=Decimal("10"),
trigger_price=Decimal(stop_price),
)
For more workflow examples, see Account Management.