Skip to content

Orders

Field Required Values and use
request_id Yes Unique mutation ID, 8 to 80 characters
client_order_id Yes Unique order ID from your system
market_id Yes Market symbol such as BTC-PERP
side Yes buy or sell
type Yes market or limit
quantity Yes Positive decimal string
leverage Yes Integer from 1 to the market’s maximum_leverage
price Limit orders Positive decimal string
time_in_force No GTC or IOC for Practice; default GTC. FOK is not supported on Practice.
post_only No Valid for GTC limit orders; default false
reduce_only No Prevents the order from increasing exposure
position_id No Position targeted by a reduce-only order
margin_mode No isolated or cross; default isolated
max_slippage_percent Market orders Greater than 0 and no more than 2
expires_at No Not supported on Practice; requests containing it are rejected

Practice orders execute on Novrinex L1 through novrinex-paper. The account and route are bound to your key.

The SDK generates request_id and client_order_id when omitted. Raw HTTP requests must include them.

POST /v1/orders
Content-Type: application/json
{
"request_id": "strategy-a:order:0001",
"client_order_id": "strategy-a-0001",
"market_id": "BTC-PERP",
"side": "buy",
"type": "market",
"quantity": "0.001",
"leverage": 2,
"margin_mode": "isolated",
"max_slippage_percent": "0.50"
}

A successful submission returns HTTP 202:

{
"request_id": "strategy-a:order:0001",
"order_id": "6de51f30-7687-47d3-88b3-20e4a5a9cb34",
"client_order_id": "strategy-a-0001",
"market_id": "BTC-PERP",
"route_id": "novrinex-paper",
"side": "buy",
"type": "market",
"quantity": "0.001",
"price": null,
"trigger_price": null,
"time_in_force": "GTC",
"post_only": false,
"reduce_only": false,
"status": "PENDING",
"execution_stage": "QUEUED",
"received_at": "2026-09-10T11:33:27.837476Z",
"updated_at": "2026-09-10T11:33:27.837476Z",
"filled_quantity": "0",
"average_fill_price": null,
"last_event_sequence": 4182,
"provenance": {"provider": "novrinex"},
"error": null
}

202 means the order was accepted for processing. Read the order or subscribe to order events for its final state.

{
"request_id": "strategy-a:order:0002",
"client_order_id": "strategy-a-0002",
"market_id": "ETH-PERP",
"side": "sell",
"type": "limit",
"quantity": "0.25",
"price": "4200.00",
"time_in_force": "GTC",
"post_only": true,
"leverage": 3,
"margin_mode": "isolated"
}

POST /v1/orders/simulate accepts the same body as order placement and does not create an order.

simulation = await client.simulate_order(order)
if simulation["decision"] == "READY":
accepted = await client.place_order(order)
else:
print(simulation["issues"])

Example simulation response:

{
"market_id": "BTC-PERP",
"route_id": "novrinex-paper",
"decision": "READY",
"required_margin": "34.12",
"reference_price": "68240.50",
"maximum_quantity": "0.145",
"issues": [],
"evaluated_at": "2026-09-10T11:33:20.120000Z",
"expires_at": "2026-09-10T11:33:25.120000Z"
}

Simulation is a point-in-time estimate. Order placement repeats the checks against current data.

GET /v1/orders/6de51f30-7687-47d3-88b3-20e4a5a9cb34

You can also look up an order using your own identifier:

GET /v1/orders/by-client-id/strategy-a-0001

Practice does not support amendment or conditional entry orders. Cancel the existing order, confirm its terminal state, then submit a new order ID. A cancellation can race a fill, so check the filled quantity before replacing it.

POST /v1/orders/6de51f30-7687-47d3-88b3-20e4a5a9cb34/cancel
Content-Type: application/json
{
"request_id": "strategy-a:cancel:0001"
}

Cancel every active order, or only orders in one market:

POST /v1/orders/cancel-all
Content-Type: application/json
{
"request_id": "strategy-a:cancel-all:0001",
"market_id": "BTC-PERP"
}

Send only request_id to cancel all active orders.

POST /v1/positions/{position_id}/close
Content-Type: application/json
{
"request_id": "strategy-a:close:0001",
"client_order_id": "strategy-a-close-0001",
"quantity_percent": "50",
"max_slippage_percent": "0.50"
}

quantity_percent defaults to 100.

POST /v1/orders/batch accepts 1 to 20 orders:

{
"request_id": "strategy-a:batch:0001",
"orders": [
{
"request_id": "strategy-a:order:0101",
"client_order_id": "strategy-a-0101",
"market_id": "BTC-PERP",
"side": "buy",
"type": "limit",
"quantity": "0.001",
"price": "67500",
"leverage": 2
},
{
"request_id": "strategy-a:order:0102",
"client_order_id": "strategy-a-0102",
"market_id": "ETH-PERP",
"side": "buy",
"type": "limit",
"quantity": "0.02",
"price": "3500",
"leverage": 2
}
]
}

The response contains one result per order. A failure for one order does not roll back the others.

Set a deadline that requests cancellation of active orders in the bound Practice account if your client stops refreshing it:

PUT /v1/cancel-all-after
Content-Type: application/json
{
"request_id": "strategy-a:dead-man:0001",
"timeout_seconds": 30
}
{
"request_id": "strategy-a:dead-man:0001",
"deadline_at": "2026-09-10T11:34:00.000000Z"
}

The service enforces the deadline and submits cancellations to L1. Confirmation depends on service and chain availability; the deadline is not a guarantee of cancellation at that exact instant.

Refresh the deadline with a new request_id before it expires. Set timeout_seconds to 0 to disable it.

Every mutation uses request_id for idempotency. Repeating the same request ID with the same body returns the stored result. Reusing it with different content returns IDEMPOTENCY_CONFLICT.

After a timeout, recover the original request:

GET /v1/requests/strategy-a:order:0001
{
"request_id": "strategy-a:order:0001",
"command_type": "order.open",
"state": "COMPLETED",
"result": {
"order_id": "6de51f30-7687-47d3-88b3-20e4a5a9cb34",
"status": "PENDING"
},
"created_at": "2026-09-10T11:33:27.837476Z",
"updated_at": "2026-09-10T11:33:27.901200Z",
"completed_at": "2026-09-10T11:33:27.901200Z"
}
Status Meaning
PENDING Accepted and waiting for submission
SUBMITTED Submitted for execution
OPEN Resting and active
PARTIALLY_FILLED Partially filled and still active
FILLED Fully filled
CANCELLED Cancelled
REJECTED Rejected before or during submission
UNKNOWN Final state is being reconciled