Skip to main content

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"
}
FieldTypeRequiredNotes
symbolstringyesRocky perp symbol, e.g. BTC-PERP.
sidestringyesBUY or SELL (uppercase).
pricestringyesLimit price, > 0. Web v1 orders are always limit orders.
qtystringyesQuantity, > 0.
leverageintegeryes1–100.
idempotency_keystringyesRe-sending the same key within 15 minutes returns the original order_id with 200.
tp_pricestringnoAttached take-profit trigger price; must be above price for BUY, below for SELL.
sl_pricestringnoAttached 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.