Skip to content

Market and account data

Market data is public. Account, position, order, and fill data requires a signed request with the matching read scope.

Terminal window
curl https://trading-api.testnet.novrinex.com/v1/markets

This returns currently tradable Practice markets, including price_tick, quantity_step, minimum_quantity, minimum_notional, maximum_leverage, margin_modes and order_types. Round order prices and quantities to these increments before submission.

Read one market for its current price data:

Terminal window
curl https://trading-api.testnet.novrinex.com/v1/markets/BTC-PERP
{
"market_id": "BTC-PERP",
"display_name": "BTC",
"base_asset": "BTC",
"quote_asset": "pUSDC",
"category": "crypto",
"status": "active",
"routes": ["novrinex-paper"],
"preferred_route_id": "novrinex-paper",
"mark_price": "68240.50",
"index_price": "68237.10",
"last_price": "68241.00",
"funding_rate": null,
"next_funding_time": null,
"volume_24h": null,
"open_interest": null,
"observed_at": "2026-09-10T11:33:27.843553Z",
"data_status": "live"
}
Terminal window
curl "https://trading-api.testnet.novrinex.com/v1/markets/BTC-PERP/book?depth=5"
{
"market_id": "BTC-PERP",
"route_id": "novrinex-paper",
"market_structure": "order_book",
"sequence": 92810442,
"checksum": "0f2a...",
"bids": [
{"price": "68240.00", "quantity": "1.42", "order_count": 8}
],
"asks": [
{"price": "68240.50", "quantity": "0.91", "order_count": 5}
],
"oracle": null,
"observed_at": "2026-09-10T11:33:27.843553Z"
}

Practice books contain orders committed on Novrinex L1.

Terminal window
curl "https://trading-api.testnet.novrinex.com/v1/markets/BTC-PERP/trades?limit=50"
curl "https://trading-api.testnet.novrinex.com/v1/markets/BTC-PERP/candles?interval=1h&limit=100"

Supported candle intervals are 1m, 5m, 15m, 30m, 1h, 4h, 1d, and 1w.

Trades and candles come from actual Practice executions. A market with no trades has no candles; it can still have a quoted book and an oracle mark price. Missing metrics are null, not zero.

account = await client.account()
print(account["total_equity"])
print(account["available"])
{
"account_id": "00000000-0000-4000-8000-000000000101",
"snapshot_version": 1789040007837476,
"observed_at": "2026-09-10T11:33:27.837476Z",
"total_equity": "12542.84",
"available": "9812.17",
"in_positions": "2730.67",
"unrealized_pnl": "142.61",
"complete": true,
"data_status": "live"
}

GET /v1/accounts returns the same bound Practice account. Account responses include trading_mode: "paper" and settlement_asset: "pUSDC". Current balances and positions come from the native L1 reader. Fill history and order events are reconciled into the API after commitment.

positions = await client.positions(limit=50)
orders = await client.orders(limit=50)
fills = await client.fills(limit=50, market_id="BTC-PERP")
Endpoint Scope Filters
GET /v1/positions account:read limit, cursor
GET /v1/orders orders:read limit, cursor, market_id, status
GET /v1/fills fills:read limit, cursor, market_id

Order status filters are PENDING, SUBMITTED, OPEN, PARTIALLY_FILLED, FILLED, CANCELLED, REJECTED, and UNKNOWN.

List endpoints return an opaque cursor:

{
"data": [],
"page": {
"next_cursor": "eyJ0cyI6...",
"has_more": true
}
}

Pass next_cursor unchanged to the next request:

page = await client.orders(limit=100)
while True:
for order in page["data"]:
print(order["order_id"], order["status"])
if not page["page"]["has_more"]:
break
page = await client.orders(
limit=100,
cursor=page["page"]["next_cursor"],
)

Market data can be live, stale, or unavailable. Account data can be live or degraded.