Orders
Place, cancel, query, and list orders. Inspect your own fills.
Authentication
All endpoints in this page require JWT or API Key:
Authorization: Bearer <JWT>
or
X-API-Key: <key>
Place Order
POST /spot/orders
Request Body
{
"symbol": "DFUSDT",
"side": "buy",
"type": "limit",
"tif": "gtc",
"price": "0.5000",
"quantity": "100",
"quote_quantity": null
}
| Field | Type | Required | Notes |
|---|---|---|---|
symbol | string | Yes | Market id from GET /spot/markets. |
side | string | Yes | buy or sell. |
type | string | Yes | limit or market. |
tif | string | No | gtc (default for limit) / ioc / post_only. Market orders are always IOC. |
price | string / number | limit only | Must be a multiple of tick_size. |
quantity | string / number | limit + market sell | Base amount. Must be a multiple of lot_size. |
quote_quantity | string / number | market buy only | Amount of quote (USDT) to spend. Use this instead of quantity for market buys. |
TIF semantics
tif | Behavior |
|---|---|
gtc | Good-Til-Canceled. Resting remainder stays on the book until canceled or fully filled. |
ioc | Immediate-Or-Cancel. Match what you can right now; cancel the rest. Status becomes canceled if any qty remains (filled_qty > 0 indicates partial). |
post_only | Limit-only. If the order would cross the book at placement time, it's rejected with POST_ONLY_REJECT and no fill occurs. Otherwise it rests like a GTC. |
Market BUY contract (quote_quantity)
Market buys lock the quote token (USDT) up front. You specify how much you're willing to spend (quote_quantity); the engine walks asks ascending, filling base in lot_size increments until the lock is exhausted. Any unspent quote is refunded after matching.
Market sells use quantity (base / DF) — same as limit sell.
Self-trade prevention
If your incoming order would cross your own resting order, the new order is rejected with SELF_TRADE (DECLINE_TAKER policy). Existing resting orders are untouched.
Response — 200 OK
Inline fills array reports any matches that happened during this request (Binance-style):
{
"id": "9f2a-...-uuid",
"symbol": "DFUSDT",
"side": "buy",
"type": "limit",
"tif": "gtc",
"price": "0.5",
"quantity": "100",
"quote_quantity": null,
"filled_qty": "30",
"avg_fill_price": "0.499",
"status": "partially_filled",
"reject_reason": null,
"created_at": 1778400000,
"updated_at": 1778400000,
"fills": [
{ "trade_id": "...", "price": "0.499", "quantity": "30", "fee": "0", "fee_token": "DF" }
]
}
fee_token is the token the caller received (BUY → base, SELL → quote). MVP fees are 0; the field is populated for forward compatibility.
Status
status | Meaning |
|---|---|
open | Resting on the book (no fills yet). |
partially_filled | Resting on the book with filled_qty > 0. |
filled | Fully filled — terminal. |
canceled | Canceled by user, IOC remainder, market remainder, or status delist — terminal. |
rejected | Validation failed before the engine accepted it (e.g., self-trade) — terminal. |
expired | (Reserved; not used for spot in MVP.) |
Error responses
| HTTP | error | When |
|---|---|---|
400 | MARKET_NOT_FOUND, INVALID_TICK, INVALID_LOT, BELOW_MIN_NOTIONAL, INSUFFICIENT_BALANCE, POST_ONLY_REJECT, SELF_TRADE, invalid side/type/tif, quote_quantity required for market buy, quantity required for limit/market sell | request validation / engine pre-checks |
404 | MARKET_NOT_FOUND | symbol not in spot_markets |
409 | MARKET_HALTED | market in halted state |
410 | MARKET_DELISTED | market terminal |
503 | spot trading disabled (engine not started) / ENGINE_BUSY (mpsc full) / ENGINE_RESTARTING (recovery in progress) | transient |
500 | DB_ERROR | server fault |
Cancel One
DELETE /spot/orders/:id
:id is the order UUID. Cancels iff the order is open or partially_filled and belongs to the caller. Returns the canceled order.
Response — 200 OK
Same shape as a single order returned by GET /spot/orders/:id, with status = "canceled".
Errors
| HTTP | error |
|---|---|
400 | invalid id (not a UUID) |
403 | FORBIDDEN (order belongs to another user) |
404 | ORDER_NOT_FOUND (already terminal or doesn't exist) |
Cancel All
DELETE /spot/orders?symbol=DFUSDT
Cancels every open / partially_filled order belonging to the caller, optionally scoped to one market. Orders that were already terminal are silently skipped.
Response — 200 OK
{ "canceled": [ { ...order... }, { ...order... } ] }
Get One
GET /spot/orders/:id
Returns one order owned by the caller. 404 ORDER_NOT_FOUND if it doesn't exist or belongs to another user.
{
"id": "9f2a-...", "symbol": "DFUSDT", "side": "buy", "type": "limit", "tif": "gtc",
"price": "0.5", "quantity": "100", "quote_quantity": null,
"filled_qty": "100", "avg_fill_price": "0.499",
"status": "filled", "reject_reason": null,
"created_at": 1778400000, "updated_at": 1778400090
}
List Orders
GET /spot/orders
Query Parameters
| Param | Type | Default | Notes |
|---|---|---|---|
symbol | string | (any) | Filter to one market. |
status | string | (any) | open / partially_filled / filled / canceled / rejected / expired. |
start | number (unix seconds) | (any) | created_at >= start. |
end | number (unix seconds) | (any) | created_at <= end. |
limit | number | 50 | 1–200; clamped server-side. |
Response — 200 OK: array of order objects, newest first.
Tip: to get only currently-open orders, use
GET /spot/orders?status=open(orstatus=partially_filled); both are non-terminal.
My Trades (Fills)
Every fill the caller participated in — as either maker or taker.
GET /spot/trades/me
Query Parameters
| Param | Type | Default | Notes |
|---|---|---|---|
symbol | string | (any) | |
start / end | number (unix seconds) | (any) | |
limit | number | 50 | 1–200. |
Response — 200 OK
[
{
"trade_id": "...",
"symbol": "DFUSDT",
"side": "buy",
"price": "0.499",
"quantity": "30",
"fee": "0",
"fee_token": "DF",
"role": "taker",
"order_id": "9f2a-...",
"ts": 1778400090
}
]
| Field | Notes |
|---|---|
side | The caller's side at this fill (BUY/SELL), not the global taker side. |
fee / fee_token | Fee paid by the caller, in the token they received. |
role | maker or taker. |
order_id | The caller's order id involved in this fill. |
ts | Unix seconds. |
Code Example
End-to-end: place a buy, watch it fill, list resulting trades.
import requests, time
BASE = "https://api-sepolia.p99.world/api/v1"
JWT = "your_jwt_token"
H = {"Authorization": f"Bearer {JWT}", "Content-Type": "application/json"}
# Place a GTC limit buy
order = requests.post(f"{BASE}/spot/orders", headers=H, json={
"symbol": "DFUSDT", "side": "buy", "type": "limit", "tif": "gtc",
"price": "0.5", "quantity": "100"
}).json()
print(order["status"], order["filled_qty"], "/", order["quantity"])
# Poll until terminal
oid = order["id"]
while True:
o = requests.get(f"{BASE}/spot/orders/{oid}", headers=H).json()
if o["status"] in ("filled", "canceled", "rejected"):
break
time.sleep(1)
# Inspect fills
fills = requests.get(f"{BASE}/spot/trades/me?symbol=DFUSDT&limit=10", headers=H).json()
for f in fills:
print(f" {f['role']:5} {f['side']:4} {f['quantity']:>8} @ {f['price']}")