# Table of Contents - [Introduction](#introduction) - [Installation | 01](#installation-01) - [Setup | 01](#setup-01) - [Funding | 01](#funding-01) - [First Trade | 01](#first-trade-01) - [Key Components | 01](#key-components-01) - [API Reference | 01](#api-reference-01) - [NordUser (Trading & Account) | 01](#norduser-trading-account-01) - [Market Data & Info (Nord Client) | 01](#market-data-info-nord-client-01) - [REST API Reference | 01](#rest-api-reference-01) - [GET /info | 01](#get-info-01) - [GET /market/{market_id}/orderbook | 01](#get-market-market-id-orderbook-01) - [GET /market/{id}/stats | 01](#get-market-id-stats-01) - [GET /trades | 01](#get-trades-01) - [GET /user/{pubkey} | 01](#get-user-pubkey-01) - [GET /timestamp | 01](#get-timestamp-01) - [GET /account/{account_id} | 01](#get-account-account-id-01) - [POST /action | 01](#post-action-01) - [WebSocket Endpoints | 01](#websocket-endpoints-01) - [Initializing Nord | 01](#initializing-nord-01) - [Creating a User from Private Key | 01](#creating-a-user-from-private-key-01) - [Trading Operations | 01](#trading-operations-01) - [Deposits and Withdrawals | 01](#deposits-and-withdrawals-01) - [Account Information | 01](#account-information-01) - [Market Data | 01](#market-data-01) - [Python Integration | 01](#python-integration-01) - [WebSockets | 01](#websockets-01) - [Session & Authentication | 01](#session-authentication-01) - [Funds & Withdrawals (Python) | 01](#funds-withdrawals-python-01) - [Trading Operations (Python) | 01](#trading-operations-python-01) - [Market Data (Python) | 01](#market-data-python-01) - [Page | 01](#page-01) - [Support | 01](#support-01) - [Account Information (Python) | 01](#account-information-python-01) - [FAQ | 01](#faq-01) - [Common Errors | 01](#common-errors-01) - [General FAQ | 01](#general-faq-01) - [Trading FAQ | 01](#trading-faq-01) - [Troubleshooting FAQ | 01](#troubleshooting-faq-01) - [Markets | 01](#markets-01) - [01](#01) - [01](#01) - [01](#01) --- # Introduction [Skip to Content](https://docs.01.xyz/#nextra-skip-nav) Introduction Copy page Introduction ============ **@n1xyz/nord-ts** is a TypeScript SDK for interacting with 01 Exchange, powered by the [N1 blockchain](https://docs.n1.xyz/learn/introduction-to-n1)   and trading infrastructure. Support for Python and raw HTTP integration is also available. [**@n1xyz/nord-ts**\ \ Official Web SDK.\ \ TypeScript SDK](https://docs.01.xyz/getting-started/installation) [**Python**\ \ For trading bots.\ \ Python Integration](https://docs.01.xyz/examples/python) [**REST API**\ \ HTTP Reference.\ \ REST API](https://docs.01.xyz/reference/rest-api) [**N1 Blockchain**\ \ Learn about the architecture.\ \ N1 Blockchain](https://docs.n1.xyz/learn/introduction-to-n1) Features[](https://docs.01.xyz/#features) ------------------------------------------ * **Trading Operations**: Place, cancel, and manage orders with full support for limit, market, and trigger orders * **Account Management**: Create and manage trading accounts with multi-account support * **Real-time Data**: Subscribe to orderbook updates, trades, and account changes via WebSocket * **Atomic Operations**: Execute multiple operations atomically for complex trading strategies Installation[](https://docs.01.xyz/#installation) -------------------------------------------------- ### TypeScript SDK[](https://docs.01.xyz/#typescript-sdk) pnpmnpmyarnbun ### pnpm `pnpm install @n1xyz/nord-ts` ### npm `npm install @n1xyz/nord-ts` ### yarn `yarn add @n1xyz/nord-ts` ### bun `bun add @n1xyz/nord-ts` ### Python Dependencies[](https://docs.01.xyz/#python-dependencies) `pip install protobuf cryptography requests base58` Quick Start (TypeScript)[](https://docs.01.xyz/#quick-start-typescript) ------------------------------------------------------------------------ `import { Nord } from '@n1xyz/nord-ts'; import { Connection } from '@solana/web3.js'; // Initialize Solana connection const connection = new Connection('https://api.devnet.solana.com'); // Create a Nord instance and fetch market data const nord = await Nord.new({ app: 'zoau54n5U24GHNKqyoziVaVxgsiQYnPMx33fKmLLCT5', // 01 Exchange App Key solanaConnection: connection, webServerUrl: 'https://zo-devnet.n1.xyz', // or 'https://zo-mainnet.n1.xyz' for mainnet }); console.log('Nord initialized successfully');` > For Python quick start, see the [Python Integration Guide](https://docs.01.xyz/examples/python) > . Next Steps[](https://docs.01.xyz/#next-steps) ---------------------------------------------- * [Getting Started (TS)](https://docs.01.xyz/getting-started/installation) - TypeScript SDK setup * [Python Integration](https://docs.01.xyz/examples/python) - Python bot setup * [API Reference](https://docs.01.xyz/reference/rest-api) - Raw HTTP endpoints Last updated on February 3, 2026 [Installation](https://docs.01.xyz/getting-started/installation "Installation") --- # Installation | 01 [Skip to Content](https://docs.01.xyz/getting-started/installation#nextra-skip-nav) Getting StartedInstallation Copy page Installation ============ The **Nord SDK** (`@n1xyz/nord-ts`) is the official TypeScript library for interacting with the 01 Exchange. It runs on the N1 blockchain and provides a simple interface for trading, account management, and real-time data. Prerequisites[](https://docs.01.xyz/getting-started/installation#prerequisites) -------------------------------------------------------------------------------- Before you begin, ensure you have the following installed: * **Node.js**: v16 or higher * **Package Manager**: npm, pnpm, yarn, or bun Install the SDK[](https://docs.01.xyz/getting-started/installation#install-the-sdk) ------------------------------------------------------------------------------------ Install the package using your preferred package manager. pnpmnpmyarnbun ### pnpm `pnpm install @n1xyz/nord-ts @solana/web3.js` ### npm `npm install @n1xyz/nord-ts @solana/web3.js` ### yarn `yarn add @n1xyz/nord-ts @solana/web3.js` ### bun `bun add @n1xyz/nord-ts @solana/web3.js` > **Note:** `@solana/web3.js` is a required peer dependency for handling Solana connections and public keys. Next Steps[](https://docs.01.xyz/getting-started/installation#next-steps) -------------------------------------------------------------------------- Once installed, proceed to the **[Setup](https://docs.01.xyz/getting-started/setup) ** guide to initialize the client and create your first user. Last updated on January 16, 2026 [Introduction](https://docs.01.xyz/ "Introduction") [Setup](https://docs.01.xyz/getting-started/setup "Setup") --- # Setup | 01 [Skip to Content](https://docs.01.xyz/getting-started/setup#nextra-skip-nav) [Getting Started](https://docs.01.xyz/getting-started/installation "Getting Started") Setup Copy page Setup ===== In this step, we will initialize the Nord SDK and create a user instance. Initialize the Client[](https://docs.01.xyz/getting-started/setup#initialize-the-client) ----------------------------------------------------------------------------------------- First, create a `Nord` instance to interact with the 01 Exchange. You will need the **01 Exchange App Key** and a Solana RPC connection. > **Note:** For this guide, we are connecting to the **Devnet**. `import { Nord } from "@n1xyz/nord-ts"; import { Connection } from "@solana/web3.js"; // 1. Setup Solana Connection const connection = new Connection("https://api.devnet.solana.com"); // 2. Initialize Nord Client const nord = await Nord.new({ app: "zoau54n5U24GHNKqyoziVaVxgsiQYnPMx33fKmLLCT5", // 01 Exchange App Key solanaConnection: connection, webServerUrl: "https://zo-devnet.n1.xyz", // Devnet URL }); console.log("Nord client initialized!");` Create a User[](https://docs.01.xyz/getting-started/setup#create-a-user) ------------------------------------------------------------------------- To perform actions like trading or successful deposits, you need a `NordUser`. The easiest way to get started programmatically is using a private key. `import { NordUser } from "@n1xyz/nord-ts"; import { Keypair } from "@solana/web3.js"; import bs58 from "bs58"; // requires 'bs58' package if using string key // Replace with your actual private key (Uint8Array or base58 string) // WARNING: Never commit real private keys to version control! const privateKey = "YOUR_PRIVATE_KEY_HERE"; const user = NordUser.fromPrivateKey(nord, privateKey); // Update local state to ensure we have the latest account info await user.updateAccountId(); await user.fetchInfo(); console.log("User initialized:", user.address.toString());` Last updated on February 3, 2026 [Installation](https://docs.01.xyz/getting-started/installation "Installation") [Funding](https://docs.01.xyz/getting-started/funding "Funding") --- # Funding | 01 [Skip to Content](https://docs.01.xyz/getting-started/funding#nextra-skip-nav) [Getting Started](https://docs.01.xyz/getting-started/installation "Getting Started") Funding Copy page Funding ======= Before you can trade, you need to deposit funds into your 01 Exchange account. Supported Assets[](https://docs.01.xyz/getting-started/funding#supported-assets) --------------------------------------------------------------------------------- On **Devnet**, we use mock tokens. You will need `SOL` for transaction fees and `USDC` (or other supported assets) for trading collateral. Depositing Funds[](https://docs.01.xyz/getting-started/funding#depositing-funds) --------------------------------------------------------------------------------- Use the `depositSpl` method to move funds from your Solana wallet into your 01 Exchange account. ``// Example: Deposit 100 USDC // Token ID 0 represents USDC on 01 Exchange const USDC_TOKEN_ID = 0; const AMOUNT_TO_DEPOSIT = 100; try { console.log(`Depositing ${AMOUNT_TO_DEPOSIT} USDC...`); const txId = await user.depositSpl(AMOUNT_TO_DEPOSIT, USDC_TOKEN_ID); console.log("Deposit successful!"); console.log("Transaction ID:", txId); // Refresh user state to see updated balances await user.fetchInfo(); console.log("New Balance:", user.balances[USDC_TOKEN_ID]); } catch (error) { console.error("Deposit failed:", error); }`` > **Tip:** Ensure your Solana wallet has enough SOL to pay for the transaction fees. Last updated on January 16, 2026 [Setup](https://docs.01.xyz/getting-started/setup "Setup") [First Trade](https://docs.01.xyz/getting-started/first-trade "First Trade") --- # First Trade | 01 [Skip to Content](https://docs.01.xyz/getting-started/first-trade#nextra-skip-nav) [Getting Started](https://docs.01.xyz/getting-started/installation "Getting Started") First Trade Copy page First Trade =========== Now that your account is funded, let’s place your first order. Placing a Market Order[](https://docs.01.xyz/getting-started/first-trade#placing-a-market-order) ------------------------------------------------------------------------------------------------- A market order is the simplest way to trade. It executes immediately at the best available price. In this example, we will buy `BTC-PERP` using a market order. `import { Side, FillMode } from "@n1xyz/nord-ts"; // Market ID 0 represents BTC-PERP on 01 Exchange const MARKET_ID = 0; try { console.log("Placing market order..."); const result = await user.placeOrder({ marketId: MARKET_ID, side: Side.Bid, // Buy fillMode: FillMode.FillOrKill, // FOK for Market Order isReduceOnly: false, size: 0.01, // Quantity of BTC // Note: For market orders, price is set to an aggressive value internally }); console.log("Order placed successfully!"); console.log("Action ID:", result.actionId); } catch (error) { console.error("Trading failed:", error); }` Verifying the Trade[](https://docs.01.xyz/getting-started/first-trade#verifying-the-trade) ------------------------------------------------------------------------------------------- After placing the order, you can check your positions to confirm the trade was executed. ``// Refresh data await user.fetchInfo(); // Check positions for Market ID 0 (BTC) const position = user.positions[MARKET_ID]; if (position && position.size > 0) { console.log(`Current Position: ${position.size} BTC`); console.log(`Entry Price: ${position.price}`); } else { console.log("No active position found."); }`` Congratulations! You have successfully initialized the SDK, funded your account, and executed your first trade. Last updated on January 16, 2026 [Funding](https://docs.01.xyz/getting-started/funding "Funding") [Key Components](https://docs.01.xyz/getting-started/key-components "Key Components") --- # Key Components | 01 [Skip to Content](https://docs.01.xyz/getting-started/key-components#nextra-skip-nav) [Getting Started](https://docs.01.xyz/getting-started/installation "Getting Started") Key Components Copy page Key Components ============== Understand the core classes and types used in the Nord SDK. Core Classes[](https://docs.01.xyz/getting-started/key-components#core-classes) -------------------------------------------------------------------------------- ### Nord[](https://docs.01.xyz/getting-started/key-components#nord) The `Nord` class is the main entry point for public API interactions. * **Purpose**: Fetch market data, orderbooks, and global state without user authentication. * **Usage**: Initialize once and pass to other components. ### NordUser[](https://docs.01.xyz/getting-started/key-components#norduser) The `NordUser` class represents an authenticated user. * **Purpose**: Manage account state, place orders, and handle funds. * **Usage**: Created via `NordUser.fromPrivateKey` or `NordUser.fromWallet` (for browser wallets). Important Types & Enums[](https://docs.01.xyz/getting-started/key-components#important-types--enums) ----------------------------------------------------------------------------------------------------- ### Market IDs[](https://docs.01.xyz/getting-started/key-components#market-ids) Markets are identified by numeric IDs, not strings. * `0`: BTC-PERP * `1`: ETH-PERP * `2`: SOL-PERP _(Check the `/info` endpoint for the full list of dynamic IDs)_ ### Side[](https://docs.01.xyz/getting-started/key-components#side) Specifies the direction of an order. `enum Side { Bid = 'Bid', // Buy Ask = 'Ask' // Sell }` ### FillMode[](https://docs.01.xyz/getting-started/key-components#fillmode) Defines how an order should be executed. `enum FillMode { Limit = 0, // Standard limit order PostOnly = 1, // Maker-only order ImmediateOrCancel = 2, // Fill what you can immediately, cancel the rest FillOrKill = 3 // Fill the entire size immediately or cancel (Market Order) }` ### TriggerKind[](https://docs.01.xyz/getting-started/key-components#triggerkind) Used for conditional orders. `enum TriggerKind { StopLoss = 0, TakeProfit = 1 }` Infrastructure[](https://docs.01.xyz/getting-started/key-components#infrastructure) ------------------------------------------------------------------------------------ ### Solana Connection[](https://docs.01.xyz/getting-started/key-components#solana-connection) The SDK relies on `@solana/web3.js` for blockchain interactions. * **Purpose**: Broadcasting transactions and listening for on-chain confirmations. * **Requirement**: Must be a valid RPC connection (e.g., Helius, Alchemy, or generic Solana RPC). Last updated on January 16, 2026 [First Trade](https://docs.01.xyz/getting-started/first-trade "First Trade") [Overview](https://docs.01.xyz/reference "Overview") --- # API Reference | 01 [Skip to Content](https://docs.01.xyz/reference#nextra-skip-nav) API ReferenceOverview Copy page API Reference ============= This section provides detailed information about every method and endpoint available in the Nord SDK. Core Components[](https://docs.01.xyz/reference#core-components) ----------------------------------------------------------------- The SDK is primarily interacted with through two main classes: ### [NordUser](https://docs.01.xyz/reference/nord-user) [](https://docs.01.xyz/reference#norduser) The `NordUser` class handles all **authenticated actions**. This includes placing orders, managing positions, depositing/withdrawing funds, and managing sub-accounts. ### [Nord (Market Data)](https://docs.01.xyz/reference/market-data) [](https://docs.01.xyz/reference#nord-market-data) The `Nord` class (often referred to as the “Client”) handles **public information**. Use this to fetch market statistics, orderbooks, trade history, and real-time data via WebSockets. SDK Installation[](https://docs.01.xyz/reference#sdk-installation) ------------------------------------------------------------------- If you haven’t already, install the SDK using your preferred package manager: pnpmnpmyarnbun ### pnpm `pnpm install @n1xyz/nord-ts @solana/web3.js` ### npm `npm install @n1xyz/nord-ts @solana/web3.js` ### yarn `yarn add @n1xyz/nord-ts @solana/web3.js` ### bun `bun add @n1xyz/nord-ts @solana/web3.js` Last updated on January 16, 2026 [Key Components](https://docs.01.xyz/getting-started/key-components "Key Components") [NordUser (Trading)](https://docs.01.xyz/reference/nord-user "NordUser (Trading)") --- # NordUser (Trading & Account) | 01 [Skip to Content](https://docs.01.xyz/reference/nord-user#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") NordUser (Trading) Copy page NordUser (Trading & Account) ============================ The `NordUser` class is for interacting with the Nord protocol as an authenticated user. It handles trading, balance management, and sub-account operations. Trading Operations[](https://docs.01.xyz/reference/nord-user#trading-operations) --------------------------------------------------------------------------------- ### `placeOrder`[](https://docs.01.xyz/reference/nord-user#placeorder) Places an order on the exchange. **Signature:** `placeOrder(params: PlaceOrderParams): Promise` **Arguments (PlaceOrderParams):** | Name | Type | Required | Description | | --- | --- | --- | --- | | `marketId` | `number` | Yes | Target market identifier. | | `side` | `Side` | Yes | Order side (`Side.Bid` or `Side.Ask`). | | `fillMode` | `FillMode` | Yes | `FillMode.Limit`, `FillMode.PostOnly`, `FillMode.ImmediateOrCancel`, or `FillMode.FillOrKill`. | | `isReduceOnly` | `boolean` | Yes | If true, order only decreases position. | | `size` | `Decimal.Value` | No | Quantity of base asset. Required for most orders. | | `price` | `Decimal.Value` | No | Limit price. Required for Limit orders. | | `quoteSize` | `QuoteSize` | No | Quote-sized order representation for market orders. | | `accountId` | `number` | No | Sub-account ID executing the order. | | `clientOrderId` | `BigIntValue` | No | Optional client-specified identifier. | **Response (PlaceOrderResponse):** | Field | Type | Description | | --- | --- | --- | | `actionId` | `bigint` | Unique identifier for the transaction action. | | `orderId` | `bigint` | (Optional) The ID assigned to the resting order if posted. | | `fills` | `Receipt_Trade[]` | Array of trade receipts if the order was filled. | * * * ### `cancelOrder`[](https://docs.01.xyz/reference/nord-user#cancelorder) Cancels an existing order. **Signature:** `cancelOrder(orderId: BigIntValue, accountId?: number): Promise` **Arguments:** | Name | Type | Required | Description | | --- | --- | --- | --- | | `orderId` | `BigIntValue` | Yes | The ID of the order to cancel. | | `accountId` | `number` | No | The sub-account ID that placed the order. | **Response (CancelResult):** | Field | Type | Description | | --- | --- | --- | | `actionId` | `bigint` | Action identifier for the cancellation. | | `orderId` | `bigint` | The cancelled order ID. | | `accountId` | `number` | The account ID involved. | * * * ### `atomic`[](https://docs.01.xyz/reference/nord-user#atomic) Executes multiple operations (place/cancel) atomically in a single transaction. **Signature:** `atomic(userActions: UserAtomicSubaction[], providedAccountId?: number): Promise` **UserAtomicSubaction Fields:** | Field | Type | Description | | --- | --- | --- | | `kind` | `"place" \| "cancel"` | The type of sub-action. | | `marketId` | `number` | (Optional) Market ID. | | `orderId` | `BigIntValue` | (Optional) Order ID to cancel. | | `side` | `Side` | (Optional) Order side. | | `fillMode` | `FillMode` | (Optional) Fill mode. | | `size` | `Decimal.Value` | (Optional) Quantity. | | `price` | `Decimal.Value` | (Optional) Price. | * * * Trigger Operations[](https://docs.01.xyz/reference/nord-user#trigger-operations) --------------------------------------------------------------------------------- > \[!CAUTION\] **Experimental Feature:** Trigger orders (TP/SL) are currently unstable and may change. Use with caution in production. ### `addTrigger`[](https://docs.01.xyz/reference/nord-user#addtrigger) Adds a stop-loss or take-profit trigger. **Arguments:** | Name | Type | Required | Description | | --- | --- | --- | --- | | `marketId` | `number` | Yes | Market to watch. | | `side` | `Side` | Yes | Order side for the trigger. | | `kind` | `TriggerKind` | Yes | `TriggerKind.StopLoss` or `TriggerKind.TakeProfit`. | | `triggerPrice` | `Decimal.Value` | Yes | Price that activates the trigger. | | `limitPrice` | `Decimal.Value` | No | Optional limit price once triggered. | * * * Fund Management[](https://docs.01.xyz/reference/nord-user#fund-management) --------------------------------------------------------------------------- ### `deposit`[](https://docs.01.xyz/reference/nord-user#deposit) Deposits SPL tokens to the exchange. **Arguments:** | Name | Type | Required | Description | | --- | --- | --- | --- | | `amount` | `number` | Yes | Amount to deposit. | | `tokenId` | `number` | Yes | Token identifier (e.g., 1 for USDC). | | `recipient` | `PublicKey` | No | Recipient address; defaults to user’s address. | **Response:** Returns `{ signature: string, buffer: PublicKey }`. * * * ### `withdraw`[](https://docs.01.xyz/reference/nord-user#withdraw) Withdraws tokens from the exchange to your wallet. **Arguments:** | Name | Type | Required | Description | | --- | --- | --- | --- | | `amount` | `number` | Yes | Amount to withdraw. | | `tokenId` | `number` | Yes | Token identifier. | | `destPubkey` | `string` | No | Optional destination registration pubkey (base58). | * * * Information & State[](https://docs.01.xyz/reference/nord-user#information--state) ---------------------------------------------------------------------------------- ### `fetchInfo`[](https://docs.01.xyz/reference/nord-user#fetchinfo) Refreshes the local state of the user, including balances, orders, and positions. `await user.fetchInfo(); console.log(user.balances);` ### `getSolanaBalances`[](https://docs.01.xyz/reference/nord-user#getsolanabalances) Checks token balances in your Solana wallet context (not on-exchange). **Arguments:** | Name | Type | Default | Description | | --- | --- | --- | --- | | `includeZeroBalances` | `boolean` | `true` | Include tokens with 0 balance. | | `includeTokenAccounts` | `boolean` | `false` | Include specific token account addresses. | Last updated on February 3, 2026 [Overview](https://docs.01.xyz/reference "Overview") [Market Data & Info](https://docs.01.xyz/reference/market-data "Market Data & Info") --- # Market Data & Info (Nord Client) | 01 [Skip to Content](https://docs.01.xyz/reference/market-data#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") Market Data & Info Copy page Market Data & Info (Nord Client) ================================ The `Nord` class (Client) is used to interact with public endpoints of the Nord protocol. It does not require a user session for most operations. Initialization[](https://docs.01.xyz/reference/market-data#initialization) --------------------------------------------------------------------------- `import { Nord } from "@n1xyz/nord-ts"; const nord = await Nord.new({ webServerUrl: "https://zo-mainnet.n1.xyz", solanaConnection: connection, // @solana/web3.js Connection app: APP_PUBLIC_KEY, });` * * * REST Endpoints[](https://docs.01.xyz/reference/market-data#rest-endpoints) --------------------------------------------------------------------------- ### `getInfo`[](https://docs.01.xyz/reference/market-data#getinfo) Returns comprehensive information about all available markets and tokens. **Signature:** `getInfo(): Promise` **Response (MarketsInfo):** | Field | Type | Description | | --- | --- | --- | | `markets` | `Market[]` | Array of available markets (BTC, ETH, etc). | | `tokens` | `Token[]` | Array of available tokens and their metadata. | * * * ### `getMarketStats`[](https://docs.01.xyz/reference/market-data#getmarketstats) Fetches detailed statistics for a specific market, including funding rates and price info. **Signature:** `getMarketStats({ marketId: number }): Promise` **Response (MarketStats):** | Field | Type | Description | | --- | --- | --- | | `indexPrice` | `number` | Current index price from oracle. | | `perpStats.mark_price` | `number` | Current mark price of the perpetual. | | `perpStats.funding_rate` | `number` | Current funding rate. | | `perpStats.open_interest` | `number` | Total open interest in base units. | | `volumeQuote24h` | `number` | 24-hour trading volume in USDC. | * * * ### `getOrderbook`[](https://docs.01.xyz/reference/market-data#getorderbook) Retrieves the current orderbook for a market. **Signature:** `getOrderbook({ symbol?: string, marketId?: number }): Promise` **Response (OrderbookResponse):** | Field | Type | Description | | --- | --- | --- | | `bids` | `[price, size][]` | Array of bids (buy orders). | | `asks` | `[price, size][]` | Array of asks (sell orders). | * * * ### `getTrades`[](https://docs.01.xyz/reference/market-data#gettrades) Retrieves recent trade history for a market or account. **Arguments:** | Name | Type | Description | | --- | --- | --- | | `marketId` | `number` | (Optional) Filter by market. | | `makerId` | `number` | (Optional) Filter by maker account ID. | | `takerId` | `number` | (Optional) Filter by taker account ID. | | `pageSize` | `number` | (Optional) Max trades to return. | * * * WebSockets (Real-time)[](https://docs.01.xyz/reference/market-data#websockets-real-time) ----------------------------------------------------------------------------------------- ### `subscribeOrderbook`[](https://docs.01.xyz/reference/market-data#subscribeorderbook) Subscribes to live orderbook updates. `const sub = nord.subscribeOrderbook("BTCUSDC"); sub.on("update", (data) => { console.log("Orderbook Update:", data); });` ### `subscribeTrades`[](https://docs.01.xyz/reference/market-data#subscribetrades) Subscribes to live trade events. `const sub = nord.subscribeTrades("BTCUSDC"); sub.on("trade", (trade) => { console.log("New Trade:", trade); });` Last updated on January 16, 2026 [NordUser (Trading)](https://docs.01.xyz/reference/nord-user "NordUser (Trading)") [Overview](https://docs.01.xyz/reference/rest-api "Overview") --- # REST API Reference | 01 [Skip to Content](https://docs.01.xyz/reference/rest-api#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") REST APIOverview Copy page REST API Reference ================== The Nord API provides direct HTTP access to 01 Exchange functionality. This is useful for integrations that don’t use the TypeScript SDK. Base URLs[](https://docs.01.xyz/reference/rest-api#base-urls) -------------------------------------------------------------- | Environment | URL | | --- | --- | | Mainnet | `https://zo-mainnet.n1.xyz` | | Devnet | `https://zo-devnet.n1.xyz` | API Documentation[](https://docs.01.xyz/reference/rest-api#api-documentation) ------------------------------------------------------------------------------ The API provides an OpenAPI specification and interactive documentation: * **OpenAPI Spec**: `{BASE_URL}/openapi.json` * **Interactive Docs**: `{BASE_URL}/docs` * **Protobuf Schema**: `{BASE_URL}/schema.proto` Authentication[](https://docs.01.xyz/reference/rest-api#authentication) ------------------------------------------------------------------------ Most read-only endpoints (market data, orderbook, trades) do not require authentication. However, trading operations require a session-based authentication flow. ### Session-Based Authentication[](https://docs.01.xyz/reference/rest-api#session-based-authentication) Trading actions use a two-step authentication process: 1. **Create Session**: Sign a `CreateSession` action with your user wallet key 2. **Execute Actions**: Sign subsequent actions with the session key `Client Server | | |----- CreateSession (user-signed) ----->| | | |<---- session_id -----------------------| | | |----- PlaceOrder (session-signed) ----->| | | |<---- Receipt / Confirmation -----------| | |` ### Signing Actions[](https://docs.01.xyz/reference/rest-api#signing-actions) Actions are signed using Ed25519 signatures. The signing scheme differs based on the action type: | Action Type | Signing Scheme | | --- | --- | | `CreateSession` | User signing (hex-encoded message) | | `PlaceOrder`, `CancelOrder`, etc. | Session signing (raw bytes) | See the [POST /action](https://docs.01.xyz/reference/action) endpoint for detailed signing instructions. Common Response Format[](https://docs.01.xyz/reference/rest-api#common-response-format) ---------------------------------------------------------------------------------------- Successful responses return a `Receipt` protobuf message containing: * `action_id`: Unique identifier for the action * Action-specific result (e.g., `place_order_result`, `cancel_order_result`) * `err`: Error code if the action failed Endpoints Overview[](https://docs.01.xyz/reference/rest-api#endpoints-overview) -------------------------------------------------------------------------------- | Endpoint | Method | Auth | Description | | --- | --- | --- | --- | | `/info` | GET | No | Markets and tokens information | | `/market/{id}/stats` | GET | No | Market statistics and funding rates | | `/market/{id}/orderbook` | GET | No | Current orderbook snapshot | | `/trades` | GET | No | Recent trade history | | `/user/{pubkey}` | GET | No | User account IDs and sessions | | `/account/{id}` | GET | No | Account balances, positions, orders | | `/timestamp` | GET | No | Server timestamp for action signing | | `/action` | POST | Yes | Execute trading actions (protobuf) | Rate Limits[](https://docs.01.xyz/reference/rest-api#rate-limits) ------------------------------------------------------------------ Contact support for rate limit information specific to your use case. Last updated on January 16, 2026 [Market Data & Info](https://docs.01.xyz/reference/market-data "Market Data & Info") [GET /info](https://docs.01.xyz/reference/rest-api/info "GET /info") --- # GET /info | 01 [Skip to Content](https://docs.01.xyz/reference/rest-api/info#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") [REST API](https://docs.01.xyz/reference/rest-api "REST API") GET /info Copy page GET /info ========= Returns comprehensive information about all available markets and tokens. Request[](https://docs.01.xyz/reference/rest-api/info#request) --------------------------------------------------------------- `curl https://zo-mainnet.n1.xyz/info` Response[](https://docs.01.xyz/reference/rest-api/info#response) ----------------------------------------------------------------- `{ "markets": [ { "marketId": 1, "symbol": "…", "priceDecimals": 1, "sizeDecimals": 1, "baseTokenId": 1, "quoteTokenId": 1, "imf": 1, "mmf": 1, "cmf": 1 } ], "tokens": [ { "tokenId": 1, "symbol": "…", "decimals": 1, "mintAddr": "…", "weightBps": 1 } ] }` Response Fields[](https://docs.01.xyz/reference/rest-api/info#response-fields) ------------------------------------------------------------------------------- ### Market Object[](https://docs.01.xyz/reference/rest-api/info#market-object) | Field | Type | Description | | --- | --- | --- | | `marketId` | number | Unique market identifier | | `symbol` | string | Trading pair symbol (e.g., “BTCUSD”) | | `baseTokenId` | number | Token ID of the base asset | | `quoteTokenId` | number | Token ID of the quote asset | | `priceDecimals` | number | Decimal precision for prices | | `sizeDecimals` | number | Decimal precision for order sizes | | `imf` | number | Initial Margin Fraction (e.g., 0.05 = 5%) | | `mmf` | number | Maintenance Margin Fraction (e.g., 0.025 = 2.5%) | | `cmf` | number | Cancel Margin Fraction (e.g., 0.01 = 1%) | > \[!NOTE\] **Margin fractions explained:** > > * **IMF (Initial)**: Maximum leverage = 1/IMF. E.g., 5% IMF = 20x max leverage. > * **MMF (Maintenance)**: If margin falls below this, positions may be liquidated. > * **CMF (Cancel)**: If margin falls below this, open orders may be cancelled. ### Token Object[](https://docs.01.xyz/reference/rest-api/info#token-object) | Field | Type | Description | | --- | --- | --- | | `tokenId` | number | Unique token identifier | | `symbol` | string | Token symbol (e.g., “USDC”) | | `decimals` | number | Token decimal precision | | `mintAddr` | string | Solana mint address | | `weightBps` | number | Collateral weight in basis points (10000 = 100%) | Example: Python[](https://docs.01.xyz/reference/rest-api/info#example-python) ------------------------------------------------------------------------------ `import requests response = requests.get("https://zo-mainnet.n1.xyz/info") data = response.json() print("Markets:") for market in data["markets"]: max_leverage = 1 / market["imf"] print(f" {market['symbol']} (ID: {market['marketId']}) - Max {max_leverage:.0f}x leverage") print("\nTokens:") for token in data["tokens"]: weight_pct = token["weightBps"] / 100 print(f" {token['symbol']} (ID: {token['tokenId']}) - {weight_pct:.0f}% collateral weight")` Helper Functions[](https://docs.01.xyz/reference/rest-api/info#helper-functions) --------------------------------------------------------------------------------- `import requests from functools import lru_cache @lru_cache(maxsize=1) def get_market_info(): """Fetch and cache market info.""" resp = requests.get("https://zo-mainnet.n1.xyz/info") data = resp.json() # Create lookup dictionaries markets_by_id = {m["marketId"]: m for m in data["markets"]} markets_by_symbol = {m["symbol"]: m for m in data["markets"]} tokens_by_id = {t["tokenId"]: t for t in data["tokens"]} return markets_by_id, markets_by_symbol, tokens_by_id def get_market_by_symbol(symbol: str): """Get market info by symbol.""" _, markets_by_symbol, _ = get_market_info() return markets_by_symbol.get(symbol) def get_price_scale(market_id: int) -> int: """Get price multiplier for a market.""" markets_by_id, _, _ = get_market_info() market = markets_by_id[market_id] return 10 ** market["priceDecimals"] def get_size_scale(market_id: int) -> int: """Get size multiplier for a market.""" markets_by_id, _, _ = get_market_info() market = markets_by_id[market_id] return 10 ** market["sizeDecimals"]` Last updated on February 3, 2026 [Overview](https://docs.01.xyz/reference/rest-api "Overview") [GET /market/\[id\]/stats](https://docs.01.xyz/reference/rest-api/market-stats "GET /market/[id]/stats") --- # GET /market/{market_id}/orderbook | 01 [Skip to Content](https://docs.01.xyz/reference/rest-api/orderbook#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") [REST API](https://docs.01.xyz/reference/rest-api "REST API") GET /market/\[id\]/orderbook Copy page GET /market/{market\_id}/orderbook ================================== Returns the current orderbook snapshot for a market. Request[](https://docs.01.xyz/reference/rest-api/orderbook#request) -------------------------------------------------------------------- **Path Parameters:** | Name | Type | Required | Description | | --- | --- | --- | --- | | `market_id` | number | Yes | Market ID (e.g., `0` for BTC/USD) | `curl https://zo-mainnet.n1.xyz/market/0/orderbook` Response[](https://docs.01.xyz/reference/rest-api/orderbook#response) ---------------------------------------------------------------------- `{ "updateId": 1, "asks": [ [] ], "bids": [ [] ], "asksSummary": { "sum": 1, "count": 1 }, "bidsSummary": { "sum": 1, "count": 1 } }` Response Fields[](https://docs.01.xyz/reference/rest-api/orderbook#response-fields) ------------------------------------------------------------------------------------ | Field | Type | Description | | --- | --- | --- | | `updateId` | number | Sequence number for tracking orderbook state | | `bids` | `[price, size][]` | Array of bid levels (buy orders), sorted by price descending | | `asks` | `[price, size][]` | Array of ask levels (sell orders), sorted by price ascending | | `bidsSummary` | object | Summary of all bids (`sum`: total size, `count`: number of levels) | | `asksSummary` | object | Summary of all asks (`sum`: total size, `count`: number of levels) | Each level is a tuple of `[price, size]` where: * `price`: Limit price * `size`: Total quantity at that price level Example: Python[](https://docs.01.xyz/reference/rest-api/orderbook#example-python) ----------------------------------------------------------------------------------- `import requests market_id = 0 # BTC/USD response = requests.get(f"https://zo-mainnet.n1.xyz/market/{market_id}/orderbook") orderbook = response.json() print(f"Update ID: {orderbook['updateId']}") print("\nTop 5 Bids:") for price, size in orderbook["bids"][:5]: print(f" ${price:,.1f} x {size:.4f}") print("\nTop 5 Asks:") for price, size in orderbook["asks"][:5]: print(f" ${price:,.1f} x {size:.4f}") # Calculate mid price best_bid = orderbook["bids"][0][0] if orderbook["bids"] else 0 best_ask = orderbook["asks"][0][0] if orderbook["asks"] else 0 mid_price = (best_bid + best_ask) / 2 print(f"\nMid Price: ${mid_price:,.2f}") # Summary stats print(f"\nTotal Bid Size: {orderbook['bidsSummary']['sum']:.4f}") print(f"Total Ask Size: {orderbook['asksSummary']['sum']:.4f}")` Error Responses[](https://docs.01.xyz/reference/rest-api/orderbook#error-responses) ------------------------------------------------------------------------------------ | Status | Description | | --- | --- | | 404 | Market not found | `{ "market_id": 999 }` Last updated on February 3, 2026 [GET /market/\[id\]/stats](https://docs.01.xyz/reference/rest-api/market-stats "GET /market/[id]/stats") [GET /trades](https://docs.01.xyz/reference/rest-api/trades "GET /trades") --- # GET /market/{id}/stats | 01 [Skip to Content](https://docs.01.xyz/reference/rest-api/market-stats#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") [REST API](https://docs.01.xyz/reference/rest-api "REST API") GET /market/\[id\]/stats Copy page GET /market/{id}/stats ====================== Returns detailed statistics for a specific market, including funding rates and price information. Request[](https://docs.01.xyz/reference/rest-api/market-stats#request) ----------------------------------------------------------------------- **Path Parameters:** | Name | Type | Required | Description | | --- | --- | --- | --- | | `id` | number | Yes | Market ID (e.g., `0` for BTC/USD) | `curl https://zo-mainnet.n1.xyz/market/0/stats` Response[](https://docs.01.xyz/reference/rest-api/market-stats#response) ------------------------------------------------------------------------- `{ "indexPrice": null, "indexPriceConf": null, "frozen": true, "volumeBase24h": 1, "volumeQuote24h": 1, "high24h": null, "low24h": null, "close24h": null, "prevClose24h": null, "perpStats": null }` Response Fields[](https://docs.01.xyz/reference/rest-api/market-stats#response-fields) --------------------------------------------------------------------------------------- | Field | Type | Description | | --- | --- | --- | | `indexPrice` | number \| null | Current oracle index price | | `indexPriceConf` | number \| null | Index price confidence interval | | `volumeBase24h` | number | 24h volume in base asset | | `volumeQuote24h` | number | 24h volume in quote asset (USD) | | `high24h` | number \| null | 24h high price | | `low24h` | number \| null | 24h low price | | `close24h` | number \| null | Current 24h close price | | `prevClose24h` | number \| null | Previous 24h close price | | `frozen` | boolean | Whether the market is frozen | ### perpStats Object[](https://docs.01.xyz/reference/rest-api/market-stats#perpstats-object) | Field | Type | Description | | --- | --- | --- | | `mark_price` | number | Current mark price | | `funding_rate` | number | Current hourly funding rate | | `next_funding_time` | string | Next funding timestamp (ISO 8601) | | `open_interest` | number | Total open interest in base units | | `aggregated_funding_index` | number | Cumulative funding index | Example: Python[](https://docs.01.xyz/reference/rest-api/market-stats#example-python) -------------------------------------------------------------------------------------- `import requests market_id = 0 # BTC/USD response = requests.get(f"https://zo-mainnet.n1.xyz/market/{market_id}/stats") stats = response.json() print(f"Index Price: ${stats['indexPrice']:,.2f}") print(f"Funding Rate: {stats['perpStats']['funding_rate']:.4%}") print(f"Open Interest: {stats['perpStats']['open_interest']:,.2f} BTC")` Fetching Multiple Markets[](https://docs.01.xyz/reference/rest-api/market-stats#fetching-multiple-markets) ----------------------------------------------------------------------------------------------------------- `import requests from concurrent.futures import ThreadPoolExecutor market_ids = [0, 1, 2] # BTC, ETH, SOL def fetch_stats(market_id): resp = requests.get(f"https://zo-mainnet.n1.xyz/market/{market_id}/stats") return (market_id, resp.json()) with ThreadPoolExecutor(max_workers=3) as executor: all_stats = list(executor.map(fetch_stats, market_ids)) for market_id, stats in all_stats: print(f"Market {market_id}: {stats['perpStats']['funding_rate']:.4%}")` Last updated on January 16, 2026 [GET /info](https://docs.01.xyz/reference/rest-api/info "GET /info") [GET /market/\[id\]/orderbook](https://docs.01.xyz/reference/rest-api/orderbook "GET /market/[id]/orderbook") --- # GET /trades | 01 [Skip to Content](https://docs.01.xyz/reference/rest-api/trades#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") [REST API](https://docs.01.xyz/reference/rest-api "REST API") GET /trades Copy page GET /trades =========== Returns recent trade history with pagination. Ordered from present to past. Request[](https://docs.01.xyz/reference/rest-api/trades#request) ----------------------------------------------------------------- **Query Parameters:** | Name | Type | Required | Description | | --- | --- | --- | --- | | `marketId` | number | No | Filter by market ID | | `makerId` | number | No | Filter by maker account ID | | `takerId` | number | No | Filter by taker account ID | | `takerSide` | string | No | Filter by taker side: `ask` or `bid` | | `since` | string | No | Start timestamp (RFC3339); defaults to UNIX epoch | | `until` | string | No | End timestamp (RFC3339); defaults to current time | | `startInclusive` | number | No | Pagination cursor for fetching next page | | `pageSize` | number | No | Maximum trades to return (default: 50, max: 50) | `# Recent trades for a market curl "https://zo-mainnet.n1.xyz/trades?marketId=0&pageSize=10" # Trades for a specific maker with time range curl "https://zo-mainnet.n1.xyz/trades?makerId=12345&since=2024-01-01T00:00:00Z&until=2024-01-02T00:00:00Z" # Filter by taker side curl "https://zo-mainnet.n1.xyz/trades?marketId=0&takerSide=bid&pageSize=50"` Response[](https://docs.01.xyz/reference/rest-api/trades#response) ------------------------------------------------------------------- `{ "items": [ { "time": "…", "actionId": 1, "tradeId": 1, "takerId": 1, "takerSide": "ask", "makerId": 1, "marketId": 1, "orderId": 1, "price": 1, "baseSize": 1 } ], "nextStartInclusive": null }` Response Fields[](https://docs.01.xyz/reference/rest-api/trades#response-fields) --------------------------------------------------------------------------------- ### PageResult Object[](https://docs.01.xyz/reference/rest-api/trades#pageresult-object) | Field | Type | Description | | --- | --- | --- | | `items` | Trade\[\] | Array of trade objects | | `nextStartInclusive` | number \| null | Pagination cursor for next page. If `null`, no more data. | ### Trade Object[](https://docs.01.xyz/reference/rest-api/trades#trade-object) | Field | Type | Description | | --- | --- | --- | | `time` | string | Trade timestamp (RFC3339/ISO 8601) | | `actionId` | number | Action ID that caused this trade | | `tradeId` | number | Unique trade identifier | | `takerId` | number | Taker account ID | | `takerSide` | string | Taker side: `bid` (buy) or `ask` (sell) | | `makerId` | number | Maker account ID | | `marketId` | number | Market where trade occurred | | `orderId` | number | Order ID of the maker order | | `price` | number | Trade execution price | | `baseSize` | number | Trade size in base asset | Pagination[](https://docs.01.xyz/reference/rest-api/trades#pagination) ----------------------------------------------------------------------- To fetch all trades, use the `nextStartInclusive` cursor: `import requests def fetch_all_trades(market_id: int, since: str, until: str): all_trades = [] cursor = None while True: params = { "marketId": market_id, "since": since, "until": until, "pageSize": 50 } if cursor is not None: params["startInclusive"] = cursor response = requests.get("https://zo-mainnet.n1.xyz/trades", params=params) data = response.json() all_trades.extend(data["items"]) cursor = data.get("nextStartInclusive") if cursor is None: break return all_trades trades = fetch_all_trades(0, "2024-01-01T00:00:00Z", "2024-01-02T00:00:00Z") print(f"Total trades: {len(trades)}")` Example: Python[](https://docs.01.xyz/reference/rest-api/trades#example-python) -------------------------------------------------------------------------------- `import requests from datetime import datetime response = requests.get( "https://zo-mainnet.n1.xyz/trades", params={"marketId": 0, "pageSize": 20} ) data = response.json() print("Recent Trades:") for trade in data["items"]: time = datetime.fromisoformat(trade["time"].replace("Z", "+00:00")) side = "BUY" if trade["takerSide"] == "bid" else "SELL" print(f" {time:%H:%M:%S} | {side:4} | ${trade['price']:,.1f} x {trade['baseSize']:.4f}")` Fetching Trade History for Your Account[](https://docs.01.xyz/reference/rest-api/trades#fetching-trade-history-for-your-account) --------------------------------------------------------------------------------------------------------------------------------- `import requests # Replace with your account ID my_account_id = 12345 # Trades where you were the maker maker_trades = requests.get( "https://zo-mainnet.n1.xyz/trades", params={"makerId": my_account_id, "pageSize": 50} ).json() # Trades where you were the taker taker_trades = requests.get( "https://zo-mainnet.n1.xyz/trades", params={"takerId": my_account_id, "pageSize": 50} ).json() print(f"Maker trades: {len(maker_trades['items'])}") print(f"Taker trades: {len(taker_trades['items'])}")` Last updated on February 3, 2026 [GET /market/\[id\]/orderbook](https://docs.01.xyz/reference/rest-api/orderbook "GET /market/[id]/orderbook") [GET /user/\[pubkey\]](https://docs.01.xyz/reference/rest-api/user "GET /user/[pubkey]") --- # GET /user/{pubkey} | 01 [Skip to Content](https://docs.01.xyz/reference/rest-api/user#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") [REST API](https://docs.01.xyz/reference/rest-api "REST API") GET /user/\[pubkey\] Copy page GET /user/{pubkey} ================== Returns the account IDs and active sessions associated with a Solana public key. Request[](https://docs.01.xyz/reference/rest-api/user#request) --------------------------------------------------------------- **Path Parameters:** | Name | Type | Required | Description | | --- | --- | --- | --- | | `pubkey` | string | Yes | Base58-encoded Solana public key | `curl https://zo-mainnet.n1.xyz/user/YourBase58PubkeyHere` Response[](https://docs.01.xyz/reference/rest-api/user#response) ----------------------------------------------------------------- `{ "accountIds": [ 1 ], "sessions": { "pubkey": "…", "expiry": "…" } }` Response Fields[](https://docs.01.xyz/reference/rest-api/user#response-fields) ------------------------------------------------------------------------------- | Field | Type | Description | | --- | --- | --- | | `accountIds` | number\[\] | List of Nord account IDs owned by this user | | `sessions` | object | Map of active session public keys to session info | ### Session Object[](https://docs.01.xyz/reference/rest-api/user#session-object) | Field | Type | Description | | --- | --- | --- | | `pubkey` | string | Session public key (Base58) | | `expiry` | string | Session expiration time (RFC3339/ISO 8601) | Example: Python[](https://docs.01.xyz/reference/rest-api/user#example-python) ------------------------------------------------------------------------------ `import requests from base58 import b58encode API_URL = "https://zo-mainnet.n1.xyz" def get_user_account_ids(user_pubkey: bytes) -> list[int]: """Get account IDs for a user public key.""" pubkey_b58 = b58encode(user_pubkey).decode() resp = requests.get(f"{API_URL}/user/{pubkey_b58}") if resp.status_code == 404: return [] # User not found data = resp.json() return data["accountIds"] # Get account IDs account_ids = get_user_account_ids(user_pubkey) print(f"Found {len(account_ids)} accounts: {account_ids}") # Use the first account ID to fetch account details if account_ids: account_id = account_ids[0] # See GET /account/{account_id} for fetching balances, positions, orders` Error Responses[](https://docs.01.xyz/reference/rest-api/user#error-responses) ------------------------------------------------------------------------------- | Status | Description | | --- | --- | | 404 | User not found (no accounts for this pubkey) | Related Endpoints[](https://docs.01.xyz/reference/rest-api/user#related-endpoints) ----------------------------------------------------------------------------------- > \[!TIP\] To get account balances, positions, and orders, use the account ID from this endpoint with: > > * [`GET /account/{account_id}`](https://docs.01.xyz/reference/rest-api/account) > - Account summary > * [`GET /account/{account_id}/orders`](https://docs.01.xyz/reference/rest-api/account#orders) > - Paginated orders Last updated on January 16, 2026 [GET /trades](https://docs.01.xyz/reference/rest-api/trades "GET /trades") [GET /account/\[id\]](https://docs.01.xyz/reference/rest-api/account "GET /account/[id]") --- # GET /timestamp | 01 [Skip to Content](https://docs.01.xyz/reference/rest-api/timestamp#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") [REST API](https://docs.01.xyz/reference/rest-api "REST API") GET /timestamp Copy page GET /timestamp ============== Returns the current server timestamp. Used for signing actions that require a `current_timestamp` field. Request[](https://docs.01.xyz/reference/rest-api/timestamp#request) -------------------------------------------------------------------- `curl https://zo-mainnet.n1.xyz/timestamp` Response[](https://docs.01.xyz/reference/rest-api/timestamp#response) ---------------------------------------------------------------------- Returns a plain integer timestamp (Unix seconds): `1705312800` Usage[](https://docs.01.xyz/reference/rest-api/timestamp#usage) ---------------------------------------------------------------- The server timestamp should be used when constructing actions to ensure they are accepted. Using a local timestamp may cause actions to be rejected if clocks are out of sync. Example: Python[](https://docs.01.xyz/reference/rest-api/timestamp#example-python) ----------------------------------------------------------------------------------- `import requests def get_server_timestamp(): response = requests.get("https://zo-mainnet.n1.xyz/timestamp") return int(response.json()) server_time = get_server_timestamp() print(f"Server time: {server_time}")` Example: cURL + jq[](https://docs.01.xyz/reference/rest-api/timestamp#example-curl--jq) ---------------------------------------------------------------------------------------- `# Get timestamp as integer curl -s https://zo-mainnet.n1.xyz/timestamp | jq '.'` Notes[](https://docs.01.xyz/reference/rest-api/timestamp#notes) ---------------------------------------------------------------- * Always fetch a fresh timestamp before constructing trading actions * The timestamp is in Unix seconds (not milliseconds) * Actions with timestamps too far in the past or future will be rejected Last updated on January 16, 2026 [POST /action](https://docs.01.xyz/reference/rest-api/action "POST /action") [WebSocket Endpoints](https://docs.01.xyz/reference/rest-api/websockets "WebSocket Endpoints") --- # GET /account/{account_id} | 01 [Skip to Content](https://docs.01.xyz/reference/rest-api/account#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") [REST API](https://docs.01.xyz/reference/rest-api "REST API") GET /account/\[id\] Copy page GET /account/{account\_id} ========================== Returns comprehensive account information including balances, positions, open orders, and margin status. Request[](https://docs.01.xyz/reference/rest-api/account#request) ------------------------------------------------------------------ **Path Parameters:** | Name | Type | Required | Description | | --- | --- | --- | --- | | `account_id` | number | Yes | Nord account ID | `curl https://zo-mainnet.n1.xyz/account/12345` Response[](https://docs.01.xyz/reference/rest-api/account#response) -------------------------------------------------------------------- `{ "updateId": 1, "orders": [ { "orderId": 1, "marketId": 1, "side": "ask", "size": 1, "price": 1, "originalOrderSize": 1, "clientOrderId": null } ], "positions": [ { "marketId": 1, "openOrders": 1, "perp": null, "actionId": 1 } ], "balances": [ { "tokenId": 1, "token": "…", "amount": 1 } ], "margins": { "omf": 1, "mf": 1, "imf": 1, "cmf": 1, "mmf": 1, "pon": 1, "pn": 1, "bankruptcy": true } }` Response Fields[](https://docs.01.xyz/reference/rest-api/account#response-fields) ---------------------------------------------------------------------------------- ### Account Object[](https://docs.01.xyz/reference/rest-api/account#account-object) | Field | Type | Description | | --- | --- | --- | | `updateId` | number | Sequence number for state tracking | | `balances` | Balance\[\] | Token balances | | `positions` | Position\[\] | Market positions | | `orders` | Order\[\] | Open orders | | `margins` | Margins | Account margin/health status | ### Balance Object[](https://docs.01.xyz/reference/rest-api/account#balance-object) | Field | Type | Description | | --- | --- | --- | | `tokenId` | number | Token identifier | | `token` | string | Token symbol (e.g., “USDC”) | | `amount` | number | Total balance | ### Position Object[](https://docs.01.xyz/reference/rest-api/account#position-object) | Field | Type | Description | | --- | --- | --- | | `marketId` | number | Market identifier | | `openOrders` | number | Number of open orders in this market | | `perp` | PerpPosition \| null | Perpetual position details | | `actionId` | number | Last action that modified this position | ### PerpPosition Object[](https://docs.01.xyz/reference/rest-api/account#perpposition-object) | Field | Type | Description | | --- | --- | --- | | `baseSize` | number | Position size in base asset | | `price` | number | Entry/average price | | `isLong` | boolean | True if long, false if short | | `sizePricePnl` | number | PnL from size/price changes (USDC) | | `fundingPaymentPnl` | number | PnL from funding payments (USDC) | | `updatedFundingRateIndex` | number | Funding rate index at last update | ### Order Object[](https://docs.01.xyz/reference/rest-api/account#order-object) | Field | Type | Description | | --- | --- | --- | | `orderId` | number | Unique order identifier | | `marketId` | number | Market identifier | | `side` | string | `bid` (buy) or `ask` (sell) | | `price` | number | Order price | | `size` | number | Remaining order size | | `originalOrderSize` | number | Original order size | | `clientOrderId` | number \| null | Optional client-provided order ID | ### Margins Object[](https://docs.01.xyz/reference/rest-api/account#margins-object) | Field | Type | Description | | --- | --- | --- | | `omf` | number | Open Margin Fraction numerator (USD) | | `mf` | number | Margin Fraction numerator (USD) | | `imf` | number | Initial Margin requirement numerator | | `cmf` | number | Cancel Margin requirement numerator | | `mmf` | number | Maintenance Margin requirement numerator | | `pon` | number | Position + Orders Notional (USD) | | `pn` | number | Position Notional (USD) | | `bankruptcy` | boolean | True if account is bankrupt | > \[!NOTE\] Margin fractions are expressed as numerators. Divide by `pon` or `pn` to get the actual ratio. For example, if `omf = 15000` and `pon = 50000`, the open margin fraction is 0.3 (30%). Example: Python[](https://docs.01.xyz/reference/rest-api/account#example-python) --------------------------------------------------------------------------------- `import requests API_URL = "https://zo-mainnet.n1.xyz" def get_account(account_id: int): resp = requests.get(f"{API_URL}/account/{account_id}") return resp.json() account = get_account(12345) # Print balances print("Balances:") for balance in account["balances"]: print(f" {balance['token']}: {balance['amount']:.2f}") # Print positions print("\nPositions:") for pos in account["positions"]: if pos.get("perp"): perp = pos["perp"] direction = "LONG" if perp["isLong"] else "SHORT" pnl = perp["sizePricePnl"] + perp["fundingPaymentPnl"] print(f" Market {pos['marketId']}: {direction} {perp['baseSize']:.4f} @ ${perp['price']:,.2f} (PnL: ${pnl:,.2f})") # Print open orders print("\nOpen Orders:") for order in account["orders"]: side = "BUY" if order["side"] == "bid" else "SELL" print(f" {side} {order['size']:.4f} @ ${order['price']:,.2f}") # Check account health margins = account["margins"] if margins["pon"] > 0: margin_ratio = margins["omf"] / margins["pon"] print(f"\nMargin Ratio: {margin_ratio:.2%}") if margins["bankruptcy"]: print("⚠️ ACCOUNT IS BANKRUPT")` Error Responses[](https://docs.01.xyz/reference/rest-api/account#error-responses) ---------------------------------------------------------------------------------- | Status | Description | | --- | --- | | 404 | Account not found | Last updated on February 3, 2026 [GET /user/\[pubkey\]](https://docs.01.xyz/reference/rest-api/user "GET /user/[pubkey]") [POST /action](https://docs.01.xyz/reference/rest-api/action "POST /action") --- # POST /action | 01 [Skip to Content](https://docs.01.xyz/reference/rest-api/action#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") [REST API](https://docs.01.xyz/reference/rest-api "REST API") POST /action Copy page POST /action ============ Execute trading actions using protobuf-encoded messages. This endpoint handles all authenticated operations including session creation, order placement, and cancellation. Request[](https://docs.01.xyz/reference/rest-api/action#request) ----------------------------------------------------------------- **Headers:** | Name | Value | | --- | --- | | `Content-Type` | `application/octet-stream` | **Body:** The request body is a binary payload containing: 1. **Varint-encoded length** of the Action message 2. **Serialized Action** protobuf message 3. **Ed25519 signature** (64 bytes) `┌─────────────────┬────────────────────────┬─────────────────┐ │ Length (varint) │ Action (protobuf) │ Signature (64B) │ └─────────────────┴────────────────────────┴─────────────────┘` Protobuf Schema[](https://docs.01.xyz/reference/rest-api/action#protobuf-schema) --------------------------------------------------------------------------------- Download the schema from `https://zo-devnet.n1.xyz/schema.proto` Generate bindings: `# Python curl https://zo-devnet.n1.xyz/schema.proto -o schema.proto protoc --python_out=. schema.proto` Action Types[](https://docs.01.xyz/reference/rest-api/action#action-types) --------------------------------------------------------------------------- ### CreateSession[](https://docs.01.xyz/reference/rest-api/action#createsession) Creates an authenticated session for trading. **Must be signed with user wallet key.** `message CreateSession { bytes user_pubkey = 1; // 32-byte user public key bytes session_pubkey = 2; // 32-byte session public key int64 expiry_timestamp = 3; // Session expiration (Unix seconds) }` ### PlaceOrder[](https://docs.01.xyz/reference/rest-api/action#placeorder) Places a new order. **Must be signed with session key.** `message PlaceOrder { uint64 session_id = 1; uint32 market_id = 2; Side side = 3; // ASK = 0, BID = 1 FillMode fill_mode = 4; // LIMIT = 0, POST_ONLY = 1, IMMEDIATE_OR_CANCEL = 2, FILL_OR_KILL = 3 uint64 price = 5; // Price * 10^priceDecimals uint64 size = 6; // Size * 10^sizeDecimals }` ### CancelOrder[](https://docs.01.xyz/reference/rest-api/action#cancelorder) Cancels an existing order. **Must be signed with session key.** `message CancelOrder { uint64 session_id = 1; uint64 order_id = 2; }` Signing[](https://docs.01.xyz/reference/rest-api/action#signing) ----------------------------------------------------------------- ### User Signing (for CreateSession)[](https://docs.01.xyz/reference/rest-api/action#user-signing-for-createsession) Sign the **hex-encoded** message bytes: `import binascii def user_sign(key, msg: bytes) -> bytes: """Sign using user wallet key (hex-encoded).""" payload = binascii.hexlify(msg) return key.sign(payload)` ### Session Signing (for PlaceOrder, CancelOrder)[](https://docs.01.xyz/reference/rest-api/action#session-signing-for-placeorder-cancelorder) Sign the **raw** message bytes: `def session_sign(key, msg: bytes) -> bytes: """Sign using session key (raw bytes).""" return key.sign(msg)` Example: Python[](https://docs.01.xyz/reference/rest-api/action#example-python) -------------------------------------------------------------------------------- Complete example for creating a session and placing an order: `import requests import binascii from google.protobuf.internal import encoder, decoder from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey import schema_pb2 # Generated from schema.proto API_URL = "https://zo-devnet.n1.xyz" def get_varint_bytes(value): return encoder._VarintBytes(value) def read_varint(buffer, offset=0): return decoder._DecodeVarint32(buffer, offset) def execute_action(action, signing_key, sign_func): """Serialize, sign, and send an action.""" payload = action.SerializeToString() length_prefix = get_varint_bytes(len(payload)) message = length_prefix + payload signature = sign_func(signing_key, message) resp = requests.post( f"{API_URL}/action", data=message + signature, headers={"Content-Type": "application/octet-stream"} ) resp.raise_for_status() # Parse receipt msg_len, pos = read_varint(resp.content, 0) receipt = schema_pb2.Receipt() receipt.ParseFromString(resp.content[pos:pos + msg_len]) return receipt # Create session def create_session(user_key, session_key, server_time): action = schema_pb2.Action() action.current_timestamp = server_time action.nonce = 0 action.create_session.user_pubkey = user_key.public_key().public_bytes_raw() action.create_session.session_pubkey = session_key.public_key().public_bytes_raw() action.create_session.expiry_timestamp = server_time + 3600 def user_sign(key, msg): return key.sign(binascii.hexlify(msg)) receipt = execute_action(action, user_key, user_sign) return receipt.create_session_result.session_id # Place order def place_order(session_key, session_id, market_id, side, price, size): action = schema_pb2.Action() action.current_timestamp = int(requests.get(f"{API_URL}/timestamp").json()) action.place_order.session_id = session_id action.place_order.market_id = market_id action.place_order.side = side action.place_order.fill_mode = schema_pb2.FillMode.LIMIT action.place_order.price = price action.place_order.size = size receipt = execute_action(action, session_key, lambda k, m: k.sign(m)) return receipt` Response[](https://docs.01.xyz/reference/rest-api/action#response) ------------------------------------------------------------------- Returns a protobuf `Receipt` message: `message Receipt { uint64 action_id = 1; oneof kind { Error err = 32; CreateSessionResult create_session_result = 33; PlaceOrderResult place_order_result = 34; CancelOrderResult cancel_order_result = 35; // ... other results } }` Error Handling[](https://docs.01.xyz/reference/rest-api/action#error-handling) ------------------------------------------------------------------------------- Check the `err` field for error codes: `if receipt.HasField("err"): error_name = schema_pb2.Error.Name(receipt.err) print(f"Action failed: {error_name}")` Common errors: * `INSUFFICIENT_FUNDS` - Not enough balance * `INVALID_SIGNATURE` - Signature verification failed * `SESSION_NOT_FOUND` - Session has expired or is invalid * `ORDER_NOT_FOUND` - Order doesn’t exist (for cancel) Last updated on January 16, 2026 [GET /account/\[id\]](https://docs.01.xyz/reference/rest-api/account "GET /account/[id]") [GET /timestamp](https://docs.01.xyz/reference/rest-api/timestamp "GET /timestamp") --- # WebSocket Endpoints | 01 [Skip to Content](https://docs.01.xyz/reference/rest-api/websockets#nextra-skip-nav) [API Reference](https://docs.01.xyz/reference "API Reference") [REST API](https://docs.01.xyz/reference/rest-api "REST API") WebSocket Endpoints Copy page WebSocket Endpoints =================== The Nord API provides WebSocket connections for real-time data streaming. Base URLs[](https://docs.01.xyz/reference/rest-api/websockets#base-urls) ------------------------------------------------------------------------- | Environment | URL | | --- | --- | | Mainnet | `wss://zo-mainnet.n1.xyz` | | Devnet | `wss://zo-devnet.n1.xyz` | Available Streams[](https://docs.01.xyz/reference/rest-api/websockets#available-streams) ----------------------------------------------------------------------------------------- | Stream | Endpoint | Description | | --- | --- | --- | | Candles | `candle@{symbol}:{resolution}` | OHLCV candlestick data | | Trades | `trades@{symbol}` | Real-time trade executions | | Orderbook | `deltas@{symbol}` | Orderbook updates (bids/asks) | | Account | `account@{account_id}` | Account updates (fills, orders, balances) | You can subscribe to multiple streams in a single connection: `wss://{host}/ws/trades@BTCUSD&deltas@BTCUSD&account@42` * * * Candle Data Stream[](https://docs.01.xyz/reference/rest-api/websockets#candle-data-stream) ------------------------------------------------------------------------------------------- Stream real-time candlestick (OHLCV) data for charting. ### Endpoint[](https://docs.01.xyz/reference/rest-api/websockets#endpoint) `wss://{host}/ws/candle@{symbol}:{resolution}` | Parameter | Type | Description | | --- | --- | --- | | `symbol` | string | Trading pair (e.g., “BTCUSD”) | | `resolution` | string | Timeframe: “1”, “5”, “15”, “30”, “60”, “240”, “1D”, “1W”, “1M” | ### Message Format[](https://docs.01.xyz/reference/rest-api/websockets#message-format) `{ "res": "1", "mid": 0, "t": 1705312800, "o": 97500.0, "h": 97550.0, "l": 97480.0, "c": 97520.0, "v": 125.5 }` | Field | Type | Description | | --- | --- | --- | | `res` | string | Resolution/timeframe | | `mid` | number | Market ID | | `t` | number | Timestamp (Unix seconds) | | `o`, `h`, `l`, `c` | number | Open, High, Low, Close prices | | `v` | number | Volume (optional) | * * * Trades Stream[](https://docs.01.xyz/reference/rest-api/websockets#trades-stream) --------------------------------------------------------------------------------- Stream real-time trade executions for a market. ### Endpoint[](https://docs.01.xyz/reference/rest-api/websockets#endpoint-1) `wss://{host}/ws/trades@{symbol}` | Parameter | Type | Description | | --- | --- | --- | | `symbol` | string | Trading pair (e.g., “BTCUSD”) | ### Message Format[](https://docs.01.xyz/reference/rest-api/websockets#message-format-1) `{ "trades": { "market_symbol": "BTCUSD", "trade_id": 12345, "price": 97500.0, "base_size": 0.5, "taker_side": "bid", "time": "2024-01-15T10:30:00Z" } }` | Field | Type | Description | | --- | --- | --- | | `market_symbol` | string | Trading pair symbol | | `trade_id` | number | Unique trade identifier | | `price` | number | Execution price | | `base_size` | number | Trade size in base currency | | `taker_side` | string | `"bid"` (buy) or `"ask"` (sell) | | `time` | string | ISO 8601 timestamp | ### Example: JavaScript[](https://docs.01.xyz/reference/rest-api/websockets#example-javascript) ``const ws = new WebSocket("wss://zo-mainnet.n1.xyz/ws/trades@BTCUSD"); ws.onmessage = (event) => { const data = JSON.parse(event.data); const trade = data.trades; console.log(`${trade.taker_side.toUpperCase()} ${trade.base_size} @ $${trade.price}`); };`` * * * Orderbook Deltas Stream[](https://docs.01.xyz/reference/rest-api/websockets#orderbook-deltas-stream) ----------------------------------------------------------------------------------------------------- Stream real-time orderbook updates (bid/ask changes). ### Endpoint[](https://docs.01.xyz/reference/rest-api/websockets#endpoint-2) `wss://{host}/ws/deltas@{symbol}` | Parameter | Type | Description | | --- | --- | --- | | `symbol` | string | Trading pair (e.g., “BTCUSD”) | ### Message Format[](https://docs.01.xyz/reference/rest-api/websockets#message-format-2) `{ "delta": { "market_symbol": "BTCUSD", "update_id": 98765, "bids": [[97500.0, 1.5], [97490.0, 2.0]], "asks": [[97510.0, 0.8], [97520.0, 1.2]] } }` | Field | Type | Description | | --- | --- | --- | | `market_symbol` | string | Trading pair symbol | | `update_id` | number | Sequence number for ordering | | `bids` | array | Bid updates as `[price, size]` pairs | | `asks` | array | Ask updates as `[price, size]` pairs | > \[!NOTE\] A size of `0` indicates the price level should be removed from the orderbook. ### Example: JavaScript[](https://docs.01.xyz/reference/rest-api/websockets#example-javascript-1) `const ws = new WebSocket("wss://zo-mainnet.n1.xyz/ws/deltas@BTCUSD"); ws.onmessage = (event) => { const data = JSON.parse(event.data); const delta = data.delta; // Apply delta updates to your local orderbook delta.bids.forEach(([price, size]) => { if (size === 0) { // Remove price level } else { // Update price level with new size } }); };` * * * Account Stream[](https://docs.01.xyz/reference/rest-api/websockets#account-stream) ----------------------------------------------------------------------------------- Stream real-time account updates including order fills, placements, cancellations, and balance changes. ### Endpoint[](https://docs.01.xyz/reference/rest-api/websockets#endpoint-3) `wss://{host}/ws/account@{account_id}` | Parameter | Type | Description | | --- | --- | --- | | `account_id` | number | Your Nord account ID | ### Message Format[](https://docs.01.xyz/reference/rest-api/websockets#message-format-3) `{ "account": { "account_id": 42, "update_id": 123456, "fills": { "order_123": { "order_id": 123, "market_id": 0, "maker_id": 42, "quantity": 0.5, "price": 97500.0 } }, "places": { "order_124": { "market_id": 0, "side": "bid", "price": 97000.0, "current_size": 1.0 } }, "cancels": {}, "balances": { "0": { "token_id": 0, "amount": 1000.0 } } } }` | Field | Type | Description | | --- | --- | --- | | `account_id` | number | Account identifier | | `update_id` | number | Sequence number for ordering | | `fills` | object | Filled orders (keyed by order ID) | | `places` | object | Newly placed orders | | `cancels` | object | Cancelled orders | | `balances` | object | Updated token balances | ### Example: JavaScript[](https://docs.01.xyz/reference/rest-api/websockets#example-javascript-2) ``const accountId = 42; // Your account ID const ws = new WebSocket(`wss://zo-mainnet.n1.xyz/ws/account@${accountId}`); ws.onmessage = (event) => { const data = JSON.parse(event.data); const account = data.account; // Handle fills Object.values(account.fills || {}).forEach(fill => { console.log(`Order ${fill.order_id} filled: ${fill.quantity} @ $${fill.price}`); }); // Handle new orders Object.entries(account.places || {}).forEach(([orderId, order]) => { console.log(`Order ${orderId} placed: ${order.side} ${order.current_size} @ $${order.price}`); }); // Handle cancellations Object.keys(account.cancels || {}).forEach(orderId => { console.log(`Order ${orderId} cancelled`); }); };`` * * * Connection Best Practices[](https://docs.01.xyz/reference/rest-api/websockets#connection-best-practices) --------------------------------------------------------------------------------------------------------- 1. **Reconnection**: Implement automatic reconnection with exponential backoff 2. **Heartbeat**: Respond to server pings to keep the connection alive 3. **Sequence tracking**: Use `update_id` to detect missed messages 4. **Resource cleanup**: Close connections when no longer needed ### Reconnecting Client Example[](https://docs.01.xyz/reference/rest-api/websockets#reconnecting-client-example) `import asyncio import websockets import json async def resilient_stream(symbol: str): uri = f"wss://zo-mainnet.n1.xyz/ws/trades@{symbol}" retry_delay = 1 while True: try: async with websockets.connect(uri) as ws: retry_delay = 1 async for message in ws: yield json.loads(message) except websockets.ConnectionClosed: await asyncio.sleep(retry_delay) retry_delay = min(retry_delay * 2, 30) asyncio.run(resilient_stream("BTCUSD"))` Last updated on January 16, 2026 [GET /timestamp](https://docs.01.xyz/reference/rest-api/timestamp "GET /timestamp") [Initializing Nord](https://docs.01.xyz/examples/initializing "Initializing Nord") --- # Initializing Nord | 01 [Skip to Content](https://docs.01.xyz/examples/initializing#nextra-skip-nav) Usage ExamplesInitializing Nord Copy page Initializing Nord ================= To initialize the SDK, you’ll need the 01 Exchange App Key: `zoau54n5U24GHNKqyoziVaVxgsiQYnPMx33fKmLLCT5` `import { Nord } from "@n1xyz/nord-ts"; const connection = new Connection('https://api.devnet.solana.com'); const appKey = 'zoau54n5U24GHNKqyoziVaVxgsiQYnPMx33fKmLLCT5' // 01 Exchange App Key // Create a Nord instance // Initialize and fetch market data const nord = await Nord.new({ app: appKey, // 01 app key solanaConnection: connection, webServerUrl: 'https://zo-devnet.n1.xyz', });` Last updated on February 3, 2026 [WebSocket Endpoints](https://docs.01.xyz/reference/rest-api/websockets "WebSocket Endpoints") [Creating a User](https://docs.01.xyz/examples/creating-user "Creating a User") --- # Creating a User from Private Key | 01 [Skip to Content](https://docs.01.xyz/examples/creating-user#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") Creating a User Copy page Creating a User from Private Key ================================ `import { Nord, NordUser } from "@n1xyz/nord-ts"; import { Connection } from "@solana/web3.js"; const connection = new Connection('https://api.devnet.solana.com'); // Create a Nord instance // Initialize and fetch market data const nord = await Nord.new({ app: 'zoau54n5U24GHNKqyoziVaVxgsiQYnPMx33fKmLLCT5', // 01 Exchange App Key solanaConnection: connection, webServerUrl: 'https://zo-devnet.n1.xyz', }); // Create user from private key const user = NordUser.fromPrivateKey( nord, 'your_private_key', // Can be string or Uint8Array ); // Fetch user account information await user.updateAccountId(); await user.fetchInfo();` Last updated on February 3, 2026 [Initializing Nord](https://docs.01.xyz/examples/initializing "Initializing Nord") [Trading Operations](https://docs.01.xyz/examples/trading "Trading Operations") --- # Trading Operations | 01 [Skip to Content](https://docs.01.xyz/examples/trading#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") Trading Operations Copy page Trading Operations ================== Learn how to perform trading operations using the `NordUser` class. > \[!TIP\] Check out the [API Reference](https://docs.01.xyz/reference/nord-user) > for a full breakdown of every method, including argument tables and expected responses. > \[!NOTE\] **Other languages:** See [Python Trading](https://docs.01.xyz/examples/python/trading) > for Python examples, or [REST API](https://docs.01.xyz/reference/rest-api/action) > for raw HTTP API usage. Prerequisites[](https://docs.01.xyz/examples/trading#prerequisites) -------------------------------------------------------------------- Ensure you have an initialized `NordUser` instance. See [Creating a User](https://docs.01.xyz/examples/creating-user) for details. `import { Nord, NordUser, Side, FillMode, TriggerKind } from "@n1xyz/nord-ts"; import { PublicKey } from "@solana/web3.js"; // user is an initialized instance of NordUser` Placing Orders[](https://docs.01.xyz/examples/trading#placing-orders) ---------------------------------------------------------------------- Place various types of orders using the `placeOrder` method. **Method:** `nordUser.placeOrder(orderConfig)` ### Parameters[](https://docs.01.xyz/examples/trading#parameters) | Name | Type | Required | Description | | --- | --- | --- | --- | | `marketId` | number | Yes | The ID of the market (e.g., `0` for BTC/USDC). | | `side` | `Side` | Yes | Order side: `Side.Bid` (Buy) or `Side.Ask` (Sell). | | `fillMode` | `FillMode` | Yes | `FillMode.Limit`, `FillMode.PostOnly`, `FillMode.ImmediateOrCancel`, or `FillMode.FillOrKill`. | | `size` | number | Yes | The size of the order in base asset units. | | `price` | number | No\* | The limit price. Required if `fillMode` is `Limit`. | | `isReduceOnly` | boolean | No | If true, the order will only reduce an existing position. Default `false`. | ### Return Value[](https://docs.01.xyz/examples/trading#return-value) Returns a `Promise` that resolves to an object containing the `orderId`. `{ orderId: bigint }` ### Examples[](https://docs.01.xyz/examples/trading#examples) #### Limit Order[](https://docs.01.xyz/examples/trading#limit-order) `const limitOrder = await user.placeOrder({ marketId: 0, // e.g., BTC/USDC market side: Side.Bid, // Buy fillMode: FillMode.Limit, isReduceOnly: false, size: 0.1, // Quantity price: 50000, // Limit Price }); console.log("Placed limit order:", limitOrder.orderId);` #### Market Order[](https://docs.01.xyz/examples/trading#market-order) `const marketOrder = await user.placeOrder({ marketId: 0, side: Side.Ask, fillMode: FillMode.FillOrKill, // FOK for market orders isReduceOnly: false, size: 0.5, }); console.log("Placed market order:", marketOrder.actionId);` #### Reduce-Only Order[](https://docs.01.xyz/examples/trading#reduce-only-order) `const reduceOnlyOrder = await user.placeOrder({ marketId: 0, side: Side.Ask, fillMode: FillMode.Limit, isReduceOnly: true, size: 0.1, price: 55000, });` Canceling Orders[](https://docs.01.xyz/examples/trading#canceling-orders) -------------------------------------------------------------------------- Cancel an existing order using its `orderId`. **Method:** `nordUser.cancelOrder(orderId)` ### Parameters[](https://docs.01.xyz/examples/trading#parameters-1) | Name | Type | Required | Description | | --- | --- | --- | --- | | `orderId` | bigint \| string | Yes | The unique identifier of the order to cancel. | ### Return Value[](https://docs.01.xyz/examples/trading#return-value-1) Returns a `Promise` containing the canceled order details. `{ orderId: bigint, // ... other order details }` ### Example[](https://docs.01.xyz/examples/trading#example) `const cancelResult = await user.cancelOrder(existingOrderId); console.log("Cancelled order:", cancelResult.orderId);` Atomic Operations[](https://docs.01.xyz/examples/trading#atomic-operations) ---------------------------------------------------------------------------- Execute multiple actions (place, cancel) in a single atomic transaction. > \[!IMPORTANT\] **Constraints:** > > * Maximum **4 operations** per atomic transaction > * **Ordering per market:** Cancels → Trades → Places (cancels must come first, placements last) > * Across different markets, order can be any **Method:** `nordUser.atomic(actions)` ### Parameters[](https://docs.01.xyz/examples/trading#parameters-2) | Name | Type | Required | Description | | --- | --- | --- | --- | | `actions` | `UserAtomicSubaction[]` | Yes | An array of actions (`place` or `cancel`). Max 4. | **UserAtomicSubaction Structure:** For `place`: same fields as `placeOrder` plus `kind: "place"`. For `cancel`: `kind: "cancel"`, `marketId`, and `orderId`. ### Return Value[](https://docs.01.xyz/examples/trading#return-value-2) Returns a `Promise` resolving to the atomic action result. `{ actionId: bigint, // ... result details }` ### Example[](https://docs.01.xyz/examples/trading#example-1) `const atomicResult = await user.atomic([ { kind: "cancel", marketId: 0, orderId: existingOrderId, }, { kind: "place", marketId: 0, side: Side.Bid, fillMode: FillMode.Limit, isReduceOnly: false, size: 0.2, price: 49500, }, ]); console.log("Atomic action ID:", atomicResult.actionId);` Trigger Orders[](https://docs.01.xyz/examples/trading#trigger-orders) ---------------------------------------------------------------------- Manage stop-loss and take-profit triggers. > \[!CAUTION\] **Experimental Feature:** Trigger orders (TP/SL) are currently unstable and may change. Use with caution in production. > \[!INFO\] **Auto-Close on Position Changes:** Triggers automatically close when your position is closed or flipped. This prevents triggers from executing unexpectedly after position state changes. ### Add Trigger[](https://docs.01.xyz/examples/trading#add-trigger) **Method:** `nordUser.addTrigger(triggerConfig)` ### Parameters[](https://docs.01.xyz/examples/trading#parameters-3) | Name | Type | Required | Description | | --- | --- | --- | --- | | `marketId` | number | Yes | The ID of the market. | | `side` | `Side` | Yes | `Side.Bid` or `Side.Ask`. | | `kind` | `TriggerKind` | Yes | `TriggerKind.StopLoss` or `TriggerKind.TakeProfit`. | | `triggerPrice` | number | Yes | The price that activates the trigger. | | `limitPrice` | number | No | The price for the triggered limit order. | ### Example[](https://docs.01.xyz/examples/trading#example-2) `const trigger = await user.addTrigger({ marketId: 0, side: Side.Ask, kind: TriggerKind.StopLoss, triggerPrice: 45000, limitPrice: 44900, }); console.log("Added trigger:", trigger.actionId);` ### Remove Trigger[](https://docs.01.xyz/examples/trading#remove-trigger) **Method:** `nordUser.removeTrigger(triggerConfig)` ### Parameters[](https://docs.01.xyz/examples/trading#parameters-4) | Name | Type | Required | Description | | --- | --- | --- | --- | | `marketId` | number | Yes | The ID of the market. | | `side` | `Side` | Yes | `Side.Bid` or `Side.Ask`. | | `kind` | `TriggerKind` | Yes | `TriggerKind.StopLoss` or `TriggerKind.TakeProfit`. | ### Example[](https://docs.01.xyz/examples/trading#example-3) `await user.removeTrigger({ marketId: 0, side: Side.Ask, kind: TriggerKind.StopLoss, });` Fund Management[](https://docs.01.xyz/examples/trading#fund-management) ------------------------------------------------------------------------ Manage your account balances on the exchange. ### Deposit Tokens[](https://docs.01.xyz/examples/trading#deposit-tokens) **Method:** `nordUser.deposit(depositConfig)` ### Parameters[](https://docs.01.xyz/examples/trading#parameters-5) | Name | Type | Required | Description | | --- | --- | --- | --- | | `amount` | number | Yes | Amount to deposit. | | `tokenId` | number | Yes | The ID of the token (e.g., `1` for USDC). | | `recipient` | PublicKey | No | Optional recipient public key. | ### Return Value[](https://docs.01.xyz/examples/trading#return-value-3) `{ signature: string }` ### Example[](https://docs.01.xyz/examples/trading#example-4) `const depositResult = await user.deposit({ amount: 1000, tokenId: 1, }); console.log("Deposit signature:", depositResult.signature);` ### Withdraw Tokens[](https://docs.01.xyz/examples/trading#withdraw-tokens) **Method:** `nordUser.withdraw(withdrawConfig)` ### Parameters[](https://docs.01.xyz/examples/trading#parameters-6) | Name | Type | Required | Description | | --- | --- | --- | --- | | `amount` | number | Yes | Amount to withdraw. | | `tokenId` | number | Yes | The ID of the token. | ### Return Value[](https://docs.01.xyz/examples/trading#return-value-4) `{ actionId: bigint }` ### Example[](https://docs.01.xyz/examples/trading#example-5) `const withdrawResult = await user.withdraw({ amount: 500, tokenId: 1, }); console.log("Withdrawal action ID:", withdrawResult.actionId);` ### Transfer to Account[](https://docs.01.xyz/examples/trading#transfer-to-account) Transfer tokens between different accounts. **Method:** `nordUser.transferToAccount(transferConfig)` ### Parameters[](https://docs.01.xyz/examples/trading#parameters-7) | Name | Type | Required | Description | | --- | --- | --- | --- | | `tokenId` | number | Yes | The ID of the token. | | `amount` | number | Yes | Amount to transfer. | | `fromAccountId` | number | Yes | Source account ID. | | `toAccountId` | number | Yes | Destination account ID. | ### Example[](https://docs.01.xyz/examples/trading#example-6) `const transferResult = await user.transferToAccount({ tokenId: 1, amount: 100, fromAccountId: 0, toAccountId: 1, }); console.log("Transfer action ID:", transferResult.actionId);` Information & Balances[](https://docs.01.xyz/examples/trading#information--balances) ------------------------------------------------------------------------------------- ### Fetch User Info[](https://docs.01.xyz/examples/trading#fetch-user-info) Refresh the local state of the user, including balances and orders. `await user.fetchInfo(); console.log("Balances:", user.balances); console.log("Orders:", user.orders);` ### Get Solana Balances[](https://docs.01.xyz/examples/trading#get-solana-balances) Check token balances in your Solana wallet context. `const solBalances = await user.getSolanaBalances({ includeZeroBalances: false, }); console.log("Solana Balances:", solBalances);` Trade History[](https://docs.01.xyz/examples/trading#trade-history) -------------------------------------------------------------------- To retrieve trade history, you can manually fetch it from the Nord API. This is done by making a GET request to the `/trades` endpoint. ### Endpoint[](https://docs.01.xyz/examples/trading#endpoint) The URL is constructed as follows: `GET {NORD_API_URL}/trades?makerId={makerId}&pageSize={pageSize}` * **makerId**: (Required) The ID of the maker (user) whose trade history you want to fetch. * **pageSize**: (Optional) The number of trades to retrieve per page. ### Usage Example[](https://docs.01.xyz/examples/trading#usage-example) Here is an example of how to fetch trade history using the native `fetch` API: ``// Define the Nord API URL (e.g., for Mainnet) const NORD_URL = "https://zo-mainnet.n1.xyz"; async function fetchTradeHistory(makerId: string, pageSize: number = 50) { try { const response = await fetch( `${NORD_URL}/trades?makerId=${makerId}&pageSize=${pageSize}` ); if (!response.ok) { throw new Error(`Error fetching trades: ${response.statusText}`); } const trades = await response.json(); console.log("Trade History:", trades); return trades; } catch (error) { console.error("Failed to fetch trade history:", error); } } // Example usage // Replace 'YOUR_MAKER_ID' with the actual maker ID fetchTradeHistory("YOUR_MAKER_ID");`` Last updated on February 3, 2026 [Creating a User](https://docs.01.xyz/examples/creating-user "Creating a User") [Deposits & Withdrawals](https://docs.01.xyz/examples/deposits-withdrawals "Deposits & Withdrawals") --- # Deposits and Withdrawals | 01 [Skip to Content](https://docs.01.xyz/examples/deposits-withdrawals#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") Deposits & Withdrawals Copy page Deposits and Withdrawals ======================== ``import { Nord, NordUser } from "@n1xyz/nord-ts"; // Assuming nord and user are already initialized // Withdraw tokens try { const tokenId = 0; // USDC const amount = 100; // 100 USDC await user.withdraw({ tokenId, amount }); console.log(`Successfully withdrew ${amount} of token ID ${tokenId}`); } catch (error) { console.error(`Withdrawal error: ${error}`); } // For Solana SPL tokens try { const tokenId = 1; // SOL const amount = 1; // 1 SOL const txId = await user.depositSpl(amount, tokenId); console.log(`Deposit transaction ID: ${txId}`); } catch (error) { console.error(`Deposit error: ${error}`); }`` Last updated on January 16, 2026 [Trading Operations](https://docs.01.xyz/examples/trading "Trading Operations") [Market Data](https://docs.01.xyz/examples/market-data "Market Data") --- # Account Information | 01 [Skip to Content](https://docs.01.xyz/examples/account-info#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") Account Information Copy page Account Information =================== > \[!NOTE\] **Other languages:** See [Python Integration](https://docs.01.xyz/examples/python) > for Python examples. `import { Nord, NordUser } from "@n1xyz/nord-ts"; // Assuming nord and user are already initialized // Refresh user info await user.fetchInfo(); // Access user balances console.log('Balances:', user.balances); // Access user positions console.log('Positions:', user.positions); // Access user orders console.log('Orders:', user.orders);` Last updated on January 16, 2026 [Market Data](https://docs.01.xyz/examples/market-data "Market Data") [Websockets](https://docs.01.xyz/examples/websockets "Websockets") --- # Market Data | 01 [Skip to Content](https://docs.01.xyz/examples/market-data#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") Market Data Copy page Market Data =========== This section covers how to fetch market information, statistics, and real-time data from the Nord API. > \[!NOTE\] **Other languages:** See [Python Market Data](https://docs.01.xyz/examples/python/market-data) > for Python examples, or [REST API Reference](https://docs.01.xyz/reference/rest-api) > for raw HTTP endpoints. Nord Info Endpoint[](https://docs.01.xyz/examples/market-data#nord-info-endpoint) ---------------------------------------------------------------------------------- The `/info` endpoint returns all available markets and tokens without requiring a Nord instance. **Endpoint:** `GET /info` ### Parameters[](https://docs.01.xyz/examples/market-data#parameters) | Name | Type | Required | Description | | --- | --- | --- | --- | | None | \- | \- | This endpoint takes no parameters. | ### Response Structure[](https://docs.01.xyz/examples/market-data#response-structure) The response is a JSON object containing arrays of `markets` and `tokens`. `{ "markets": [ { "marketId": number, "symbol": string, "baseTokenId": number, "quoteTokenId": number, "priceDecimals": number, "sizeDecimals": number, // ... other market properties } ], "tokens": [ { "tokenId": number, "symbol": string, "decimals": number, "mint": string, // ... other token properties } ] }` ### Example[](https://docs.01.xyz/examples/market-data#example) ``const NORD_URL = "https://zo-mainnet.n1.xyz"; // or "https://zo-devnet.n1.xyz" for devnet // Fetch all markets and tokens const response = await fetch(`${NORD_URL}/info`); const data = await response.json(); console.log('Markets:', data.markets); console.log('Tokens:', data.tokens);`` Market Statistics[](https://docs.01.xyz/examples/market-data#market-statistics) -------------------------------------------------------------------------------- The `/market/{marketId}/stats` endpoint provides detailed statistics for a specific market, including funding rate, mark price, and 24h metrics. **Endpoint:** `GET /market/{marketId}/stats` ### Parameters[](https://docs.01.xyz/examples/market-data#parameters-1) | Name | Type | Required | Description | | --- | --- | --- | --- | | `marketId` | number | Yes | The unique identifier of the market (e.g., `0` for BTC/USDC). | ### Response Structure[](https://docs.01.xyz/examples/market-data#response-structure-1) `{ "marketId": number, "indexPrice": number, // Current index price "indexPriceConf": number, // Index price confidence interval "volumeBase24h": number, // 24h volume in base asset "volumeQuote24h": number, // 24h volume in quote asset (USDC) "high24h": number, // 24h high "low24h": number, // 24h low "close24h": number, // 24h close "prevClose24h": number, // Previous 24h close "perpStats": { "mark_price": number, // Current mark price "funding_rate": number, // Current funding rate "next_funding_time": string, // Next funding timestamp "open_interest": number, // Total open interest "aggregated_funding_index": number // Aggregated funding index } }` ### Example[](https://docs.01.xyz/examples/market-data#example-1) ``const NORD_URL = "https://zo-mainnet.n1.xyz"; const marketId = 0; // BTC/USDC const response = await fetch(`${NORD_URL}/market/${marketId}/stats`); const stats = await response.json(); console.log('Index Price:', stats.indexPrice); console.log('Funding Rate:', stats.perpStats.funding_rate); console.log('Mark Price:', stats.perpStats.mark_price);`` Fetching Multiple Market Stats[](https://docs.01.xyz/examples/market-data#fetching-multiple-market-stats) ---------------------------------------------------------------------------------------------------------- To fetch statistics for multiple markets efficiently: ``const NORD_URL = "https://zo-mainnet.n1.xyz"; const marketIds = [0, 1, 2]; // BTC, ETH, SOL const statsPromises = marketIds.map(async (marketId) => { const response = await fetch(`${NORD_URL}/market/${marketId}/stats`); return response.json(); }); const allStats = await Promise.all(statsPromises); allStats.forEach((stats, i) => { console.log(`Market ${marketIds[i]} Funding Rate:`, stats.perpStats?.funding_rate); });`` Using Nord Client[](https://docs.01.xyz/examples/market-data#using-nord-client) -------------------------------------------------------------------------------- If you have a Nord instance, you can use the built-in methods: `import { Nord } from "@n1xyz/nord-ts"; // Assuming nord is already initialized // Get orderbook for a market const orderbook = await nord.getOrderbook({ marketId: 0 }); console.log('Bids:', orderbook.bids); console.log('Asks:', orderbook.asks); // Get recent trades const trades = await nord.getTrades({ marketId: 0, pageSize: 10 }); console.log('Recent trades:', trades.trades); // Subscribe to real-time orderbook updates const orderbookSub = nord.subscribeOrderbook('BTC/USDC'); orderbookSub.on('update', (data) => { console.log('Orderbook update:', data); });` Last updated on January 16, 2026 [Deposits & Withdrawals](https://docs.01.xyz/examples/deposits-withdrawals "Deposits & Withdrawals") [Account Information](https://docs.01.xyz/examples/account-info "Account Information") --- # Python Integration | 01 [Skip to Content](https://docs.01.xyz/examples/python#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") Python IntegrationGetting Started Copy page Python Integration ================== This guide covers how to integrate with 01 Exchange using Python and the protobuf-based API. > \[!NOTE\] Unlike the TypeScript SDK, Python integration uses the raw REST API with protobuf encoding. This approach gives you full control but requires more low-level setup. Prerequisites[](https://docs.01.xyz/examples/python#prerequisites) ------------------------------------------------------------------- * Python 3.8+ * `protobuf` for message encoding * `cryptography` for Ed25519 signing * `requests` for HTTP calls * `base58` for key encoding Installation[](https://docs.01.xyz/examples/python#installation) ----------------------------------------------------------------- `pip install protobuf cryptography requests base58` Or with `uv`: `uv add protobuf cryptography requests base58` Generate Protocol Buffers[](https://docs.01.xyz/examples/python#generate-protocol-buffers) ------------------------------------------------------------------------------------------- Download and compile the protobuf schema: `# Download schema curl https://zo-devnet.n1.xyz/schema.proto -o schema.proto # Generate Python bindings protoc --python_out=. schema.proto` This creates `schema_pb2.py` which provides all message types (Action, Receipt, etc.). Project Structure[](https://docs.01.xyz/examples/python#project-structure) --------------------------------------------------------------------------- `your-project/ ├── schema.proto # Downloaded schema ├── schema_pb2.py # Generated Python bindings ├── id.json # Your Solana keypair (32-byte array) └── main.py # Your trading script` Basic Setup[](https://docs.01.xyz/examples/python#basic-setup) --------------------------------------------------------------- `import json import requests from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from base58 import b58encode import schema_pb2 API_URL = "https://zo-devnet.n1.xyz" # or "https://zo-mainnet.n1.xyz" # Load your Solana keypair with open("id.json", "r") as f: key_data = json.load(f) # Create signing key from first 32 bytes user_signkey = Ed25519PrivateKey.from_private_bytes(bytes(key_data[:32])) user_pubkey = user_signkey.public_key().public_bytes_raw() print(f"User pubkey: {b58encode(user_pubkey).decode()}")` Key Concepts[](https://docs.01.xyz/examples/python#key-concepts) ----------------------------------------------------------------- ### Keypairs[](https://docs.01.xyz/examples/python#keypairs) You need two types of keys: | Key Type | Purpose | Signing Method | | --- | --- | --- | | **User Key** | Your Solana wallet key | Signs `CreateSession` (hex-encoded) | | **Session Key** | Temporary trading key | Signs all other actions (raw bytes) | ### Actions and Receipts[](https://docs.01.xyz/examples/python#actions-and-receipts) All trading operations follow this pattern: 1. Create an `Action` protobuf message 2. Serialize and sign it 3. POST to `/action` endpoint 4. Parse the `Receipt` response ### Server Timestamp[](https://docs.01.xyz/examples/python#server-timestamp) Always fetch the server timestamp for action construction: `def get_server_timestamp(): resp = requests.get(f"{API_URL}/timestamp") return int(resp.json())` Next Steps[](https://docs.01.xyz/examples/python#next-steps) ------------------------------------------------------------- * [Session & Authentication](https://docs.01.xyz/examples/python/session) - Create a trading session * [Trading Operations](https://docs.01.xyz/examples/python/trading) - Place and cancel orders * [Market Data](https://docs.01.xyz/examples/python/market-data) - Fetch market information Last updated on January 16, 2026 [Websockets](https://docs.01.xyz/examples/websockets "Websockets") [Session & Authentication](https://docs.01.xyz/examples/python/session "Session & Authentication") --- # WebSockets | 01 [Skip to Content](https://docs.01.xyz/examples/websockets#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") Websockets Copy page WebSockets ========== The Nord application provides real-time data streaming via WebSocket connections. > \[!NOTE\] **Full API Reference:** See [REST API WebSockets](https://docs.01.xyz/reference/rest-api/websockets) > for detailed message schemas and Python examples. Stream Types[](https://docs.01.xyz/examples/websockets#stream-types) --------------------------------------------------------------------- | Stream | Use Case | | --- | --- | | `candle@{symbol}:{resolution}` | Chart candlestick data | | `trades@{symbol}` | Live trade feed | | `deltas@{symbol}` | Orderbook updates | | `account@{account_id}` | Account activity (fills, orders) | Candle Data Streaming[](https://docs.01.xyz/examples/websockets#candle-data-streaming) --------------------------------------------------------------------------------------- ``const nordUrl = "wss://zo-mainnet.n1.xyz"; const symbol = "SOLUSD"; const resolution = "1"; // 1 minute candles const socket = new WebSocket(`${nordUrl}/ws/candle@${symbol}:${resolution}`); interface CandleUpdate { res: string; mid: number; t: number; o: number; h: number; l: number; c: number; v?: number; } socket.onmessage = (event) => { const candle: CandleUpdate = JSON.parse(event.data); console.log(`OHLC: ${candle.o} / ${candle.h} / ${candle.l} / ${candle.c}`); };`` Trade Stream[](https://docs.01.xyz/examples/websockets#trade-stream) --------------------------------------------------------------------- ``const socket = new WebSocket("wss://zo-mainnet.n1.xyz/ws/trades@BTCUSD"); interface TradeMessage { trades: { market_symbol: string; trade_id: number; price: number; base_size: number; taker_side: "bid" | "ask"; time: string; }; } socket.onmessage = (event) => { const { trades }: TradeMessage = JSON.parse(event.data); const side = trades.taker_side === "bid" ? "BUY" : "SELL"; console.log(`${side} ${trades.base_size} @ $${trades.price.toFixed(2)}`); };`` Orderbook Deltas[](https://docs.01.xyz/examples/websockets#orderbook-deltas) ----------------------------------------------------------------------------- `const socket = new WebSocket("wss://zo-mainnet.n1.xyz/ws/deltas@BTCUSD"); interface DeltaMessage { delta: { market_symbol: string; update_id: number; bids: [number, number][]; // [price, size] asks: [number, number][]; }; } // Local orderbook state const orderbook = { bids: new Map(), asks: new Map() }; socket.onmessage = (event) => { const { delta }: DeltaMessage = JSON.parse(event.data); delta.bids.forEach(([price, size]) => { size === 0 ? orderbook.bids.delete(price) : orderbook.bids.set(price, size); }); delta.asks.forEach(([price, size]) => { size === 0 ? orderbook.asks.delete(price) : orderbook.asks.set(price, size); }); };` Account Updates[](https://docs.01.xyz/examples/websockets#account-updates) --------------------------------------------------------------------------- ``const accountId = 42; // Your Nord account ID const socket = new WebSocket(`wss://zo-mainnet.n1.xyz/ws/account@${accountId}`); interface AccountMessage { account: { account_id: number; update_id: number; fills: Record; places: Record; cancels: Record; balances: Record; }; } socket.onmessage = (event) => { const { account }: AccountMessage = JSON.parse(event.data); Object.values(account.fills).forEach(fill => { console.log(`Order ${fill.order_id} filled: ${fill.quantity} @ $${fill.price}`); }); Object.entries(account.places).forEach(([id, order]) => { console.log(`Order ${id}: ${order.side} ${order.current_size} @ $${order.price}`); }); Object.keys(account.cancels).forEach(id => { console.log(`Order ${id} cancelled`); }); };`` Multi-Stream Connection[](https://docs.01.xyz/examples/websockets#multi-stream-connection) ------------------------------------------------------------------------------------------- > \[!WARNING\] **Maximum 12 Connections:** A single client can subscribe to a maximum of 12 streams in one multi-stream connection. If you need to monitor more than 12 streams, use multiple WebSocket connections. Subscribe to multiple streams in one connection: ``const streams = "trades@BTCUSD&deltas@BTCUSD&account@42"; const socket = new WebSocket(`wss://zo-mainnet.n1.xyz/ws/${streams}`); socket.onmessage = (event) => { const data = JSON.parse(event.data); if ("trades" in data) { // Handle trade } else if ("delta" in data) { // Handle orderbook update } else if ("account" in data) { // Handle account update } };`` Last updated on January 16, 2026 [Account Information](https://docs.01.xyz/examples/account-info "Account Information") [Getting Started](https://docs.01.xyz/examples/python "Getting Started") --- # Session & Authentication | 01 [Skip to Content](https://docs.01.xyz/examples/python/session#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") [Python Integration](https://docs.01.xyz/examples/python "Python Integration") Session & Authentication Copy page Session & Authentication ======================== This guide shows how to create an authenticated session for trading operations. Overview[](https://docs.01.xyz/examples/python/session#overview) ----------------------------------------------------------------- Trading requires a session-based authentication flow: 1. Generate a temporary session keypair 2. Sign a `CreateSession` action with your user wallet key 3. Use the returned `session_id` for subsequent trading actions 4. Sign trading actions with the session key Signing Functions[](https://docs.01.xyz/examples/python/session#signing-functions) ----------------------------------------------------------------------------------- Two different signing schemes are used: `import binascii def user_sign(key, msg: bytes) -> bytes: """ User signing: sign hex-encoded message. Used for CreateSession. """ payload = binascii.hexlify(msg) return key.sign(payload) def session_sign(key, msg: bytes) -> bytes: """ Session signing: sign raw bytes. Used for PlaceOrder, CancelOrder, etc. """ return key.sign(msg)` Execute Action Helper[](https://docs.01.xyz/examples/python/session#execute-action-helper) ------------------------------------------------------------------------------------------- `import requests from google.protobuf.internal import encoder, decoder import schema_pb2 API_URL = "https://zo-devnet.n1.xyz" def get_varint_bytes(value): """Encode an integer as a protobuf varint.""" return encoder._VarintBytes(value) def read_varint(buffer, offset=0): """Decode a protobuf varint from a buffer.""" return decoder._DecodeVarint32(buffer, offset) def execute_action(action, signing_key, sign_func): """ Serialize, sign, and send an Action to the API. Returns the parsed Receipt. """ # Serialize the action payload = action.SerializeToString() length_prefix = get_varint_bytes(len(payload)) message = length_prefix + payload # Sign the message signature = sign_func(signing_key, message) # Send to API resp = requests.post( f"{API_URL}/action", data=message + signature, headers={"Content-Type": "application/octet-stream"} ) if resp.status_code != 200: raise Exception(f"API error: {resp.status_code} {resp.text}") # Parse the receipt msg_len, pos = read_varint(resp.content, 0) receipt = schema_pb2.Receipt() receipt.ParseFromString(resp.content[pos:pos + msg_len]) return receipt` Creating a Session[](https://docs.01.xyz/examples/python/session#creating-a-session) ------------------------------------------------------------------------------------- `import json import requests from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from base58 import b58encode import schema_pb2 API_URL = "https://zo-devnet.n1.xyz" def create_session(): # Load user wallet key with open("id.json", "r") as f: key_data = json.load(f) user_signkey = Ed25519PrivateKey.from_private_bytes(bytes(key_data[:32])) user_pubkey = user_signkey.public_key().public_bytes_raw() print(f"User pubkey: {b58encode(user_pubkey).decode()}") # Generate session keypair session_signkey = Ed25519PrivateKey.generate() session_pubkey = session_signkey.public_key().public_bytes_raw() print(f"Session pubkey: {b58encode(session_pubkey).decode()}") # Get server timestamp server_time = int(requests.get(f"{API_URL}/timestamp").json()) print(f"Server time: {server_time}") # Build CreateSession action action = schema_pb2.Action() action.current_timestamp = server_time action.nonce = 0 action.create_session.user_pubkey = user_pubkey action.create_session.session_pubkey = session_pubkey action.create_session.expiry_timestamp = server_time + 3600 # 1 hour # Execute with user signing receipt = execute_action(action, user_signkey, user_sign) if receipt.HasField("err"): error_name = schema_pb2.Error.Name(receipt.err) raise Exception(f"CreateSession failed: {error_name}") session_id = receipt.create_session_result.session_id print(f"Session created! ID: {session_id}") return session_id, session_signkey if __name__ == "__main__": session_id, session_key = create_session()` Complete Example[](https://docs.01.xyz/examples/python/session#complete-example) --------------------------------------------------------------------------------- Full example with session creation ready for trading: `import json import requests import binascii from google.protobuf.internal import encoder, decoder from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from base58 import b58encode import schema_pb2 API_URL = "https://zo-devnet.n1.xyz" def get_varint_bytes(value): return encoder._VarintBytes(value) def read_varint(buffer, offset=0): return decoder._DecodeVarint32(buffer, offset) def user_sign(key, msg): return key.sign(binascii.hexlify(msg)) def session_sign(key, msg): return key.sign(msg) def execute_action(action, signing_key, sign_func): payload = action.SerializeToString() length_prefix = get_varint_bytes(len(payload)) message = length_prefix + payload signature = sign_func(signing_key, message) resp = requests.post( f"{API_URL}/action", data=message + signature, headers={"Content-Type": "application/octet-stream"} ) resp.raise_for_status() msg_len, pos = read_varint(resp.content, 0) receipt = schema_pb2.Receipt() receipt.ParseFromString(resp.content[pos:pos + msg_len]) return receipt def main(): # Load keys and create session with open("id.json", "r") as f: key_data = json.load(f) user_signkey = Ed25519PrivateKey.from_private_bytes(bytes(key_data[:32])) session_signkey = Ed25519PrivateKey.generate() server_time = int(requests.get(f"{API_URL}/timestamp").json()) # Create session action = schema_pb2.Action() action.current_timestamp = server_time action.nonce = 0 action.create_session.user_pubkey = user_signkey.public_key().public_bytes_raw() action.create_session.session_pubkey = session_signkey.public_key().public_bytes_raw() action.create_session.expiry_timestamp = server_time + 3600 receipt = execute_action(action, user_signkey, user_sign) if receipt.HasField("err"): raise Exception(f"Error: {schema_pb2.Error.Name(receipt.err)}") session_id = receipt.create_session_result.session_id print(f"Session ID: {session_id}") # Ready to trade! See Trading Operations guide. if __name__ == "__main__": main()` Session Expiry[](https://docs.01.xyz/examples/python/session#session-expiry) ----------------------------------------------------------------------------- Sessions expire after the `expiry_timestamp` you specify. Best practices: * Set expiry to 1 hour for short-lived scripts * Implement session refresh for long-running bots * Store session credentials securely (never in version control) Next Steps[](https://docs.01.xyz/examples/python/session#next-steps) --------------------------------------------------------------------- * [Trading Operations](https://docs.01.xyz/examples/python/trading) - Place and cancel orders using your session Last updated on January 16, 2026 [Getting Started](https://docs.01.xyz/examples/python "Getting Started") [Trading Operations](https://docs.01.xyz/examples/python/trading "Trading Operations") --- # Funds & Withdrawals (Python) | 01 [Skip to Content](https://docs.01.xyz/examples/python/funds#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") [Python Integration](https://docs.01.xyz/examples/python "Python Integration") Funds & Withdrawals Copy page Funds & Withdrawals (Python) ============================ Manage funds including withdrawals and account transfers. > \[!NOTE\] **Deposits** require Solana on-chain transactions via the Proton framework and cannot be done through the pure REST API. See the TypeScript SDK for deposit functionality. Withdrawing Funds[](https://docs.01.xyz/examples/python/funds#withdrawing-funds) --------------------------------------------------------------------------------- Withdraw tokens from the exchange to your Solana wallet. `import requests import schema_pb2 API_URL = "https://zo-devnet.n1.xyz" def withdraw(session_id, session_key, token_id, amount): """ Withdraw tokens from the exchange. Args: token_id: Token to withdraw (e.g., 1 for USDC) amount: Amount to withdraw (human-readable, e.g., 100 for 100 USDC) """ server_time = int(requests.get(f"{API_URL}/timestamp").json()) # Get token decimals info = requests.get(f"{API_URL}/info").json() token = next(t for t in info["tokens"] if t["tokenId"] == token_id) decimals = token["decimals"] # Convert to raw amount amount_raw = int(amount * (10 ** decimals)) action = schema_pb2.Action() action.current_timestamp = server_time action.withdraw.session_id = session_id action.withdraw.token_id = token_id action.withdraw.amount = amount_raw receipt = execute_action(action, session_key, session_sign) if receipt.HasField("err"): raise Exception(f"Withdraw failed: {schema_pb2.Error.Name(receipt.err)}") print(f"Withdrawal initiated! Action ID: {receipt.action_id}") return receipt # Example: Withdraw 100 USDC withdraw( session_id=session_id, session_key=session_key, token_id=1, # USDC amount=100 )` Account Transfers[](https://docs.01.xyz/examples/python/funds#account-transfers) --------------------------------------------------------------------------------- Transfer tokens between sub-accounts. `def transfer_between_accounts(session_id, session_key, token_id, amount, from_account, to_account): """ Transfer tokens between sub-accounts. Args: from_account: Source account ID to_account: Destination account ID """ server_time = int(requests.get(f"{API_URL}/timestamp").json()) # Get token decimals info = requests.get(f"{API_URL}/info").json() token = next(t for t in info["tokens"] if t["tokenId"] == token_id) decimals = token["decimals"] amount_raw = int(amount * (10 ** decimals)) action = schema_pb2.Action() action.current_timestamp = server_time action.transfer.session_id = session_id action.transfer.token_id = token_id action.transfer.amount = amount_raw action.transfer.from_account_id = from_account action.transfer.to_account_id = to_account receipt = execute_action(action, session_key, session_sign) if receipt.HasField("err"): raise Exception(f"Transfer failed: {schema_pb2.Error.Name(receipt.err)}") print(f"Transfer complete! Action ID: {receipt.action_id}") return receipt # Example: Transfer 50 USDC from account 0 to account 1 transfer_between_accounts( session_id=session_id, session_key=session_key, token_id=1, amount=50, from_account=0, to_account=1 )` Token Information[](https://docs.01.xyz/examples/python/funds#token-information) --------------------------------------------------------------------------------- Get available tokens and their metadata: `def get_tokens(): """Fetch available tokens with their IDs and decimals.""" resp = requests.get(f"{API_URL}/info") tokens = resp.json()["tokens"] for token in tokens: print(f"{token['tokenId']}: {token['symbol']} ({token['decimals']} decimals)") return tokens # Common token IDs: # 0 = (varies by deployment) # 1 = USDC` Last updated on January 16, 2026 [Market Data](https://docs.01.xyz/examples/python/market-data "Market Data") [Account Info](https://docs.01.xyz/examples/python/account "Account Info") --- # Trading Operations (Python) | 01 [Skip to Content](https://docs.01.xyz/examples/python/trading#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") [Python Integration](https://docs.01.xyz/examples/python "Python Integration") Trading Operations Copy page Trading Operations (Python) =========================== This guide shows how to place and cancel orders using Python. Prerequisites[](https://docs.01.xyz/examples/python/trading#prerequisites) --------------------------------------------------------------------------- Make sure you have: * Generated `schema_pb2.py` from the protobuf schema * Created an authenticated session (see [Session & Authentication](https://docs.01.xyz/examples/python/session) ) Fetching Market Info[](https://docs.01.xyz/examples/python/trading#fetching-market-info) ----------------------------------------------------------------------------------------- Before trading, get market decimals for price/size conversion: `import requests API_URL = "https://zo-devnet.n1.xyz" def get_market_info(): resp = requests.get(f"{API_URL}/info") info = resp.json() markets = {} for market in info["markets"]: markets[market["marketId"]] = { "symbol": market["symbol"], "price_decimals": market["priceDecimals"], "size_decimals": market["sizeDecimals"] } return markets markets = get_market_info() print(f"BTC market: {markets[0]}") # Output: {'symbol': 'BTCUSD', 'price_decimals': 1, 'size_decimals': 4}` Placing a Limit Order[](https://docs.01.xyz/examples/python/trading#placing-a-limit-order) ------------------------------------------------------------------------------------------- `import requests import schema_pb2 API_URL = "https://zo-devnet.n1.xyz" def place_limit_order(session_id, session_key, market_id, side, price, size): """ Place a limit order. Args: session_id: Active session ID session_key: Session signing key market_id: Market to trade (0 = BTC) side: schema_pb2.Side.BID or schema_pb2.Side.ASK price: Price in USD (will be converted to raw) size: Size in base units (will be converted to raw) """ # Get market decimals markets = get_market_info() market = markets[market_id] # Convert to raw values price_raw = int(price * (10 ** market["price_decimals"])) size_raw = int(size * (10 ** market["size_decimals"])) # Build action server_time = int(requests.get(f"{API_URL}/timestamp").json()) action = schema_pb2.Action() action.current_timestamp = server_time action.place_order.session_id = session_id action.place_order.market_id = market_id action.place_order.side = side action.place_order.fill_mode = schema_pb2.FillMode.LIMIT action.place_order.price = price_raw action.place_order.size = size_raw # Execute with session signing receipt = execute_action(action, session_key, session_sign) if receipt.HasField("err"): error_name = schema_pb2.Error.Name(receipt.err) raise Exception(f"PlaceOrder failed: {error_name}") result = receipt.place_order_result if result.HasField("posted"): print(f"Order posted! ID: {result.posted.order_id}") return result.posted.order_id if result.fills: print(f"Order filled! {len(result.fills)} fills") return None return None # Example usage order_id = place_limit_order( session_id=session_id, session_key=session_key, market_id=0, # BTC side=schema_pb2.Side.BID, # Buy price=90000.0, size=0.001 )` Placing a Market Order[](https://docs.01.xyz/examples/python/trading#placing-a-market-order) --------------------------------------------------------------------------------------------- `def place_market_order(session_id, session_key, market_id, side, size): """Place a market order (no price specified).""" markets = get_market_info() market = markets[market_id] size_raw = int(size * (10 ** market["size_decimals"])) server_time = int(requests.get(f"{API_URL}/timestamp").json()) action = schema_pb2.Action() action.current_timestamp = server_time action.place_order.session_id = session_id action.place_order.market_id = market_id action.place_order.side = side action.place_order.fill_mode = schema_pb2.FillMode.FILL_OR_KILL # FOK for market orders action.place_order.size = size_raw # Note: no price for market orders receipt = execute_action(action, session_key, session_sign) if receipt.HasField("err"): raise Exception(f"Error: {schema_pb2.Error.Name(receipt.err)}") print(f"Market order executed! Fills: {len(receipt.place_order_result.fills)}") return receipt.place_order_result` Canceling an Order[](https://docs.01.xyz/examples/python/trading#canceling-an-order) ------------------------------------------------------------------------------------- `def cancel_order(session_id, session_key, order_id): """Cancel an existing order.""" server_time = int(requests.get(f"{API_URL}/timestamp").json()) action = schema_pb2.Action() action.current_timestamp = server_time action.cancel_order_by_id.session_id = session_id action.cancel_order_by_id.order_id = order_id receipt = execute_action(action, session_key, session_sign) if receipt.HasField("err"): raise Exception(f"Error: {schema_pb2.Error.Name(receipt.err)}") print(f"Order {order_id} cancelled!") return receipt # Example cancel_order(session_id, session_key, order_id)` Canceling by Client Order ID[](https://docs.01.xyz/examples/python/trading#canceling-by-client-order-id) --------------------------------------------------------------------------------------------------------- Cancel orders using the `client_order_id` you specified when placing the order. `def cancel_order_by_client_id(session_id, session_key, client_order_id, account_id=None): """ Cancel an order by its client order ID. Args: session_id: Active session ID session_key: Session signing key client_order_id: The client_order_id you specified when placing the order account_id: Optional account ID (defaults to first account) """ server_time = int(requests.get(f"{API_URL}/timestamp").json()) action = schema_pb2.Action() action.current_timestamp = server_time action.cancel_order_by_client_id.session_id = session_id action.cancel_order_by_client_id.client_order_id = client_order_id if account_id is not None: action.cancel_order_by_client_id.sender_account_id = account_id receipt = execute_action(action, session_key, session_sign) if receipt.HasField("err"): raise Exception(f"Error: {schema_pb2.Error.Name(receipt.err)}") print(f"Order with client_order_id {client_order_id} cancelled!") return receipt # Example: Place order with client_order_id, then cancel by it my_order_id = 12345 # Your own tracking ID # Place order with client_order_id action = schema_pb2.Action() action.current_timestamp = int(requests.get(f"{API_URL}/timestamp").json()) action.place_order.session_id = session_id action.place_order.market_id = 0 action.place_order.side = schema_pb2.Side.BID action.place_order.fill_mode = schema_pb2.FillMode.LIMIT action.place_order.price = int(90000 * 10) # Assuming 1 price decimal action.place_order.size = int(0.001 * 10000) # Assuming 4 size decimals action.place_order.client_order_id = my_order_id # Your tracking ID receipt = execute_action(action, session_key, session_sign) # Later, cancel by client_order_id cancel_order_by_client_id(session_id, session_key, my_order_id)` Complete Trading Script[](https://docs.01.xyz/examples/python/trading#complete-trading-script) ----------------------------------------------------------------------------------------------- `import json import requests import binascii from google.protobuf.internal import encoder, decoder from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from base58 import b58encode import schema_pb2 API_URL = "https://zo-devnet.n1.xyz" # Helper functions def get_varint_bytes(value): return encoder._VarintBytes(value) def read_varint(buffer, offset=0): return decoder._DecodeVarint32(buffer, offset) def user_sign(key, msg): return key.sign(binascii.hexlify(msg)) def session_sign(key, msg): return key.sign(msg) def execute_action(action, signing_key, sign_func): payload = action.SerializeToString() message = get_varint_bytes(len(payload)) + payload signature = sign_func(signing_key, message) resp = requests.post( f"{API_URL}/action", data=message + signature, headers={"Content-Type": "application/octet-stream"} ) resp.raise_for_status() msg_len, pos = read_varint(resp.content, 0) receipt = schema_pb2.Receipt() receipt.ParseFromString(resp.content[pos:pos + msg_len]) return receipt def main(): # Load keys with open("id.json", "r") as f: key_data = json.load(f) user_key = Ed25519PrivateKey.from_private_bytes(bytes(key_data[:32])) session_key = Ed25519PrivateKey.generate() # Create session server_time = int(requests.get(f"{API_URL}/timestamp").json()) action = schema_pb2.Action() action.current_timestamp = server_time action.create_session.user_pubkey = user_key.public_key().public_bytes_raw() action.create_session.session_pubkey = session_key.public_key().public_bytes_raw() action.create_session.expiry_timestamp = server_time + 3600 receipt = execute_action(action, user_key, user_sign) session_id = receipt.create_session_result.session_id print(f"Session: {session_id}") # Get market info info = requests.get(f"{API_URL}/info").json() market = info["markets"][0] price_dec = market["priceDecimals"] size_dec = market["sizeDecimals"] print(f"Trading {market['symbol']}") # Place order server_time = int(requests.get(f"{API_URL}/timestamp").json()) action = schema_pb2.Action() action.current_timestamp = server_time action.place_order.session_id = session_id action.place_order.market_id = 0 action.place_order.side = schema_pb2.Side.BID action.place_order.fill_mode = schema_pb2.FillMode.LIMIT action.place_order.price = int(90000 * (10 ** price_dec)) action.place_order.size = int(0.001 * (10 ** size_dec)) receipt = execute_action(action, session_key, session_sign) if receipt.HasField("err"): print(f"Error: {schema_pb2.Error.Name(receipt.err)}") elif receipt.place_order_result.HasField("posted"): order_id = receipt.place_order_result.posted.order_id print(f"Order placed: {order_id}") # Cancel it server_time = int(requests.get(f"{API_URL}/timestamp").json()) action = schema_pb2.Action() action.current_timestamp = server_time action.cancel_order_by_id.session_id = session_id action.cancel_order_by_id.order_id = order_id receipt = execute_action(action, session_key, session_sign) print("Order cancelled!") if __name__ == "__main__": main()` Atomic Operations[](https://docs.01.xyz/examples/python/trading#atomic-operations) ----------------------------------------------------------------------------------- Execute multiple place/cancel actions in a single atomic transaction. > \[!IMPORTANT\] **Constraints:** > > * Maximum **4 operations** per atomic transaction > * **Ordering per market:** Cancels → Trades → Places (cancels must come first, placements last) > * Across different markets, order can be any `def atomic_cancel_and_place(session_id, session_key, cancel_order_ids, new_orders): """ Atomically cancel orders and place new ones. Args: cancel_order_ids: List of order IDs to cancel new_orders: List of dicts with {market_id, side, price, size} """ server_time = int(requests.get(f"{API_URL}/timestamp").json()) markets = get_market_info() action = schema_pb2.Action() action.current_timestamp = server_time action.atomic.session_id = session_id # Add cancel sub-actions for order_id in cancel_order_ids: sub = action.atomic.actions.add() sub.cancel_order.order_id = order_id # Add place sub-actions (using trade_or_place) for order in new_orders: market = markets[order["market_id"]] sub = action.atomic.actions.add() sub.trade_or_place.market_id = order["market_id"] sub.trade_or_place.order_type.side = order["side"] sub.trade_or_place.order_type.fill_mode = schema_pb2.FillMode.LIMIT sub.trade_or_place.order_type.is_reduce_only = False sub.trade_or_place.limit.price = int(order["price"] * (10 ** market["price_decimals"])) sub.trade_or_place.limit.size = int(order["size"] * (10 ** market["size_decimals"])) receipt = execute_action(action, session_key, session_sign) if receipt.HasField("err"): raise Exception(f"Atomic failed: {schema_pb2.Error.Name(receipt.err)}") print(f"Atomic action executed! Action ID: {receipt.action_id}") return receipt # Example: Cancel old orders and place new quotes atomic_cancel_and_place( session_id=session_id, session_key=session_key, cancel_order_ids=[old_bid_id, old_ask_id], new_orders=[ {"market_id": 0, "side": schema_pb2.Side.BID, "price": 89900, "size": 0.01}, {"market_id": 0, "side": schema_pb2.Side.ASK, "price": 90100, "size": 0.01}, ] )` Trigger Orders (Stop-Loss / Take-Profit)[](https://docs.01.xyz/examples/python/trading#trigger-orders-stop-loss--take-profit) ------------------------------------------------------------------------------------------------------------------------------ > \[!CAUTION\] **Experimental Feature:** Trigger orders (TP/SL) are currently unstable and may change. Use with caution in production. > \[!INFO\] **Auto-Close on Position Changes:** Triggers automatically close when your position is closed or flipped. This prevents triggers from executing unexpectedly after position state changes. ### Add Trigger[](https://docs.01.xyz/examples/python/trading#add-trigger) `def add_trigger(session_id, session_key, market_id, side, kind, trigger_price, limit_price=None): """ Add a stop-loss or take-profit trigger. Args: kind: schema_pb2.TriggerKind.STOP_LOSS or TAKE_PROFIT trigger_price: Price that activates the trigger limit_price: Optional limit price for the triggered order """ server_time = int(requests.get(f"{API_URL}/timestamp").json()) markets = get_market_info() market = markets[market_id] action = schema_pb2.Action() action.current_timestamp = server_time action.add_trigger.session_id = session_id action.add_trigger.market_id = market_id # TriggerKey contains kind and side action.add_trigger.key.kind = kind action.add_trigger.key.side = side # TriggerPrices contains trigger_price and optional limit_price action.add_trigger.prices.trigger_price = int(trigger_price * (10 ** market["price_decimals"])) if limit_price: action.add_trigger.prices.limit_price = int(limit_price * (10 ** market["price_decimals"])) receipt = execute_action(action, session_key, session_sign) if receipt.HasField("err"): raise Exception(f"AddTrigger failed: {schema_pb2.Error.Name(receipt.err)}") print(f"Trigger added! Action ID: {receipt.action_id}") return receipt # Example: Add stop-loss at $85,000 add_trigger( session_id=session_id, session_key=session_key, market_id=0, side=schema_pb2.Side.ASK, # Sell to close long kind=schema_pb2.TriggerKind.STOP_LOSS, trigger_price=85000, limit_price=84900 # Slight slippage protection )` ### Remove Trigger[](https://docs.01.xyz/examples/python/trading#remove-trigger) `def remove_trigger(session_id, session_key, market_id, side, kind): """Remove an existing trigger.""" server_time = int(requests.get(f"{API_URL}/timestamp").json()) action = schema_pb2.Action() action.current_timestamp = server_time action.remove_trigger.session_id = session_id action.remove_trigger.market_id = market_id # TriggerKey contains kind and side action.remove_trigger.key.kind = kind action.remove_trigger.key.side = side receipt = execute_action(action, session_key, session_sign) if receipt.HasField("err"): raise Exception(f"RemoveTrigger failed: {schema_pb2.Error.Name(receipt.err)}") print("Trigger removed!") return receipt` Next Steps[](https://docs.01.xyz/examples/python/trading#next-steps) --------------------------------------------------------------------- * [Funds & Withdrawals](https://docs.01.xyz/examples/python/funds) - Withdraw funds and transfer between accounts * [Account Info](https://docs.01.xyz/examples/python/account) - Fetch balances, positions, and orders Last updated on January 16, 2026 [Session & Authentication](https://docs.01.xyz/examples/python/session "Session & Authentication") [Market Data](https://docs.01.xyz/examples/python/market-data "Market Data") --- # Market Data (Python) | 01 [Skip to Content](https://docs.01.xyz/examples/python/market-data#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") [Python Integration](https://docs.01.xyz/examples/python "Python Integration") Market Data Copy page Market Data (Python) ==================== Fetching public market data using Python’s `requests` library. Markets and Tokens[](https://docs.01.xyz/examples/python/market-data#markets-and-tokens) ----------------------------------------------------------------------------------------- `import requests API_URL = "https://zo-mainnet.n1.xyz" def get_markets(): """Fetch all available markets.""" resp = requests.get(f"{API_URL}/info") data = resp.json() for market in data["markets"]: print(f"{market['marketId']}: {market['symbol']} " f"(price_dec={market['priceDecimals']}, size_dec={market['sizeDecimals']})") return data["markets"] def get_tokens(): """Fetch all available tokens.""" resp = requests.get(f"{API_URL}/info") data = resp.json() for token in data["tokens"]: print(f"{token['tokenId']}: {token['symbol']} ({token['decimals']} decimals)") return data["tokens"] markets = get_markets() # Output: # 0: BTCUSD (price_dec=1, size_dec=4) # 1: ETHUSD (price_dec=2, size_dec=3) # ...` Market Statistics[](https://docs.01.xyz/examples/python/market-data#market-statistics) --------------------------------------------------------------------------------------- `def get_market_stats(market_id: int): """Fetch detailed statistics for a market.""" resp = requests.get(f"{API_URL}/market/{market_id}/stats") stats = resp.json() print(f"Market {market_id} Stats:") print(f" Index Price: ${stats['indexPrice']:,.2f}") print(f" Mark Price: ${stats['perpStats']['mark_price']:,.2f}") print(f" Funding Rate: {stats['perpStats']['funding_rate']:.4%}") print(f" Open Interest: {stats['perpStats']['open_interest']:,.2f}") print(f" 24h Volume: ${stats['volumeQuote24h']:,.0f}") print(f" 24h High: ${stats['high24h']:,.2f}") print(f" 24h Low: ${stats['low24h']:,.2f}") return stats stats = get_market_stats(0) # BTC` Orderbook[](https://docs.01.xyz/examples/python/market-data#orderbook) ----------------------------------------------------------------------- `def get_orderbook(market_id: int, depth: int = 10): """Fetch orderbook for a market.""" resp = requests.get(f"{API_URL}/orderbook", params={"marketId": market_id}) book = resp.json() print(f"\n{'BIDS':^25} | {'ASKS':^25}") print("-" * 53) for i in range(min(depth, max(len(book["bids"]), len(book["asks"])))): bid = book["bids"][i] if i < len(book["bids"]) else ["-", "-"] ask = book["asks"][i] if i < len(book["asks"]) else ["-", "-"] bid_str = f"{bid[1]:.4f} @ ${bid[0]:,.1f}" if bid[0] != "-" else "" ask_str = f"${ask[0]:,.1f} @ {ask[1]:.4f}" if ask[0] != "-" else "" print(f"{bid_str:>25} | {ask_str:<25}") return book orderbook = get_orderbook(0) # BTC` Recent Trades[](https://docs.01.xyz/examples/python/market-data#recent-trades) ------------------------------------------------------------------------------- `from datetime import datetime def get_recent_trades(market_id: int, limit: int = 20): """Fetch recent trades for a market.""" resp = requests.get( f"{API_URL}/trades", params={"marketId": market_id, "pageSize": limit} ) data = resp.json() print(f"\nRecent Trades (Market {market_id}):") print(f"{'Time':^12} | {'Side':^4} | {'Price':^12} | {'Size':^10}") print("-" * 45) for trade in data["trades"]: time = datetime.fromtimestamp(trade["timestamp"] / 1000) side = "BUY" if trade["side"] == "bid" else "SELL" print(f"{time:%H:%M:%S} | {side:^4} | ${trade['price']:>10,.1f} | {trade['size']:>10.4f}") return data["trades"] trades = get_recent_trades(0)` Funding Rate Monitoring[](https://docs.01.xyz/examples/python/market-data#funding-rate-monitoring) --------------------------------------------------------------------------------------------------- `import time from concurrent.futures import ThreadPoolExecutor def monitor_funding_rates(market_ids: list, interval: int = 60): """Monitor funding rates for multiple markets.""" def fetch_stats(market_id): resp = requests.get(f"{API_URL}/market/{market_id}/stats") return resp.json() print("Monitoring funding rates (Ctrl+C to stop)...") try: while True: with ThreadPoolExecutor(max_workers=5) as executor: all_stats = list(executor.map(fetch_stats, market_ids)) print(f"\n{datetime.now():%Y-%m-%d %H:%M:%S}") for stats in all_stats: market_id = stats["marketId"] funding = stats["perpStats"]["funding_rate"] mark = stats["perpStats"]["mark_price"] print(f" Market {market_id}: {funding:+.4%} @ ${mark:,.2f}") time.sleep(interval) except KeyboardInterrupt: print("\nStopped.") # Monitor BTC, ETH, SOL # monitor_funding_rates([0, 1, 2], interval=60)` WebSocket Streaming[](https://docs.01.xyz/examples/python/market-data#websocket-streaming) ------------------------------------------------------------------------------------------- For real-time data, use WebSockets: `import asyncio import websockets import json async def stream_candles(symbol: str, resolution: str = "1"): """Stream real-time candle data.""" uri = f"wss://zo-mainnet.n1.xyz/ws/candle@{symbol}:{resolution}" async with websockets.connect(uri) as ws: print(f"Connected to {symbol} {resolution}m candles") async for message in ws: candle = json.loads(message) print(f"O: {candle['o']:.1f} H: {candle['h']:.1f} " f"L: {candle['l']:.1f} C: {candle['c']:.1f}") # Run with: asyncio.run(stream_candles("BTCUSD", "1"))` Full Market Dashboard[](https://docs.01.xyz/examples/python/market-data#full-market-dashboard) ----------------------------------------------------------------------------------------------- `def market_dashboard(market_id: int = 0): """Display a comprehensive market dashboard.""" # Fetch all data info = requests.get(f"{API_URL}/info").json() stats = requests.get(f"{API_URL}/market/{market_id}/stats").json() book = requests.get(f"{API_URL}/orderbook", params={"marketId": market_id}).json() market = next(m for m in info["markets"] if m["marketId"] == market_id) print(f"\n{'='*50}") print(f"{market['symbol']} Market Dashboard") print(f"{'='*50}") print(f"\nPRICES") print(f"Index: ${stats['indexPrice']:,.2f}") print(f"Mark: ${stats['perpStats']['mark_price']:,.2f}") spread = book['asks'][0][0] - book['bids'][0][0] if book['bids'] and book['asks'] else 0 print(f"Spread: ${spread:.1f}") print(f"\n24H STATS") print(f"Volume: ${stats['volumeQuote24h']:,.0f}") print(f"High: ${stats['high24h']:,.2f}") print(f"Low: ${stats['low24h']:,.2f}") print(f"\nFUNDING") print(f"Rate: {stats['perpStats']['funding_rate']:+.4%}") print(f"Next: {stats['perpStats']['next_funding_time']}") print(f"\nORDERBOOK (Top 5)") print(f"{'BIDS':^20} | {'ASKS':^20}") for i in range(5): bid = book['bids'][i] if i < len(book['bids']) else [0, 0] ask = book['asks'][i] if i < len(book['asks']) else [0, 0] print(f"{bid[1]:.4f} @ ${bid[0]:,.1f} | ${ask[0]:,.1f} @ {ask[1]:.4f}") market_dashboard(0)` Last updated on January 16, 2026 [Trading Operations](https://docs.01.xyz/examples/python/trading "Trading Operations") [Funds & Withdrawals](https://docs.01.xyz/examples/python/funds "Funds & Withdrawals") --- # Page | 01 [Skip to Content](https://docs.01.xyz/margins/01#nextra-skip-nav) MarginsAccount Margins Copy page ### 1\. Understanding Account Margins (Numerators & Dollar Values)[](https://docs.01.xyz/margins/01#1-understanding-account-margins-numerators--dollar-values) A critical technical detail of the Nord API is that the `https://zo-mainnet.n1.xyz/account/{accountId}` endpoint returns **numerators** for the account margins, representing actual **USDC dollar values** . In contrast to the official margining docs, this structure is used because all margin requirements for a user share a common denominator, the **Position Open Notional (PON)** which is omitted to show absolute risk values in dollar format. #### API Margin Values[](https://docs.01.xyz/margins/01#api-margin-values) **`tv` (Token Value)** * **Formula:** ∑(balance⋅weight⋅pindex)\\sum (\\text{balance} \\cdot \\text{weight} \\cdot p\_{index})∑(balance⋅weight⋅pindex​) * **Description:** The discounted dollar value of all positive asset balances (spot assets). **`mf` (Account Value / `av`)** * **Formula:** ∑(balance⋅weight⋅pindex)+∑(PnL)−∑(borrow⋅pindexweight)\\sum (\\text{balance} \\cdot \\text{weight} \\cdot p\_{index}) + \\sum (\\text{PnL}) - \\sum \\left( \\frac{\\text{borrow} \\cdot p\_{index}}{\\text{weight}} \\right)∑(balance⋅weight⋅pindex​)+∑(PnL)−∑(weightborrow⋅pindex​​) * **Description:** Total net account equity, accounting for assets, liabilities, and unrealized PnL. **`pon` (Position Open Notional)** * **Formula:** ∑(∣position\_size∣⋅pindex⋅IMFbase)+∑(order\_notional⋅IMFbase)\\sum (|\\text{position\\\_size}| \\cdot p\_{index} \\cdot IMF\_{base}) + \\sum (\\text{order\\\_notional} \\cdot IMF\_{base})∑(∣position\_size∣⋅pindex​⋅IMFbase​)+∑(order\_notional⋅IMFbase​) * **Description:** The total weighted risk of the account, including both open positions and pending orders. **`pn` (Position Notional)** * **Formula:** ∑(∣position\_size∣⋅pindex⋅IMFbase)\\sum (|\\text{position\\\_size}| \\cdot p\_{index} \\cdot IMF\_{base})∑(∣position\_size∣⋅pindex​⋅IMFbase​) * **Description:** A subset of `pon` representing the weighted dollar value of open positions only. **`imf` (Initial Margin Fraction)** * **Formula:** ∑(PON⋅IMFbase)\\sum (PON \\cdot IMF\_{base})∑(PON⋅IMFbase​) * **Description:** The total dollar amount required to be maintained in order to open new positions. **`omf` (Open Margin Fraction)** * **Formula:** min⁡(AV,TV)\\min(AV, TV)min(AV,TV) * **Description:** The effective equity value used by the system to check against the initial margin requirement. **`cmf` (Cancel Margin Fraction)** * **Formula:** ∑(PON⋅CMFbase)\\sum (PON \\cdot CMF\_{base})∑(PON⋅CMFbase​) where CMFbaseCMF\_{base}CMFbase​ is (5/8)⋅IMFbase(5/8) \\cdot IMF\_{base}(5/8)⋅IMFbase​ (perp) or IMFbaseIMF\_{base}IMFbase​ (spot). * **Description:** The dollar threshold below which the system will begin canceling open orders. **`mmf` (Maintenance Margin Fraction)** * **Formula:** ∑(PON⋅MMFbase)\\sum (PON \\cdot MMF\_{base})∑(PON⋅MMFbase​) where MMFbaseMMF\_{base}MMFbase​ is (1/2)⋅IMFbase(1/2) \\cdot IMF\_{base}(1/2)⋅IMFbase​ (perp) or (1.03/weight−1)(1.03/\\text{weight} - 1)(1.03/weight−1) (spot). * **Description:** The minimum dollar equity required to avoid liquidation of open positions. * * * ### 2\. Leverage & The Risk Engine[](https://docs.01.xyz/margins/01#2-leverage--the-risk-engine) It is important to distinguish between the front-end user interface and the back-end risk engine regarding leverage. * **Front-end Leverage Slider**: This works solely as a **risk-management tool** for the user. It allows you to artificially limit your exposure, but it does not change the underlying margin requirements of the exchange. * **Back-end Risk Engine**: The engine always operates under the assumption of the **Maximum Leverage** allowed for a specific market. * **Example**: If Bitcoin (BTC) allows **50x leverage** (0.02 IMF), and you open a 1,000positionwhileyourfront−endsliderissetto"10x,"theUImightimplyyouareusing1,000 position while your front-end slider is set to "10x," the UI might imply you are using 1,000positionwhileyourfront−endsliderissetto"10x,"theUImightimplyyouareusing100 of margin. However, the risk engine calculates you are only using $20 of margin ($1000 \* 0.02$). The front-end will artificially limit the maximum order value you can open even if the risk engine allows for more. * **Liquidation Prices**: This logic explains why your liquidation price does not change when you adjust the leverage slider. The risk engine calculates your liquidation point based on the maximum possible leverage to ensure the safety of the protocol, regardless of the front-end leverage you have set. * * * ### 3\. Liquidation & Cancellation Rules[](https://docs.01.xyz/margins/01#3-liquidation--cancellation-rules) When an account becomes unhealthy, Nord triggers specific actions in a strict sequence to reduce risk. * **Order Cancellation (`omf < cmf`)**: If your account value (`omf`) drops below the `cmf` threshold, the system cancels open orders that would increase your position size. This happens before position liquidation to restore health without closing active trades. * **Position Liquidation (`mf < mmf`)**: If the account value (`mf`) drops below the `mmf` threshold, the exchange begins reducing your positions. * **Bankruptcy (`mf <= 0`)**: If account value becomes negative, the account is cleared by the insurance fund. * **Execution**: All liquidation orders are **Fill-or-Kill (FoK)**, meaning they are executed immediately or cancelled. * * * ### 4\. Margin Definitions for Markets[](https://docs.01.xyz/margins/01#4-margin-definitions-for-markets) The thresholds for `imf`, `cmf`, and `mmf` are derived from the risk profile of each market at `https://zo-mainnet.n1.xyz/info` (Note that in contrast to the account margin, the margin information here actually shows the decimal value for the market itself, not dollar value). * **Initial Margin (IMF)**: The primary representative of maximum leverage. For example, a 0.02 IMF is equal to **50x leverage**. * **Maintenance Margin (MMF)**: Typically set at **half of the IMF** (e.g., if IMF is 0.02, MMF is 0.01). * **Cancel Margin (CMF)**: For perpetuals, this is defined as **5/8 of the IMF**. * * * ### 5\. Funding Accumulation[](https://docs.01.xyz/margins/01#5-funding-accumulation) Funding at Nord follows an accumulation model for maximum efficiency. * **Accumulation Frequency**: Funding is **not paid out** every hour; instead, it is **accumulated every hour** based on the current funding rates. * **Lazy Settlement**: This accumulated value is tracked via a global **Funding Index**. * **Realization**: Payments are only settled and reflected in your actual balance when your position is updated, such as through a trade. * **Risk Calculation**: If a position is untouched, funding continues to accumulate as **unsettled funding**. This unsettled amount is still factored into your `omf` and `mf` to ensure accurate risk monitoring. * * * ### 6\. Primary Formulas[](https://docs.01.xyz/margins/01#6-primary-formulas) #### Max Available to Trade[](https://docs.01.xyz/margins/01#max-available-to-trade) To find the maximum notional value you can open on a specific market (mmm) as allowed by the risk engine (considering cross-margining): Available Notional\=omfuser−imfuserIMFbase,m\\text{Available Notional} = \\frac{omf\_{\\text{user}} - imf\_{\\text{user}}}{\\text{IMF}\_{\\text{base}, m}}Available Notional\=IMFbase,m​omfuser​−imfuser​​ * **omfuseromf\_{\\text{user}}omfuser​**: Operational Margin Factor (the minimum of your total Account Value and weighted Token Value). * **imfuserimf\_{\\text{user}}imfuser​**: Your current total initial margin requirement numerator. * **IMFbase,m\\text{IMF}\_{\\text{base}, m}IMFbase,m​**: The specific initial margin rate for the asset. #### Liquidation Price[](https://docs.01.xyz/margins/01#liquidation-price) Calculates the distance from the **current index price** where mfusermf\_{\\text{user}}mfuser​ will equal mmfusermmf\_{\\text{user}}mmfuser​. #### For Longs:[](https://docs.01.xyz/margins/01#for-longs) pliq\=pcurrent−mfuser−mmfusers×(1−MMFbase)p\_{\\text{liq}} = p\_{\\text{current}} - \\frac{mf\_{\\text{user}} - mmf\_{\\text{user}}}{s \\times (1 - MMF\_{\\text{base}})}pliq​\=pcurrent​−s×(1−MMFbase​)mfuser​−mmfuser​​ #### For Shorts:[](https://docs.01.xyz/margins/01#for-shorts) pliq\=pcurrent+mfuser−mmfusers×(1+MMFbase)p\_{\\text{liq}} = p\_{\\text{current}} + \\frac{mf\_{\\text{user}} - mmf\_{\\text{user}}}{s \\times (1 + MMF\_{\\text{base}})}pliq​\=pcurrent​+s×(1+MMFbase​)mfuser​−mmfuser​​ * **mfuser−mmfusermf\_{\\text{user}} - mmf\_{\\text{user}}mfuser​−mmfuser​**: Your dollar cushion before reaching the liquidation threshold. * **s×(1±MMFbase)s \\times (1 \\pm MMF\_{\\text{base}})s×(1±MMFbase​)**: Position sensitivity. The (1±MMFbase)(1 \\pm MMF\_{\\text{base}})(1±MMFbase​) factor accounts for the **“double-squeeze”**: as price moves against you, your account value drops **and** your required maintenance margin increases. Last updated on February 3, 2026 [Account Info](https://docs.01.xyz/examples/python/account "Account Info") [Risk Framework](https://docs.01.xyz/margins/n1 "Risk Framework") --- # Support | 01 [Skip to Content](https://docs.01.xyz/support#nextra-skip-nav) SupportSupport Guide Copy page Support Guide ============= Welcome to 01 Exchange support. Before reaching out, please check our resources below — most questions are answered in our documentation. Quick Links[](https://docs.01.xyz/support#quick-links) ------------------------------------------------------- | Resource | Description | | --- | --- | | [FAQ](https://docs.01.xyz/support/faq) | Frequently asked questions about 01 | | [Common Errors](https://docs.01.xyz/common-errors) | Trading error codes and solutions | | [Getting Started](https://docs.01.xyz/getting-started) | Setup guide for new users | | [API Reference](https://docs.01.xyz/reference) | Technical API documentation | Before You Contact Us[](https://docs.01.xyz/support#before-you-contact-us) --------------------------------------------------------------------------- > **💡 Search First** — Most issues can be resolved by searching our documentation or FAQ. Use the search bar at the top of the page. 1. **Check the FAQ** — Browse our [FAQ section](https://docs.01.xyz/support/faq) for answers to common questions 2. **Review Common Errors** — If you encountered an error, check the [error reference](https://docs.01.xyz/common-errors) 3. **Search the Docs** — Use the search function to find relevant guides Contact Us[](https://docs.01.xyz/support#contact-us) ----------------------------------------------------- If you still need help after checking the resources above: | Channel | Use For | | --- | --- | | [X (@01exchange)](https://x.com/01exchange) | General questions, announcements | | [Discord](https://discord.gg/JZwrrgMhGT) | Community support, live chat | > **⚠️ Security Notice** — The 01 team will never DM you first or ask for your private keys. Be cautious of scammers impersonating our team. Response Times[](https://docs.01.xyz/support#response-times) ------------------------------------------------------------- Our team monitors X and Discord and responds to inquiries as quickly as possible. Please allow up to 48 hours for a response during busy periods. Last updated on January 16, 2026 [Common Errors](https://docs.01.xyz/common-errors "Common Errors") [Overview](https://docs.01.xyz/support/faq "Overview") --- # Account Information (Python) | 01 [Skip to Content](https://docs.01.xyz/examples/python/account#nextra-skip-nav) [Usage Examples](https://docs.01.xyz/examples/initializing "Usage Examples") [Python Integration](https://docs.01.xyz/examples/python "Python Integration") Account Info Copy page Account Information (Python) ============================ Fetch user account data including balances, positions, and open orders. Fetching User Info[](https://docs.01.xyz/examples/python/account#fetching-user-info) ------------------------------------------------------------------------------------- The user info endpoint returns balances, positions, and orders for an account. `import requests from base58 import b58encode API_URL = "https://zo-devnet.n1.xyz" def get_user_info(user_pubkey: bytes): """ Fetch user account information. Args: user_pubkey: 32-byte user public key """ pubkey_b58 = b58encode(user_pubkey).decode() resp = requests.get(f"{API_URL}/user/{pubkey_b58}") if resp.status_code != 200: raise Exception(f"Failed to fetch user info: {resp.status_code}") return resp.json() # Example usage user_pubkey = user_key.public_key().public_bytes_raw() info = get_user_info(user_pubkey) print("Balances:", info.get("balances", [])) print("Positions:", info.get("positions", [])) print("Open Orders:", info.get("orders", []))` Understanding the Response[](https://docs.01.xyz/examples/python/account#understanding-the-response) ----------------------------------------------------------------------------------------------------- ### Balances[](https://docs.01.xyz/examples/python/account#balances) `{ "tokenId": 1, "available": 10000.0, # Available for trading "locked": 500.0, # Locked in open orders "total": 10500.0 # Total balance }` ### Positions[](https://docs.01.xyz/examples/python/account#positions) `{ "marketId": 0, "size": 0.5, # Position size (+ long, - short) "entryPrice": 92000.0, # Average entry price "unrealizedPnl": 250.0, # Current unrealized PnL "liquidationPrice": 75000.0 # Estimated liquidation price }` ### Orders[](https://docs.01.xyz/examples/python/account#orders) `{ "orderId": 12345, "marketId": 0, "side": "bid", # "bid" or "ask" "price": 90000.0, "size": 0.1, "filledSize": 0.0, "status": "open" }` Monitoring Positions[](https://docs.01.xyz/examples/python/account#monitoring-positions) ----------------------------------------------------------------------------------------- `def monitor_positions(user_pubkey, interval=5): """Monitor positions and PnL in real-time.""" import time pubkey_b58 = b58encode(user_pubkey).decode() while True: try: resp = requests.get(f"{API_URL}/user/{pubkey_b58}") info = resp.json() print(f"\n{'='*50}") print(f"Time: {time.strftime('%H:%M:%S')}") for pos in info.get("positions", []): if pos["size"] != 0: print(f"Market {pos['marketId']}: " f"Size={pos['size']:+.4f} " f"Entry=${pos['entryPrice']:,.2f} " f"PnL=${pos['unrealizedPnl']:+,.2f}") time.sleep(interval) except KeyboardInterrupt: break # monitor_positions(user_pubkey)` Checking Available Margin[](https://docs.01.xyz/examples/python/account#checking-available-margin) --------------------------------------------------------------------------------------------------- `def get_available_margin(user_pubkey): """Calculate available margin for new trades.""" info = get_user_info(user_pubkey) # Sum available balances (simplified) total_available = sum( b["available"] for b in info.get("balances", []) if b["tokenId"] == 1 # USDC ) # Account for unrealized PnL unrealized_pnl = sum( p["unrealizedPnl"] for p in info.get("positions", []) ) return total_available + unrealized_pnl margin = get_available_margin(user_pubkey) print(f"Available margin: ${margin:,.2f}")` Listing Open Orders[](https://docs.01.xyz/examples/python/account#listing-open-orders) --------------------------------------------------------------------------------------- `def get_open_orders(user_pubkey, market_id=None): """Get open orders, optionally filtered by market.""" info = get_user_info(user_pubkey) orders = info.get("orders", []) if market_id is not None: orders = [o for o in orders if o["marketId"] == market_id] for order in orders: side = "BUY" if order["side"] == "bid" else "SELL" print(f"Order {order['orderId']}: {side} " f"{order['size']:.4f} @ ${order['price']:,.2f}") return orders # Get all BTC orders btc_orders = get_open_orders(user_pubkey, market_id=0)` Last updated on January 16, 2026 [Funds & Withdrawals](https://docs.01.xyz/examples/python/funds "Funds & Withdrawals") [Account Margins](https://docs.01.xyz/margins/01 "Account Margins") --- # FAQ | 01 [Skip to Content](https://docs.01.xyz/support/faq#nextra-skip-nav) [Support](https://docs.01.xyz/support "Support") FAQOverview Copy page Frequently Asked Questions ========================== Find answers to common questions about 01 Exchange, trading, leverage, and troubleshooting. Categories[](https://docs.01.xyz/support/faq#categories) --------------------------------------------------------- | Category | Topics Covered | | --- | --- | | [General](https://docs.01.xyz/support/faq/general) | About 01, getting started, fees, contact | | [Trading](https://docs.01.xyz/support/faq/trading) | Leverage, liquidation, risks, order types | | [Troubleshooting](https://docs.01.xyz/support/faq/troubleshooting) | Common errors and solutions | * * * Can’t find what you’re looking for?[](https://docs.01.xyz/support/faq#cant-find-what-youre-looking-for) -------------------------------------------------------------------------------------------------------- Check out our other resources: * [Getting Started Guide](https://docs.01.xyz/getting-started) — Step-by-step setup instructions * [API Reference](https://docs.01.xyz/reference) — Technical documentation for developers * [Common Errors](https://docs.01.xyz/common-errors) — Detailed error code reference Last updated on February 3, 2026 [Support Guide](https://docs.01.xyz/support "Support Guide") [General](https://docs.01.xyz/support/faq/general "General") --- # Common Errors | 01 [Skip to Content](https://docs.01.xyz/common-errors#nextra-skip-nav) Common Errors Copy page Common Errors ============= This guide lists common errors you might encounter when using the SDK or API, along with their causes and recommended solutions. Error Reference[](https://docs.01.xyz/common-errors#error-reference) --------------------------------------------------------------------- | Error Subject | Error Messages / Codes | Description & Solution | | --- | --- | --- | | **Insufficient Funds** | `insufficient lamports`, `BALANCE_INSUFFICIENT`, `BANKRUPTCY_INSUFFICIENT_COVERAGE` | **Cause:** Wallet lacks enough SOL for transaction fees or USDC/tokens for the trade.
**Solution:** Deposit more funds to cover fees and order value. | | **Session & Auth** | `SESSION_NOT_FOUND`, `INVALID_SIGNATURE` | **Cause:** The trading session key has expired, is invalid, or the signature failed.
**Solution:** Refresh the session or disconnect and reconnect your wallet to generate a new session. | | **Order Validation** | `ORDER_EXECUTION_LIMIT_PRICE`, `ORDER_EXECUTION_SIZE_LIMIT`, `tick size`, `precision` | **Cause:** Price or size does not meet market precision requirements.
**Solution:** Adjust values to match the market’s tick size and lot size. | | **Market Constraints** | `POST_ONLY_MUST_NOT_FILL_ANY_OPPOSITE_ORDERS`, `IMMEDIATE_ORDER_GOT_NO_FILLS`, `ORDER_EXECUTION_FILL_OR_KILL` | **Cause:** Order constraints (Post-Only, IOC, FOK) could not be satisfied.
**Solution:** Relax constraints or adjust price/size to ensure execution. | | **Market Status** | `MARKET_NOT_READY`, `MARKET_FROZEN` | **Cause:** The market is currently closed or frozen.
**Solution:** Wait for the market to resume trading. | | **Position Limits** | `POSITION_SIZE_LIMIT`, `REDUCE_ONLY`, `position size` | **Cause:** Position limit reached or “Reduce-Only” order would increase position.
**Solution:** Reduce trade size or ensure the order only closes existing positions. | | **Stale Data** | `TIMESTAMP_STALE`, `TIMESTAMP_OUT_OF_THRESHOLD`, `price changed` | **Cause:** Market data used for the order is too old.
**Solution:** Fetch fresh market data and retry the order. | | **Account Health** | `UNHEALTHY`, `OMF` | **Cause:** Order would put account in an unhealthy state or exceed risk parameters.
**Solution:** Reduce order size or add more margin to your account. | | **Order Execution** | `ORDER_EXECUTION_EMPTY` | **Cause:** Market has insufficient liquidity to fill the order.
**Solution:** Try a smaller order size or wait for more orderbook liquidity. | | **Minimum Size** | `minimum size`, `MINIMUM_SIZE_DECIMALS` | **Cause:** Order size is below the minimum required for the market.
**Solution:** Increase order size to meet the minimum lot size requirement. | | **Price Band** | `price band`, `outside range` | **Cause:** Order price is outside the allowed price band range.
**Solution:** Adjust price to be within the market’s price band limits. | | **Position Order Conflict** | `POSITION_STATE_ORDER_PRICE` | **Cause:** Market close order plus pending limit orders exceeds current position size.
**Solution:** Cancel some limit orders or reduce the close amount. | | **Nord Initialization** | `Invalid public key input` | **Cause:** Incorrect app ID when initializing Nord.
**Solution:** Verify the application ID used during initialization. | Last updated on February 3, 2026 [Risk Framework](https://docs.01.xyz/margins/n1 "Risk Framework") [Support Guide](https://docs.01.xyz/support "Support Guide") --- # General FAQ | 01 [Skip to Content](https://docs.01.xyz/support/faq/general#nextra-skip-nav) [Support](https://docs.01.xyz/support "Support") [FAQ](https://docs.01.xyz/support/faq "FAQ") General Copy page General FAQ =========== Common questions about 01 Exchange, getting started, and platform basics. * * * What is 01?[](https://docs.01.xyz/support/faq/general#what-is-01) ------------------------------------------------------------------ 01 is a decentralized exchange (DEX) frontend that allows users to trade cryptocurrencies and other digital assets in a permissionless, non-custodial manner directly on a blockchain. * * * What blockchain is 01 built on?[](https://docs.01.xyz/support/faq/general#what-blockchain-is-01-built-on) ---------------------------------------------------------------------------------------------------------- 01 uses [N1](https://n1.xyz/)  ’s NordVM engine, a purpose-built rollup for orderbooks with our own dedicated execution environment, to execute trades in a decentralized manner while having speed that is on-par with centralized exchanges. * * * How can I get started trading on 01?[](https://docs.01.xyz/support/faq/general#how-can-i-get-started-trading-on-01) -------------------------------------------------------------------------------------------------------------------- To start trading on 01, you will need to fund your 01 account with USDC from the Solana or Arbitrum blockchain. See our [Getting Started guide](https://docs.01.xyz/getting-started) for step-by-step instructions. * * * What can I trade on 01?[](https://docs.01.xyz/support/faq/general#what-can-i-trade-on-01) ------------------------------------------------------------------------------------------ For the latest list of active markets, please visit [01.xyz/markets](https://01.xyz/markets)  . * * * What are the fees for trading on 01?[](https://docs.01.xyz/support/faq/general#what-are-the-fees-for-trading-on-01) -------------------------------------------------------------------------------------------------------------------- 01 has different fee tiers depending on your last 30-day trade volume and whether you are a maker or taker: | Tier | 30-Day Volume | Maker Fee | Taker Fee | | --- | --- | --- | --- | | 1 | ≤ $5M | 0.01% | 0.035% | | 2 | \> $5M | 0.005% | 0.03% | | 3 | \> $25M | 0% | 0.025% | | 4 | \> $100M | 0% | 0.023% | | 5 | \> $1B | 0% | 0.02% | * * * Who can use 01?[](https://docs.01.xyz/support/faq/general#who-can-use-01) -------------------------------------------------------------------------- The 01 frontend is not accessible to, and may not be used by, any individual or entity that is a resident, citizen, incorporated in, located in, or otherwise operating from any jurisdiction that is subject to sanctions or other legal restrictions, including, but not limited to, the United States, Canada, Cuba, Iran, North Korea, Syria, Myanmar, and Russia (including regions occupied or controlled by Russia). Restrictions may apply not only based on residency or physical location, but also on citizenship, place of incorporation, or jurisdiction of operations. By accessing or using 01, you represent and warrant that you are not a person or entity described above, and that your access to and use of 01 complies with all applicable laws and regulations. * * * What is the 01 Points Program?[](https://docs.01.xyz/support/faq/general#what-is-the-01-points-program) -------------------------------------------------------------------------------------------------------- The 01 Points Program rewards users with points, which are intended solely as a means of measuring and acknowledging user participation within the 01 ecosystem. To learn more about the points program, visit [01.xyz/points](https://01.xyz/points)  . * * * How can I reach out to the 01 team?[](https://docs.01.xyz/support/faq/general#how-can-i-reach-out-to-the-01-team) ------------------------------------------------------------------------------------------------------------------ You can reach out to our team on: * [X (formerly Twitter)](https://x.com/01exchange)   * [Discord](https://discord.gg/JZwrrgMhGT)   Last updated on February 3, 2026 [Overview](https://docs.01.xyz/support/faq "Overview") [Trading](https://docs.01.xyz/support/faq/trading "Trading") --- # Trading FAQ | 01 [Skip to Content](https://docs.01.xyz/support/faq/trading#nextra-skip-nav) [Support](https://docs.01.xyz/support "Support") [FAQ](https://docs.01.xyz/support/faq "FAQ") Trading Copy page Trading FAQ =========== Questions about leverage trading, liquidation, risks, and order execution. * * * Why trade on a DEX?[](https://docs.01.xyz/support/faq/trading#why-trade-on-a-dex) ---------------------------------------------------------------------------------- Trading on 01 offers users greater control, transparency, and security over their assets compared to traditional centralized exchanges. On 01, trades are executed directly on-chain in a non-custodial and permissionless manner — meaning you always retain ownership of your funds, without the need to trust a third party to hold or manage your assets. * * * What are the risks with trading?[](https://docs.01.xyz/support/faq/trading#what-are-the-risks-with-trading) ------------------------------------------------------------------------------------------------------------ Trading digital assets carries significant risks: * **Market Volatility** — Prices can be highly volatile, and you may lose part or all of your invested capital * **Self-Custody Responsibility** — You are fully responsible for managing your own funds, wallet security, and transaction approvals * **Smart Contract Risk** — Vulnerabilities, network congestion, or oracle failures may impact execution or settlement * **Liquidation Risk** — Leveraged positions can be liquidated in volatile conditions * **Slippage** — Fast-moving markets can result in execution at prices different from expected Before trading, carefully assess your risk tolerance, understand how the protocol works, and never trade with funds you cannot afford to lose. * * * What is leverage trading?[](https://docs.01.xyz/support/faq/trading#what-is-leverage-trading) ---------------------------------------------------------------------------------------------- Leverage trading allows you to borrow funds to increase your trading position, amplifying potential profits (or losses). For example: | Leverage | Price Move | P&L Impact | | --- | --- | --- | | 1x | +1% | +1% | | 5x | +1% | +5% | | 10x | +1% | +10% | | 20x | +1% | +20% | > **⚠️ High Risk** — Leverage amplifies both gains and losses. A 10x leveraged position with a 10% adverse price move would result in a 100% loss of your margin. * * * What is a liquidation?[](https://docs.01.xyz/support/faq/trading#what-is-a-liquidation) ---------------------------------------------------------------------------------------- Liquidation occurs when your leveraged position loses enough value that it can no longer cover the borrowed funds. The platform automatically closes your position to prevent further losses, often resulting in a loss of your initial margin. **To avoid liquidation:** * Use lower leverage * Set stop-loss orders * Monitor your positions regularly * Maintain adequate margin buffer * * * What order types are available?[](https://docs.01.xyz/support/faq/trading#what-order-types-are-available) ---------------------------------------------------------------------------------------------------------- 01 supports multiple order types: | Order Type | Description | | --- | --- | | **Market** | Execute immediately at the best available price | | **Limit** | Execute at a specified price or better | | **Post-Only** | Guaranteed to add liquidity (maker order) | | **IOC** | Immediate-or-Cancel — fill immediately or cancel unfilled portion | | **FOK** | Fill-or-Kill — fill entirely or cancel completely | * * * What is funding rate?[](https://docs.01.xyz/support/faq/trading#what-is-funding-rate) -------------------------------------------------------------------------------------- Funding rates are periodic payments between long and short traders to keep perpetual contract prices aligned with the spot market. When funding is positive, longs pay shorts; when negative, shorts pay longs. You can view current funding rates on the trading interface or via the [market data API](https://docs.01.xyz/reference/endpoints) . Last updated on January 16, 2026 [General](https://docs.01.xyz/support/faq/general "General") [Troubleshooting](https://docs.01.xyz/support/faq/troubleshooting "Troubleshooting") --- # Troubleshooting FAQ | 01 [Skip to Content](https://docs.01.xyz/support/faq/troubleshooting#nextra-skip-nav) [Support](https://docs.01.xyz/support "Support") [FAQ](https://docs.01.xyz/support/faq "FAQ") Troubleshooting Copy page Troubleshooting FAQ =================== Solutions for common issues and errors you may encounter while trading on 01. * * * Session & Authentication Issues[](https://docs.01.xyz/support/faq/troubleshooting#session--authentication-issues) ------------------------------------------------------------------------------------------------------------------ ### ”Session Expired” or “Session Invalid”[](https://docs.01.xyz/support/faq/troubleshooting#session-expired-or-session-invalid) **Cause:** Your trading session key has expired or become invalid. **Solution:** 1. Disconnect your wallet 2. Reconnect your wallet to generate a new session 3. Retry your transaction ### ”Signature Verification Failed”[](https://docs.01.xyz/support/faq/troubleshooting#signature-verification-failed) **Cause:** The session signature could not be verified. **Solution:** Disconnect and reconnect your wallet to create a fresh session. * * * Wallet & Balance Issues[](https://docs.01.xyz/support/faq/troubleshooting#wallet--balance-issues) -------------------------------------------------------------------------------------------------- ### ”Insufficient SOL for Fees”[](https://docs.01.xyz/support/faq/troubleshooting#insufficient-sol-for-fees) **Cause:** Your wallet doesn’t have enough SOL to cover Solana transaction fees. **Solution:** Ensure your wallet has at least 0.01 SOL for transaction fees. ### ”Insufficient Balance” or “Bankruptcy”[](https://docs.01.xyz/support/faq/troubleshooting#insufficient-balance-or-bankruptcy) **Cause:** Your account doesn’t have enough USDC to place the order. **Solution:** Deposit more USDC to your 01 account before placing the order. * * * Order Errors[](https://docs.01.xyz/support/faq/troubleshooting#order-errors) ----------------------------------------------------------------------------- ### ”Invalid Price” or “Invalid Size”[](https://docs.01.xyz/support/faq/troubleshooting#invalid-price-or-invalid-size) **Cause:** The price or size doesn’t meet market precision requirements. **Solution:** Adjust your values to match the market’s tick size and lot size requirements. ### ”Minimum Size Error”[](https://docs.01.xyz/support/faq/troubleshooting#minimum-size-error) **Cause:** Order size is below the minimum required for the market. **Solution:** Increase your order size to meet the minimum lot size requirement. ### ”Price Band Error”[](https://docs.01.xyz/support/faq/troubleshooting#price-band-error) **Cause:** Order price is outside the allowed price band range. **Solution:** Adjust your price to be within the market’s price band limits. * * * Order Constraint Errors[](https://docs.01.xyz/support/faq/troubleshooting#order-constraint-errors) --------------------------------------------------------------------------------------------------- ### ”Post-Only Error”[](https://docs.01.xyz/support/faq/troubleshooting#post-only-error) **Cause:** Your post-only order would immediately match and take liquidity. **Solution:** Adjust your limit price further from the market price to ensure it rests on the book. ### ”Fill-or-Kill Error”[](https://docs.01.xyz/support/faq/troubleshooting#fill-or-kill-error) **Cause:** The order could not be filled entirely and was cancelled. **Solution:** Reduce order size or use a different order type (e.g., IOC or Market). ### ”Immediate Order Got No Fills”[](https://docs.01.xyz/support/faq/troubleshooting#immediate-order-got-no-fills) **Cause:** There was no matching liquidity at your specified price. **Solution:** Try a smaller order size or wait for more orderbook liquidity. * * * Position & Limit Errors[](https://docs.01.xyz/support/faq/troubleshooting#position--limit-errors) -------------------------------------------------------------------------------------------------- ### ”Position Size Limit Reached”[](https://docs.01.xyz/support/faq/troubleshooting#position-size-limit-reached) **Cause:** The order would exceed your account’s maximum position limit. **Solution:** Reduce your order size or close existing positions first. ### ”Reduce-Only Error”[](https://docs.01.xyz/support/faq/troubleshooting#reduce-only-error) **Cause:** A reduce-only order would increase your position instead of decreasing it. **Solution:** Ensure your order only closes existing positions and doesn’t exceed your current position size. ### ”Market Close Error”[](https://docs.01.xyz/support/faq/troubleshooting#market-close-error) **Cause:** Market close amount plus existing limit orders exceeds your position size. **Solution:** Cancel some limit orders or reduce the close amount. * * * Market Status Errors[](https://docs.01.xyz/support/faq/troubleshooting#market-status-errors) --------------------------------------------------------------------------------------------- ### ”Market Closed”[](https://docs.01.xyz/support/faq/troubleshooting#market-closed) **Cause:** The market is not currently accepting orders. **Solution:** Wait for the market to resume trading. ### ”Market Frozen”[](https://docs.01.xyz/support/faq/troubleshooting#market-frozen) **Cause:** The market has been temporarily frozen due to a protocol issue. **Solution:** Wait for the market to be restored and try again. * * * Account Health Errors[](https://docs.01.xyz/support/faq/troubleshooting#account-health-errors) ----------------------------------------------------------------------------------------------- ### ”Unhealthy Order” or “OMF Error”[](https://docs.01.xyz/support/faq/troubleshooting#unhealthy-order-or-omf-error) **Cause:** The order would put your account into an unhealthy state or exceed risk parameters. **Solution:** Reduce your order size or add more margin to your account. * * * Still having issues?[](https://docs.01.xyz/support/faq/troubleshooting#still-having-issues) -------------------------------------------------------------------------------------------- If your issue isn’t listed here: 1. Check the [Common Errors reference](https://docs.01.xyz/common-errors) for a complete error table 2. Search the documentation using the search bar 3. Reach out on [X (@01exchange)](https://x.com/01exchange)   Last updated on January 16, 2026 [Trading](https://docs.01.xyz/support/faq/trading "Trading") --- # Markets | 01 [Skip to Content](https://docs.01.xyz/margins/n1#nextra-skip-nav) [Margins](https://docs.01.xyz/margins/01 "Margins") Risk Framework Copy page Markets ======= This document specifies nord’s market types and their respective behaviour, along with some implementation notes. It is designed to be readable by anyone with limited knowledge of financial markets, but with a strong technical background. Links to external resources are provided where appropriate. Nord provides spot trading, perpetual futures trading, and spot lending. To limit risk, a margining system is defined to limit the risk a user may take on. To simplify margining, all prices are quoted (i.e. denominated) in the same asset, which we chose to be USDC. In the implementation, the first token, with `token_id == 0`, is the denominator. Open questions[](https://docs.01.xyz/margins/n1#open-questions) ---------------------------------------------------------------- ### Do we need to define a dust threshold?[](https://docs.01.xyz/margins/n1#do-we-need-to-define-a-dust-threshold) We can define a “dust threshold” for assets, where below a certain amount the asset is considered to have amount 0. We defined this in the past to deal with certain edge cases around bankruptcy, but don’t recall the rationale. ### Do we need to define position open notional for spot markets?[](https://docs.01.xyz/margins/n1#do-we-need-to-define-position-open-notional-for-spot-markets) This depends on if we want to limit open orders given a certain amount of assets and if we allow spot trades to create borrows. ### Is it possible to pay and charge interest additively?[](https://docs.01.xyz/margins/n1#is-it-possible-to-pay-and-charge-interest-additively) Multiplicative interest payments cause some amount of loss of precision. Granted, the difference is negligible, but may open a possible loss of funds vector. ### Do we adjust margin fractions for small cap coins?[](https://docs.01.xyz/margins/n1#do-we-adjust-margin-fractions-for-small-cap-coins) We can apply the following to deal with small market caps. Similarly for CMF, MMF. IMFbase′\=max⁡(IMFbase,(10sizetotal supply)12)\\text{IMF}\_\\text{base}' = \\max\\bigg( \\text{IMF}\_\\text{base}, \\Big(10\\frac{\\text{size}}{\\text{total supply}}\\Big)^\\frac{1}{2} \\bigg) IMFbase′​\=max(IMFbase​,(10total supplysize​)21​) Definitions[](https://docs.01.xyz/margins/n1#definitions) ---------------------------------------------------------- For the purposes of this document specific representations are used. Implementation may choose to diverge. ### Position size[](https://docs.01.xyz/margins/n1#position-size) The number of owned contracts for a given perpetuals market. May be a fractional amount. A short position is defined as a negative position size. ### Fill size[](https://docs.01.xyz/margins/n1#fill-size) The size of the fill when orders are matched. The size is defined to be negative for the side selling. ### [Iverson bracket](https://en.wikipedia.org/wiki/Iverson_bracket)  [](https://docs.01.xyz/margins/n1#iverson-bracket) We sometimes use the Iverson bracket I\[⋅\]\\mathbb{I}\[\\cdot\]I\[⋅\], where I\[P\]\=1\\mathbb{I}\[P\] = 1I\[P\]\=1 if PPP is true, and 000 otherwise. ### Tokens[](https://docs.01.xyz/margins/n1#tokens) Prior to trading, a user must first deposit **tokens** in the form of tokenized financial assets such as USDC and ETH. The token is deposited into the vault and the user’s token amount is increased by the same amount. Similarly for withdrawals. ### Parameters[](https://docs.01.xyz/margins/n1#parameters) #### weight[](https://docs.01.xyz/margins/n1#weight) A number in (0,1\](0, 1\](0,1\] defining the contribution of this token to the overall account value. The weight is used to deal with certain asset types having high volatility or low liquidity. For example, suppose BTC has weight 0.9 and USD price 1000 USD/BTC. If a user deposits 1 BTC, then their account value increases by `0.9 * 1 BTC * 1000 BTC/USD = 900 USD`. #### token decimals[](https://docs.01.xyz/margins/n1#token-decimals) The decimal shift for the smallest possible denomination of this asset type. This allows deposit and withdrawals to be defined in terms of integers. The original value is recovered by dividing the amount by `10 ** token decimals`. For USDC, this might be set to 6. If a user wants to deposit 1 USDC, they would set the deposit amount to `1_000_000`. Note that the shifted amount doesn’t have to be the fraction currency for the asset, such as cents for USD. For example, for ETH, we may choose a token decimals value of 8 instead of the intelligently chosen default of 18 to prevent overflows. #### max rate[](https://docs.01.xyz/margins/n1#max-rate) The maximum interest rate for borrows of this token. #### optimal rate[](https://docs.01.xyz/margins/n1#optimal-rate) The optimal interest rate, beyond which the rate sharply increases to the max rate. #### optimal utilization[](https://docs.01.xyz/margins/n1#optimal-utilization) The optimal utilization, where utilization is the ratio of total borrow to total supply. #### origination fee[](https://docs.01.xyz/margins/n1#origination-fee) Percentage fee charged for borrows. Suppose amount xxx is borrowed. Then a fee of y\=x⋅origination feey = x \\cdot \\text{origination fee}y\=x⋅origination fee is moved to the accrued fee vault when the borrow occurs. The final borrowed amount is then x−yx - yx−y. #### liq fee[](https://docs.01.xyz/margins/n1#liq-fee) Fee charged for having a spot borrow of this asset type be liquidated. ### Borrowing[](https://docs.01.xyz/margins/n1#borrowing) Tokens may also be borrowed against other, positive token. All positive token is implicitly lent and gains interest. Limits for borrows are defined by the margining system explained further below. Here, we define how lending and borrowing interest rates are computed. We first define the utilization uuu as the fraction of borrows for the supply for a given token type. In other words, u\=borrowsupplyu = \\frac{\\text{borrow}}{\\text{supply}}u\=supplyborrow​ Given the token metaparameters defined above, the yearly **interest rate** IR\\text{IR}IR is given by IR\={u⋅optimal rateoptimal utilu≤optimal util(u−optimal util)⋅max rate−optimal rate1−optimal util+optimal utilu\>optimal util\\text{IR} = \\begin{cases} u \\cdot \\frac{\\text{optimal rate}}{\\text{optimal util}} & u \\le \\text{optimal util} \\\\ (u - \\text{optimal util}) \\cdot \\frac{\\text{max rate} - \\text{optimal rate}}{1 - \\text{optimal util}} + \\text{optimal util} & u > \\text{optimal util} \\end{cases}IR\={u⋅optimal utiloptimal rate​(u−optimal util)⋅1−optimal utilmax rate−optimal rate​+optimal util​u≤optimal utilu\>optimal util​ The paid and charged interest are tracked lazily through the **supply multiplier** and **borrow multiplier**. Let T\=3600⋅24⋅365T = 3600 \\cdot 24 \\cdot 365T\=3600⋅24⋅365 be the period, BtB\_tBt​ the borrow multiplier at time ttt, and StS\_tSt​ the supply multiplier at time ttt. Bt+Δt\=Bt(1+IRΔtT)St+Δt\=St(1+u⋅IRΔtT)\\begin{align\*} B\_{t + \\Delta t} &= B\_t\\Big( 1 + \\text{IR} \\frac{\\Delta t}{T} \\Big) \\\\ S\_{t + \\Delta t} &= S\_t\\Big( 1 + u \\cdot \\text{IR} \\frac{\\Delta t}{T} \\Big) \\\\ \\end{align\*}Bt+Δt​St+Δt​​\=Bt​(1+IRTΔt​)\=St​(1+u⋅IRTΔt​)​ To apply the borrow and supply multipliers, the asset amounts by the borrow and supply multipliers to reflect the interest. Markets[](https://docs.01.xyz/margins/n1#markets) -------------------------------------------------- ### Index price[](https://docs.01.xyz/margins/n1#index-price) Index price provided by oracle is not a single scalar value but rather a probabilistic one. Oracle collects prices for an asset from several values which leads to the final index price being expressed as median price `Pm` and confidence interval `C`, such that actual index price falls within `[Pm-C; Pm+C]` interval with 95% probability. For more details, see [Confidence intervals](https://docs.pyth.network/price-feeds/best-practices#confidence-intervals)  . Computations which use index price prefer its “conservative” value, i.e. reduce positive values obtained with its use and increase negative ones. This way we’re more sure that we don’t overestimate factors like account health or funding rates. Different kinds of index price are marked below as follows: * median index price: pindexp\_\\text{index}pindex​ * lower-bound index price: plow indexp\_\\text{low index}plow index​ * upper-bound index price: phigh indexp\_\\text{high index}phigh index​ ### Parameters[](https://docs.01.xyz/margins/n1#parameters-1) These definitions apply to both spot markets and perp markets. #### size decimals[](https://docs.01.xyz/margins/n1#size-decimals) Similar to `token decimals`, but applied to `size`s. Can be interpreted as the log10log\_{10}log10​ of the lot size of this market, where the lot size may only be a power of 10. #### tick decimals[](https://docs.01.xyz/margins/n1#tick-decimals) Similar to `token decimals`, but applied to all prices. Note that we use tick _decimals_ and not a tick size, so tick sizes are limited to powers of 10. #### example decimals[](https://docs.01.xyz/margins/n1#example-decimals) Let have 1 ETH. 1 ETH on balance represented by 10token\_decimals10^{token\\\_decimals}10token\_decimals. 1 ETH on orderbook represented by 10size\_decimals10^{size\\\_decimals}10size\_decimals. So we if want to find out number representing same ETH amount on balance and on orderbook (or position), we will get: balance/10token\_decimals\=size/10size\_decimalsbalance / 10^{token\\\_decimals} = size / 10^{size\\\_decimals}balance/10token\_decimals\=size/10size\_decimals which gives us way to convert one value into other. Here is some examples of used conversions: | from\\to | base\_size | base\_amount | quote\_size | quote\_amount | | --- | --- | --- | --- | --- | | base size | self | self / 10^size\_decimals | self \* price mantissa | quote\_size / 10^(size\_decimals + price\_decimals) | | token balance | self \* 10^size\_decimals / 10^token\_decimals | | | | where `amount` is real number which humans usually expect to see #### maker fee[](https://docs.01.xyz/margins/n1#maker-fee) Fee charged to an order maker on trades by the exchange. A typical value is 2 bps, or 0.02%. #### taker fee[](https://docs.01.xyz/margins/n1#taker-fee) Fee charged to an order taker on trades by the exchange. A typical value is 5 bps, or 0.05%. #### liq fee[](https://docs.01.xyz/margins/n1#liq-fee-1) Fee charged for having a position on this perp market be liquidated. #### withdrawal fee[](https://docs.01.xyz/margins/n1#withdrawal-fee) Withdrawing balance from app takes amount of token equivalent to amount configured in USDC. For token to be withdrawable it should have price to be available. ### Spot[](https://docs.01.xyz/margins/n1#spot) Spot trading can be used to trade non-USDC assets for USDC, and vice versa. Unlike perps, there isn’t a notion of reduce only orders nor of position. Trades only lead to user assets being swapped. ### Perpetual futures[](https://docs.01.xyz/margins/n1#perpetual-futures) ### What are perpetual futures? Perpetual futures, colloquially perps, are a financial derivative designed to closely track the underlying’s price. In other words, 1 perp contract on ETHUSD will have a USD price close to that of 1 ETH. For those familiar with regular futures, the idea is similar. Users deposit an initial margin and maintain it above a maintenance margin. The primary difference is the settlement is paid hourly and the future has no maturity. Perps are thus solely for speculative purposes and provide no inherent utility. ### Why trade perps instead of the underlying? #### Gaining leverage[](https://docs.01.xyz/margins/n1#gaining-leverage) Derivatives allow users to gain leverage, sometimes up to 20 times. For example, if a trader is 10x leveraged, then a 3% loss in BTCUSD will cause the trader to incur a 30% loss. The exchange protects itself by defining a liquidation protocol. If a trader is close to wiping out their token, then the user is forced to close positions. The margining system is outlined further below. #### Simplifying shorting[](https://docs.01.xyz/margins/n1#simplifying-shorting) Shorting in spot markets requires the trader to first borrow an asset and then sell it. In perp markets, a short simply corresponds to a negative position. #### Trading illiquid assets[](https://docs.01.xyz/margins/n1#trading-illiquid-assets) Perps allow a trader to gain exposure to the underlying without having to own it. This makes perps great for illiquid assets. In fact this is what perps were [originally designed for](https://www.nber.org/system/files/working_papers/t0131/t0131.pdf)  . #### Perpetual Futures Fills[](https://docs.01.xyz/margins/n1#perpetual-futures-fills) Users earns by trading taking and trading their positions. Let S\=fill size⋅position sizeS=\\text{fill size} \\cdot \\text{position size}S\=fill size⋅position size. On trades we perform the following updates: PnL\=I\[S<0\]⋅fill size⋅(open price−fill price)position size←I\[S\>0\]⋅position size+fill sizeopen price←I\[S\>0\]⋅(position size⋅open price+fill size⋅fill price)/(position size+fill size)\\begin{align\*} \\text{PnL} &= \\mathbb{I}\[S<0\] \\cdot \\text{fill size} \\cdot (\\text{open price} - \\text{fill price}) \\\\ \\text{position size} &\\leftarrow \\mathbb{I}\[S > 0\] \\cdot \\text{position size} + \\text{fill size} \\\\ \\text{open price} &\\leftarrow \\mathbb{I}\[S > 0\] \\cdot (\\text{position size} \\cdot \\text{open price} + \\text{fill size} \\cdot \\text{fill price}) / (\\text{position size} + \\text{fill size}) \\end{align\*}PnLposition sizeopen price​\=I\[S<0\]⋅fill size⋅(open price−fill price)←I\[S\>0\]⋅position size+fill size←I\[S\>0\]⋅(position size⋅open price+fill size⋅fill price)/(position size+fill size)​ Notice that the total sum of PnL and position sizes must sum to zero, i.e. ∑(PnL)\=0\\sum(\\text{PnL}) = 0∑(PnL)\=0 and ∑(position size)\=0\\sum(\\text{position size}) = 0∑(position size)\=0. In practice, there may be a small non-zero amount, though this should always be in favour of the exchange to prevent a possible loss of funds vector. Updates to **PnL** is mutually exclusive with updates to **open price** and **position size**. #### Funding[](https://docs.01.xyz/margins/n1#funding) For a given perp market, we define the **mark price** pmarkp\_\\text{mark}pmark​ as pmark\={ last mark priceif book empty(best bid price)⋅(1+one sided multiplier)if only bids(best ask price)⋅(1−one sided multiplier)if only asksbest ask price+best bid price2otherwisep\_\\text{mark} = \\begin{cases} \\text{ last mark price} & \\text{if book empty} \\\\ (\\text{best bid price}) \\cdot (1 + \\text{one sided multiplier}) & \\text{if only bids} \\\\ (\\text{best ask price}) \\cdot (1 - \\text{one sided multiplier}) & \\text{if only asks} \\\\ \\frac{\\text{best ask price} + \\text{best bid price}}{2} & \\text{otherwise} \\end{cases}pmark​\=⎩⎨⎧​ last mark price(best bid price)⋅(1+one sided multiplier)(best ask price)⋅(1−one sided multiplier)2best ask price+best bid price​​if book emptyif only bidsif only asksotherwise​ The “one sided multiplier” can be chosen arbitrarily and is used to incentivize placing orders on the empty side. We hardcode it to 1%. The mark price is kept close to the median index price through the use of **funding**. We define the **funding rate** FR\\text{FR}FR as FR\=twap1 hour(pmarkpindex−1)/24\\text{FR} = \\mathop{\\text{twap}}\_{\\text{1 hour}}\\Big( \\frac{p\_{\\text{mark}}}{p\_\\text{index}} - 1 \\Big) / 24 FR\=twap1 hour​(pindex​pmark​​−1)/24 For notational simplicity, we define short positions as simply having a negative position and fill size of sell to be negative too, although implementations may choose to do so differently. For perp market: ∑position sizei\=0\\sum \\text{position size}\_i = 0∑position sizei​\=0 We define **current funding index** to be CFI\=FR⋅pindex\\text{CFI} = \\text{FR} \\cdot p\_\\text{index}CFI\=FR⋅pindex​ The **funding payment** is done every hour (**update interval**), computed by funding payment\=position size⋅CFI\\text{funding payment} = \\text{position size} \\cdot \\text{CFI}funding payment\=position size⋅CFI Unfortunately, iterating through all accounts to pay funding can be expensive. To alleviate this problem, we can pay funding lazily. We introduce the concept of **unsettled funding** to refer to funding that has not been paid out yet, and **settled funding** to denote the total amount of funding paid out so far. The **funding index** is adjusted on **funding rate** updates. The **user funding index** updated on user funding payments and position updates. When the position is closed, change to user position calculated as: balance change\=−position size⋅(FI - UFI)\\text{balance change} = - \\text{position size} \\cdot (\\text{FI - UFI})balance change\=−position size⋅(FI - UFI) where UFIUFIUFI use stored on last position update. **Funding index** updated with: FI\=FI+CFI⋅active time passed since last updateupdate interval\\text{FI} = \\text{FI} + \\frac{\\text{CFI} \\cdot \\text{active time passed since last update}}{\\text{update interval}}FI\=FI+update intervalCFI⋅active time passed since last update​ **Summary** * if pricemark\>priceindexprice\_{mark} > price\_{index}pricemark​\>priceindex​ during update interval, FRFRFR grows, lead to FIFIFI grow, hence long positions pay short positions * if pricemarkIMFuser\\text{OMF}\_user > \\text{IMF}\_userOMFu​ser\>IMFu​ser. First, we first define a per-market or per-asset **base IMF**. IMFbase\=1max leverage(perp)IMFbase\=1.1weightbase token−1(spot)\\begin{align\*} \\text{IMF}\_\\text{base} &= \\frac{1}{\\text{max leverage}} & (\\text{perp}) \\\\ \\text{IMF}\_\\text{base} &= \\frac{1.1}{\\text{weight}\_\\text{base token}} - 1 & (\\text{spot}) \\end{align\*} IMFbase​IMFbase​​\=max leverage1​\=weightbase token​1.1​−1​(perp)(spot)​ where * max leverage\\text{max leverage}max leverage is the maximum leverage multiplier for specific market; implementation may operate with market’s imf\\text{imf}imf value, in which case IMFbase\=imfmarket(perp)\\begin{align\*} \\text{IMF}\_\\text{base} &= {\\text{imf}\_\\text{market}} & (\\text{perp}) \\end{align\*} IMFbase​​\=imfmarket​​(perp)​ * weight\\text{weight}weight is the weight of spot market’s `base token` Note that in practice, we need only store the market IMF and token IMF. The leverage is implied from this value. Then we have the user’s IMF. IMFuser\=∑PON⋅IMFbase∑PON\\text{IMF}\_{user} = \\frac{\\sum \\text{PON} \\cdot \\text{IMF}\_\\text{base}}{\\sum \\text{PON}} IMFuser​\=∑PON∑PON⋅IMFbase​​ Note that for tokens, IMFbase\\text{IMF}\_\\text{base}IMFbase​ is only defined if the token is borrowable. For OMF\>IMF\\text{OMF} > \\text{IMF}OMF\>IMF condition we can observe that sides have same denominator, which allows to simplify it to: min⁡{AV,TV}\>∑PON⋅IMFbase\\min\\big\\{\\text{AV}, \\text{TV} \\big\\} > \\sum \\text{PON} \\cdot \\text{IMF}\_\\text{base} min{AV,TV}\>∑PON⋅IMFbase​ Let use AB\=min⁡{AV,TV}AB = \\min\\{\\text{AV}, \\text{TV}\\}AB\=min{AV,TV}. #### cancel margin fraction CMFCMFCMF[](https://docs.01.xyz/margins/n1#cancel-margin-fraction-cmf) The OMFOMFOMF below which open orders that extend the user’s current position are cancelled. Defined similarly to IMF. CMFbase\=58IMFbase(perp)CMFbase\=IMFbase(spot)\\begin{align\*} \\text{CMF}\_\\text{base} &= \\frac{5}{8} \\text{IMF}\_\\text{base} & (\\text{perp}) \\\\ \\text{CMF}\_\\text{base} &= \\text{IMF}\_\\text{base} & (\\text{spot}) \\end{align\*} CMFbase​CMFbase​​\=85​IMFbase​\=IMFbase​​(perp)(spot)​ CMFuser\=∑PON⋅CMFbase∑PON\\text{CMF}\_{user} = \\frac{\\sum \\text{PON} \\cdot \\text{CMF}\_\\text{base}}{\\sum \\text{PON}} CMFuser​\=∑PON∑PON⋅CMFbase​​ #### maintenance margin fraction MMFMMFMMF[](https://docs.01.xyz/margins/n1#maintenance-margin-fraction-mmf) The MFMFMF below which the user’s positions are closed and borrows unlent until the MFMFMF is back above the MMFMMFMMF . MMFbase\=12IMFbase(perp)MMFbase\=1.03weight−1(spot)\\begin{align\*} \\text{MMF}\_\\text{base} &= \\frac{1}{2} \\text{IMF}\_\\text{base} & (\\text{perp}) \\\\ \\text{MMF}\_\\text{base} &= \\frac{1.03}{\\text{weight}} - 1 & (\\text{spot}) \\end{align\*} MMFbase​MMFbase​​\=21​IMFbase​\=weight1.03​−1​(perp)(spot)​ MMFuser\=∑PON⋅MMFbase∑PON\\text{MMF}\_{user} = \\frac{\\sum \\text{PON} \\cdot \\text{MMF}\_\\text{base}}{\\sum \\text{PON}} MMFuser​\=∑PON∑PON⋅MMFbase​​ ### Liquidations[](https://docs.01.xyz/margins/n1#liquidations) Notice that, by definition, OMF≤MFMMF\=ideal cancellation fractioncancellation fee∗ideal cancellation size,real cancellation fraction= \\text{ideal cancellation fraction} \\\\ \\text{cancellation fee} \* \\text{ideal cancellation size}, & \\text{real cancellation fraction} < \\text{ideal cancellation fraction} \\end{cases} liquidator reward\={cancellation fee∗real cancellation size,cancellation fee∗ideal cancellation size,​real cancellation fraction\>=ideal cancellation fractionreal cancellation fraction0Wdebt\=0\\text{W}\_{penalized} = \\begin{cases} W \\cdot \\frac{\\text{escrow}-\\text{debt}}{\\text{escrow}} & debt > 0 \\\\ W & debt = 0 \\end{cases}Wpenalized​\={W⋅escrowescrow−debt​W​debt\>0debt\=0​ Difference is used to reduce debtdebtdebt ### Price bands[](https://docs.01.xyz/margins/n1#price-bands) Reject place order requests with a limit price too far from the index price for the perpetual market to band B to reduce price manipulation on small markets. plow index⋅(1−B)p\_\\text{low index} \\cdot (1 - B)plow index​⋅(1−B) for smallest price and phigh index⋅(1−B)p\_\\text{high index} \\cdot (1 - B)phigh index​⋅(1−B) for highest price possible, and B\=0.1B=0.1B\=0.1. Last updated on January 16, 2026 [Account Margins](https://docs.01.xyz/margins/01 "Account Margins") [Common Errors](https://docs.01.xyz/common-errors "Common Errors") --- # 01 [Skip to Content](https://docs.01.xyz/getting-started#nextra-skip-nav) 404 === This page could not be found. ----------------------------- --- # 01 [Skip to Content](https://docs.01.xyz/reference/action#nextra-skip-nav) 404 === This page could not be found. ----------------------------- --- # 01 [Skip to Content](https://docs.01.xyz/reference/endpoints#nextra-skip-nav) 404 === This page could not be found. ----------------------------- ---