Place Order (Web v1)
POST /v1/orders
Web v1 native — used by Rocky's browser UI. Bots should prefer the FAPI place-order.
Auth: Authorization: Bearer <session_token> — the session_token returned by POST /v1/wallet/verify (after POST /v1/wallet/challenge; sessions last 24 h). The order is placed for the session's user — there is no user_id field.
Request
POST /v1/orders
Authorization: Bearer <session_token>
Content-Type: application/json
{
"symbol": "BTC-PERP",
"side": "BUY",
"price": "76500.00",
"qty": "0.001",
"leverage": 10,
"idempotency_key": "ui-1748275200-abc",
"tp_price": "78000.00",
"sl_price": "75000.00"
}
| Field | Type | Required | Notes |
|---|---|---|---|
symbol | string | yes | Rocky perp symbol, e.g. BTC-PERP. |
side | string | yes | BUY or SELL (uppercase). |
price | string | yes | Limit price, > 0. Web v1 orders are always limit orders. |
qty | string | yes | Quantity, > 0. |
leverage | integer | yes | 1–100. |
idempotency_key | string | yes | Re-sending the same key within 15 minutes returns the original order_id with 200. |
tp_price | string | no | Attached take-profit trigger price; must be above price for BUY, below for SELL. |
sl_price | string | no | Attached stop-loss trigger price; must be below price for BUY, above for SELL. |
leverage is 1–100 (validated; previously this field was accepted but silently capped to a system-wide 10x — margin and fills now use whatever leverage the order actually requests). A position's leverage is set by whichever order opens it (or last adds to it in the same direction); a reduce-only/closing order's leverage field doesn't affect the margin math for the exposure it's closing — that always unwinds at the position's existing leverage.
tp_price / sl_price (when present and non-empty) arm a full-position-close TP/SL for the session user + symbol after the order is accepted. This is best-effort: a failed TP/SL write is logged and does not fail the placement.
Response — 200
{ "order_id": "0196a1b2c3d4e5f6a7b8c9d0e1f2a3b4" }
Returns the created order_id (UUID without hyphens).
Errors (plain-text body): 400 invalid params (side not BUY/SELL, leverage outside 1–100, non-positive price/qty, unknown symbol, tp_price/sl_price on the wrong side of price) — and also 400 for rejected placements: insufficient available balance, market … is not active, trading paused (IF threshold) / high-leverage orders paused; 401 missing/invalid session token; 422 body fails to deserialize (missing field / wrong type); 503 trading service down; 504 trading service timeout.