NAV

Best Practice

This guide provides instructions for using the ApeX Omni API and is designed to help developers integrate quickly and securely.

Guide

Preparation

To use the API, please first log in to the web portal, apply for an API key, and configure the necessary permissions.
Afterward, you can proceed with development and trading according to the details in this document.

If you are familiar with zkLink, you may also use their SDK to obtain seeds and l2Key.
However, this requires access to your private key, so please exercise caution.

Once created, make sure to securely store the following information:

API Types

APIs are divided into two main categories:

Public APIs - Used to obtain configuration and market data. - Public requests do not require authentication.

Private APIs - Used for order management and account management. - Each private request must use standardized authentication. - APIKey credentials are required for all private requests.

Rate Limits

This section outlines API rate limits:

REST API Rules - Some endpoints are limited by UID. - Some endpoints are limited by IP. - Specific rules are noted in the documentation for each endpoint.

For details, please see Rate Limits.

Market-data

WebSocket Overview

WebSocket is a new protocol in HTML5. It enables full-duplex communication between client and server, allowing fast bidirectional data transfer. A connection can be established through a simple handshake, and the server can actively push information to the client based on business rules. Its advantages include:

Domain WebSocket API Recommended Usage
Public wss://quote.omni.apex.exchange/realtime_public Main domain, public
Private wss://quote.omni.apex.exchange/realtime_private Main domain, private

Subscribing to Market Data

Subscribe to topics via WebSocket to receive real-time market data updates.

Heartbeat Example

// client -> server
{"op":"ping"}

// server -> client
{"op":"pong","ts":1699999999999}

Topic Categories

Message Structure and Types

{
  "channel":"orderBook200",
  "symbol":"BTC-USDT",
  "type":"snapshot | delta",
  "ts":1699999999999,
  "data":{ ... }
}

Type Explanation

Subscribe / Unsubscribe

// Subscribe
{"op":"subscribe","args":[ "<topic-1>", "<topic-2>" ]}

// Unsubscribe
{"op":"unsubscribe","args":[ "<topic-1>", "<topic-2>" ]}

Public Topics

Description Arg Format Key Params Notes
Trade recentlyTrade.H.{symbol} symbol High-frequency (H) trades
K-line candle.{interval}.{symbol} interval, symbol Intervals: 1 5 15 30 60 120 240 360 720 D W M
Ticker instrumentInfo.H.{symbol} symbol Single trading pair
All Tickers instrumentInfo.all - All trading pairs
Depth Snapshot/Delta orderBook{limit}.H.{symbol} limit, symbol limit ∈ {25,200}; initial snapshot, then deltas

Example Subscription Request

{"op":"subscribe","args":[
  "recentlyTrade.H.BTC-USDT",
  "candle.1.BTC-USDT",
  "instrumentInfo.H.BTC-USDT",
  "orderBook200.H.BTC-USDT"
]}

Depth: The first message is a full snapshot, followed by incremental updates. Apply updates in sequence by timestamp or ID, detect packet loss, and rebuild snapshot if needed.

Private Topics

Subscribe / Unsubscribe Examples

// Subscribe Example
{"op":"subscribe","args":[ "ws_zk_accounts_v3" ]}

// Unsubscribe Example
{"op":"unsubscribe","args":[ "ws_zk_accounts_v3" ]}

Delta Message Structure Explanation

When there is an update for a subscribed topic, the server sends a delta message.
This message only includes fields that have changed. Fields with no changes will not be included.

Field Description

Example Delta Message

{
  "type": "delta",
  "timestamp": 1647502440973,
  "topic": "ws_zk_accounts_v3",
  "contents": {
    "fills": [ ... ],
    "positions": [ ... ],
    "orders": [ ... ],
    "accounts": [ ... ],
    "transfers": [ ... ]
  }
}

Private topics only return the fields that have changed.
If there are no changes, those fields will not appear in the response.

Recommendations and Error Handling

Order Management

Subscribing to Order Channel

Before placing an order, users should first subscribe to the order channel via WebSocket. This enables monitoring of order statuses (e.g., pending, filled) and allows responsive actions (e.g., placing a new order upon fill).

The order channel supports subscriptions from multiple dimensions. Users can access order data after connecting to and authenticating on the private WebSocket.

Placing an Order

clientOrderId uniqueness check only applies to all open orders, but we still recommend using a unique clientOrderId for all orders for easier troubleshooting.

Once subscribed to the order channel, users are ready to receive incremental updates for order placement.

REST API

Users can place orders via the following REST API. The server returns the order id and clientOrderId after receiving the request.

POST /v3/order — See order API details

Market Orders

In ApeX, when placing a market order, the price field must be provided.
This is different from traditional CEXs (centralized exchanges), which usually do not require a price for market orders. ApeX needs price for zkLink signature purposes.

Where to get the price:

Checking Order Status

After placing an order, if the API returns no error ("code": "200"), users will receive a PENDING status update for the order via WebSocket. If the order is accepted, it will change to OPEN.

Once an order is fully filled, users will receive an update via WebSocket with the order status FILLED, along with other fill-related fields.

For order types like IOC (Immediate-Or-Cancel), FOK (Fill-Or-Kill), and Post Only, the order may be rejected by the matching engine. In that case, the user will receive a could_not_fill status.

Orders may also be canceled by the system for various reasons, such as market orders not executing immediately or L2 verification failure.
Refer to the Cancelation Reason for specific causes:

Order Cancelation Reason {
  "UNKNOWN_ORDER_CANCEL_REASON" // Unknown reason
  "EXPIRED"                     // Order expired
  "USER_CANCELED"               // User manually canceled
  "COULD_NOT_FILL"              // Could not be filled (FOK/IOC/Post-only condition not met)
  "REDUCE_ONLY_CANCELED"        // Reduce-only order couldn't execute
  "LIQUIDATE_CANCELED"          // Order canceled due to liquidation
  "INTERNAL_FAILED"             // Internal failure (e.g. matching or L2 verification failed)
}

An order’s final state is either canceled or filled.

Possible order statuses:

Canceling Orders

Users can cancel orders via a REST request in a similar way.

POST /v3/delete-order

Users should receive a success response via REST/WebSocket. Only when the order update via WebSocket shows canceled, the cancelation is confirmed.

Orders that are fully filled or already canceled cannot be canceled again.

A successful response only indicates that the request has been received; users should rely on the WebSocket update to confirm the cancellation.

Order Timestamps

There are multiple timestamps in the order data for tracking status and latency.

Pagination

ApeX provides pagination to help users navigate large datasets. Parameters:

Parameter Type Required Description
beginTimeInclusive String No Start time
endTimeExclusive String No End time
limit String No Max number of results (up to 100), default 100
page String No Page numbers start from 0

Trading Account and Positions Information

Account

The account API provides real-time status of user assets, including balances, frozen funds, and available funds.
Users can obtain real-time updates via WebSocket subscriptions, or pull snapshot data via REST API.

WebSocket Subscription

Subscribe to account-related topics to receive real-time updates on balances and positions.

Subscription Example:

{"op":"subscribe","args":["ws_zk_accounts_v3"]}


Example Response: See Subscription Success Push Data

REST API

Users can also query account information via REST API.

Request:

GET /v3/account

Example Response: See GET Account Data & Positions

Wallets

To obtain both spot and contract asset information, you can use the account balance endpoint:

Example Response:

"spotWallets": [
  {
    "userId": "12137",
    "accountId": "350",
    "subAccountId": "350",
    "balance": "1191781.577364",
    "tokenId": "1",
    "pendingDepositAmount": "0.000000",
    "pendingWithdrawAmount": "0.000000",
    "pendingTransferOutAmount": "0.000000",
    "pendingTransferInAmount": "0.000000",
    "createdAt": 1690365436385,
    "updatedAt": 1690365436385
  }
],
"contractWallets": [
  {
    "userId": "121372485302",
    "accountId": "350522584833",
    "balance": "1191778.137753",
    "asset": "USDT",
    "pendingDepositAmount": "0.000000",
    "pendingWithdrawAmount": "0.000000",
    "pendingTransferOutAmount": "0.000000",
    "pendingTransferInAmount": "0.000000"
  }
]

Positions

Position data is returned under the positions field, showing current holdings across all trading pairs.

Key fields:

Example:

"positions": [
  {
    "symbol": "BTC-USDT",
    "side": "LONG",
    "size": "0.000",
    "entryPrice": "0.00",
    "exitPrice": "",
    "fee": "0.000000",
    "fundingFee": "0.000000",
    "customInitialMarginRate": "0"
  }
]

Available and TotalEquity

To retrieve account financial data such as available balance, total equity value, and margin details, you can use the following endpoint:

GET /v3/account-balance

This endpoint provides the most up-to-date account information and is recommended for building asset monitoring and account overview features.