Introduction
Welcome to the IDEX v4 API developer documentation. IDEX provides a REST API for public market data, authenticated user data, and trading. IDEX also offers a WebSocket API for real-time access to market and user data.
Changelog
2024-04-26: Initial draft.
Concepts
XCHAIN
IDEX operates on XCHAIN, an advanced, application-specific layer 2 blockchain (appchain) based on Arbitrum Orbit. XCHAIN provides high throughput, low latency, and low costs, and inherits its security directly from Ethereum. These properties allow IDEX to provide a trading experience equivalent to a centralized exchange, with instant settlement and no gas costs, along with the fund security of a decentralized exchange.
As an EVM-compatible blockchain, XCHAIN supports the standard wallets, explorers, and tooling of Ethereum and uses Ether as its gas token. IDEX integrates with Stargate v2 to provide seamless, free or low cost, single-transaction cross-chain deposits and withdrawals supporting a range of blockchains.
XCHAIN Mainnet Details
Name: XCHAIN
RPC URL: https://xchain-rpc.idex.io/
Chain ID: 94524
Currency Symbol: ETH
Block Explorer URL: https://xchain-explorer.idex.io/
XCHAIN Testnet Details
Name: XCHAIN Testnet
RPC URL: https://xchain-testnet-rpc.idex.io/
Chain ID: 64002
Currency Symbol: ETH
Block Explorer URL: https://xchain-testnet-explorer.idex.io/
IDEX operates a sandbox version of the exchange on XCHAIN Testnet for development and testing purposes.
Fund Custody
As a high-performance, non-custodial exchange, IDEX does not take custody of funds before making them available to trade. Unlike centralized exchanges, where funds are first deposited to a wallet controlled by the exchange, IDEX relies on a smart contract to hold user funds, track user balances, and settle trades. The user experience is similar to a centralized exchange – funds must first be deposited to the IDEX smart contract before trading – but funds are never blindly entrusted to a third party. IDEX does not control user funds, funds can never change hands without authorization from the user’s wallet, and funds can always be withdrawn from the contract, even in the case that IDEX ceases to operate. Most importantly, these properties are independently verifiable by the community.
Matching Engine
IDEX employs a high-performance central limit order book design that continuously matches user orders on a price-time priority basis. Similar to matching engines employed by traditional, non-crypto exchanges, limit orders are filled at the specified price or better with no risk of order collisions or trade failures. As a result, the user experience is similar to a high-performance, centralized exchange.
Order Types
IDEX’s matching engine supports a wide range of order types.
Market
A market order is an order to buy or sell a quantity of an asset at the prevailing prices. Market orders execute immediately, never rest on an order book, and only take liquidity from an order book. For safety, market orders can only execute within a market’s marketOrderExecutionPriceLimit
percent of the index price.
Limit
A limit order is an order to buy or sell a quantity of an asset at or better than a specified price. Limit orders require specifying both a quantity in base terms and a price in quote terms. The matching engine only fills limit buy orders up to the specified quantity at or lower than the specified price; it fills limit sell orders up to the specified quantity at or higher than the specified price. Limit orders specified with a price that crosses the spread are immediately matched and take liquidity from an order book. Any portion of a limit order that cannot be matched immediately is added to the order book, subject to time in force rules and a market’s makerOrderMinimum
. For safety, limit orders can only be priced within a market’s limitOrderExecutionPriceLimit
percent of the index price.
Stop Loss Market
A market order that is only processed by the matching engine when the index price or most recent fill in a market crosses the specified stop price. See Stop Mechanics for the specific trigger criteria.
Stop Loss Limit
A limit order that is only processed by the matching engine when the index price or most recent fill in a market crosses the specified stop price. See Stop Mechanics for the specific trigger criteria.
Take Profit Market
A market order that is only processed by the matching engine when the index price or most recent fill in a market crosses the specified stop price. See Stop Mechanics for the specific trigger criteria.
Take Profit Limit
A limit order that is only processed by the matching engine when the index price or most recent fill in a market crosses the specified stop price. See Stop Mechanics for the specific trigger criteria.
Stop Mechanics
Stop Loss and Take Profit orders are similar, but have opposite stop trigger criteria.
Type | Side | Trigger Condition |
---|---|---|
Stop Loss | Sell | Index or last fill price <= stop price |
Take Profit | Sell | Index or last fill price >= stop price |
Stop Loss | Buy | Index or last fill price >= stop price |
Take Profit | Buy | Index or last fill price <= stop price |
Stop Loss and Take Profit orders do not appear in any public data until the stop is triggered and the order is added to the order book. Importantly, these orders are not guaranteed to execute immediately when the stop is triggered. Like all other orders, they are processed with price-time priority where the time of the order is the stop trigger time. Funds for Stop Loss Limit or Take Profit Limit orders are held immediately at the time of placement, not when the stop is triggered. Funds for Stop Loss Market and Take Profit Market orders are never held.
Time In Force
Time in force policies specify the behavior of limit orders upon execution.
Good-Til-Canceled (GTC): Under GTC rules, a limit order that is resting on the books remains on the books until canceled. This is the default policy if no time in force option is specified.
Good-Til-Crossing (GTX): GTX limit orders, sometimes referred to as limit maker or post-only orders, only add liquidity to the order book. On execution, if any part of a GTX limit order crosses the spread and matches a resting order, the entire GTX order is canceled without generating any fills.
Immediate-Or-Cancel (IOC): Limit orders with an IOC time in force only take liquidity from the order book, and never become a resting order on the book. On execution, any portion of an IOC limit order that matches resting orders is filled, and the rest of the order is canceled.
Fill-Or-Kill (FOK): Similar to IOC orders, FOK limit orders only take liquidity from an order book. The entire specified quantity must be matched immediately, however, or the order is rejected without generating any fills. FOK orders must specify the CN self-trade prevention policy to be accepted by the matching engine.
Self-Trade Prevention
IDEX’s matching engine includes logic to prevent self-trading. Two orders from the same API user or wallet cannot fill each other and on match are subject to the taker order’s specified self-trade prevention policy.
Decrement And Cancel (DC): Cancel the smaller order and decrement the larger order quantity by the smaller order quantity. Cancel both orders if they have the same open quantities. This is the default policy if no self-trade prevention option is specified.
Cancel Oldest (CO): Cancel the older, resting order from the order book and continue to execute the newer, taker order.
Cancel Newest (CN): Cancel the newer, taker order and leave the older, resting order on the order book.
Cancel Both (CB): Cancel both orders.
Order States & Lifecycle
Orders take on various states throughout the order execution lifecycle.
active: Stop limit or stop market order in force but not yet triggered or listed on an order book
open: Limit order resting on an order book without any fills
partiallyFilled: Limit order resting on an order book with fills but with remaining open quantity; market order partially filled
filled: Limit order completely filled and no longer on an order book; market order completely filled
canceled: Limit order canceled prior to being completely filled but may be partially filled; unfilled market order; may be the result of a self-trade prevention cancellation
rejected: Order rejected by the matching engine without generating fills
notFound: Order not found during an order cancellation request
Order state is included in all order endpoint responses. Orders are not guaranteed to enter the open
state before reporting as another state. For example, a limit order that is completely filled on execution first reports in the filled
state in endpoint responses.
Holds
IDEX reserves funds associated with a limit order while the order is resting on an order book. The matching engine holds quantity * price
of the wallet’s total account value at the maximum leverage of the market. For example, if a market has an initialMarginFraction
of 0.1, implying 10x maximum leverage, a resting order where quantity * price
is 2,000 USD holds 200 USD of the total account value. Canceling an open limit order releases the funds associated with the order. Because total account value is computed based on index prices for wallets with open positions, index price fluctuations may result in insufficient total account value to support all open limit orders. In this case, a wallet’s oldest resting limit orders are automatically canceled until it has sufficient value for the remaining order holds.
No funds are held for market orders or untriggered stop orders of any kind.
Held collateral and available collateral are reported by the Get Wallets endpoint.
Wallets are limited to 250 open orders regardless of available collateral.
Fees
IDEX collects several types of fees: maker trade fees, taker trade fees, and withdrawal fees.
Maker & Taker Orders
Trade fees are split into maker and taker fees, assessed when an order execution results in a fill, and deducted from each wallet's USD quote balance. Trade fees can be negative for promotional purposes, resulting in a credit to a wallet's quote balance. Default fee rates at launch:
Type | Fee |
---|---|
Maker Trade Fee | 0.01% |
Taker Trade Fee | 0.05% |
Fee Priority
IDEX defines exchange-wide default trade fee rates, market-specific trade fee rates, and wallet-specific trade fee rates. Markets may be subject to promotional periods of lower rates, and wallets have several opportunities to lower trade fees via promotional programs. IDEX applies the lowest trade fees available between the exchange, market, and wallet scopes.
Withdrawal Fees
IDEX collects fees on withdrawals to cover gas and bridge fees on behalf of the withdrawing wallet. Unlike deposits, withdrawals are initiated through the REST API. IDEX dispatches the resulting transaction to return funds to the wallet and thus pays gas. Bridged withdrawal fees can be dynamic; the Get Gas Fees endpoint provides up-to-date estimates of fees. Users authorize a maximum fee as part of the Withdraw Funds request to protect against rate fluctuations. Withdrawal fees are deducted from the withdrawn quantity.
Position Minimums
IDEX defines a minimum position size for each market in base terms, see Get Markets minimumPositionSize
. To conserve resources, positions below this quantity are subject to automatic closure at the index price 7 days after falling below the minimum. Positions below the minimum may be closed at any time via market or limit orders using a market’s takerOrderMinimum
quantity with reduceOnly
set to true
.
Perpetual Contracts
IDEX v4 exclusively offers cross-margined perpetual futures contracts with leverage for trading.
Collateral & Margin
IDEX uses USDC as its primary collateral asset, and only supports USDC for deposits and withdrawals. As a cross-margined exchange, all open positions contribute to a wallet’s total account value. No distinction is made between realized and unrealized PnL for the purposes of valuation or margin requirements.
Margin requirements are defined on a per-market basis by several fields:
- Initial Margin Fraction: Margin requirement to open a position expressed as a fraction.
- Maintenance Margin Fraction: Margin requirement to prevent liquidation expressed as a fraction.
- Base Position Size: Maximum position size available under the Initial Margin Fraction.
- Incremental Position Size & Incremental Initial Margin Fraction: If a position exceeds Base Position Size, each step of Incremental Position Size increases the Initial Margin Fraction by Incremental Initial Margin Fraction.
For safety, larger positions require more collateral and offer lower leverage. Several key position and wallet parameters derive from these leverage parameters. For a single position:
Initial Margin Requirement = Initial Margin Fraction × Absolute Position Notional Value
Maintenance Margin Requirement = Maintenance Margin Fraction × Absolute Position Notional Value
Absolute Position Notional Value = Index Price × ABS(Position Quantity)
Position quantities are positive for long positions and negative for short positions, and a wallet’s quote balance may be negative. Importantly, all margin calculations use index prices for stability. For a wallet:
Total Initial Margin Requirement = Market 1 Initial Margin Requirement + Market 2 Initial Margin Requirement + …
Total Maintenance Margin Requirement = Market 1 Maintenance Margin Requirement + Market 2 Maintenance Margin Requirement + …
For all markets in which the wallet has open positions. Finally:
Equity (Total Account Value) = Quote Balance + Market 1 Positional Notional Value + Market 2 Position Notional Value + …
Margin Ratio = Total Maintenance Margin Requirement / Equity
Leverage = Total Absolute Position Notional Value / Equity
If margin ratio rises above 1, a wallet may be subject to liquidation. Several additional values determine order placement, withdrawal, and other limits:
Free Collateral = Equity - Total Initial Margin Requirement
Held Collateral = Free Collateral committed to open limit orders
Available Collateral = Free Collateral available for order placement or withdrawal
Liquidations & ADL
Wallet total account value, or equity, is determined by index pricing that changes independently of position changes. When a wallet’s equity falls below its maintenance margin requirement, the wallet is eligible for liquidation. Liquidation closes all open positions at the close price, resulting in zero quote balance and zero equity.
Close Price = Index Price ± Close Price Adjustment
Close Price Adjustment = Index Price × Maintenance Margin Fraction × Equity / Total Maintenance Margin Requirement
The close price adjustment is subtracted for long positions and added for short positions. Profits and losses resulting from liquidations are absorbed by the insurance fund.
In the case that the insurance fund cannot absorb a liquidation, the system proceeds with automatic deleveraging, or ADL. During ADL, positions of a wallet that falls below its maintenance margin requirement are closed directly against opposing positions at the close price. ADL results in the same zero collateral and zero equity state for the liquidated wallet, and forcibly realizes unrealized PnL for counterparty wallets. While avoiding ADL is a priority, it is a necessary last resort to protect the solvency of the system.
Counterparty wallets are selected at the time of ADL according to position ADL score. The ADL score favors positions with high leverage and unrealized profit.
ADL Score = Margin Ratio × PnL Percent
Margin Ratio = Total Maintenance Margin Requirement / Equity
PnL Percent = Position Unrealized PnL / MAX(1, Equity - Total Unrealized PnL)
Position ADL risk is reported by the adlQuintile
field of the Get Positions response with 1 indicating low risk and 5 indicating high risk. This value indicates the estimated quintile of ADL counterparty selection at the index price. Multiple counterparty positions may be selected to liquidate a single position.
Liquidated wallets may deposit funds and resume trading immediately.
Funding Payments
IDEX perpetual futures contracts trade independently of the current spot price of the underlying assets. That is, perpetuals markets have their own order books that may diverge from the order books of high-volume spot exchanges, a phenomenon exacerbated by the presence of leverage. Funding payments provide an incentive for traders to keep the order book pricing of a perpetual contract in line with spot prices.
Funding payments require that open positions that are advantageous by the order book price relative to the index price pay a fee to the opposite positions on a periodic basis. For example, if the order book price of a market is $110 but the index price is $100, open long positions pay open short positions in the next funding period. Similarly, if the order book price of a market were $90 with the same index price, open shorts pay longs. Funding payments thus incentivize traders to take the unpopular position, drawing the order book price back to the index price.
Funding payments are exchanged directly between long and short positions every 8 hours at 00:00 UTC, 08:00 UTC, and 16:00 UTC. Funding payments are calculated by:
Funding Payment = -1 × Funding Rate × Position Quantity × Index Price
Positive funding rates indicate longs pay shorts, negative rates indicate shorts pay longs. The funding rate comprises two parts: the premium index and the interest rate. Premium indexes within 0.05% of the interest rate are clamped to just the interest rate. Funding rates are then clamped to 75% of a market’s maintenance margin fraction.
Funding Rate = Premium Index + CLAMP(Interest Rate − Premium Index, -0.05%, 0.05%)
The interest component represents the daily quote asset yield, set at 0.03%. Because funding payments are made 3 times per day, the interest rate value per payment is 0.01%.
The premium index represents the difference between the IDEX order book and the index price for a market.
Premium Index = (MAX(0, Impact Bid Price - Index Price) - MAX(0, Index Price - Impact Ask Price)) / (Index Price × 3)
The impact price indicates the average execution price of a predetermined quote quantity through the IDEX order book at a point in time. IDEX uses an impact quantity of 250 USD; this value is then divided by the market’s initial margin fraction to set the impact notional value. For example, a market with an initial margin fraction of 0.1 uses an impact notional value of 2500 USD.
Each market’s order book is sampled once per minute at a random point in the minute. The impact bid price and impact ask price are the average execution prices of market selling and buying the impact notional value through the sampled order book. The impact price samples are then linearly time-weight averaged over the trailing 8 hours to establish the impact bid price and impact ask price used in the premium index formula.
IDEX uses a realization period of 24 hours, indicating that the full difference between impact price and index price is paid between long and short positions every 24 hours. Because payments are made every 8 hours, the effective premium index is thus divided by 3.
Index Prices
Index prices represent the fair value of the underlying assets of perpetual futures markets, such as BTC and ETH. Index prices are collected from a variety of reliable price sources, normalized to exclude outliers and spurious data, and updated with high frequency and low latency.
IDEX uses index prices rather than order book prices for all margin calculations. As a result, index pricing determines:
- Position notional value and margin requirement and by extension wallet value and margin requirement
- Whether a wallet has sufficient funds to open positions
- When wallets are liquidated or deleveraged
- Whether to authorize withdrawals and transfers
- Funding rates for funding payments
The use of index prices reduces the impact of short term order book price movement on exchange operations.
IDEX sources index prices from Pyth Network with 2 second update frequency. Pyth prices are cryptographically verified on chain by the exchange smart contract.
IDEX also operates a first-party index price collection service for redundancy. If Pyth data is unavailable or stale, IDEX automatically falls back to internal index pricing data. IDEX sources prices from high-volume spot exchanges, uses the median of best ask, best bid, and last trade price as the source price, discards any data points greater than 10% away from the median of sources, and computes the weighted mean of the remaining values. Markets quoted in anything other than USD, for example USDT, are corrected for the quote value. These values are signed in hardware at collection and are verified on chain by the exchange smart contract.
Internal Index Price Sources and Weights
USDT-USD
Bitfinex | UST-USD | 8.9% |
Bitstamp | USDT-USD | 3.9% |
Coinbase | USDT-USD | 51.8% |
Kraken | USDT-USD | 35.4% |
BTC-USD
Binance | BTC-USDT | 45.6% |
Bybit | BTC-USDT | 11.6% |
Coinbase | BTC-USD | 16.1% |
Gateio | BTC-USDT | 9.2% |
Kraken | BTC-USD | 3.6% |
OKX | BTC-USDT | 13.9% |
ETH-USD
Binance | ETH-USDT | 41.9% |
Bybit | ETH-USDT | 13.78% |
Coinbase | ETH-USD | 12.71% |
Gateio | ETH-USDT | 11.37% |
Kraken | ETH-USD | 3.45% |
OKX | ETH-USDT | 16.79% |
SOL-USD
Binance | SOL-USDT | 55% |
Bybit | SOL-USDT | 8.92% |
Coinbase | SOL-USD | 15.41% |
Gateio | SOL-USDT | 3.49% |
Kraken | SOL-USD | 7% |
OKX | SOL-USDT | 10.18% |
Resources
Sandbox
IDEX operates a sandbox service that is a full instance of the IDEX platform running on XCHAIN testnet. The sandbox enables clients to develop and test software for the API without risking funds.
URLs & Contract Addresses
- Web Client: https://exchange-sandbox.idex.io/
- REST API: https://api-sandbox.idex.io/
- WebSocket API: wss://websocket-sandbox.idex.io/v4
- Exchange Contract (XCHAIN Testnet): 0xBB9A5455869e99652D13Cd0aE1E45dc3A2e9914B
IDEX’s data centers are in the AWS Asia Pacific (Tokyo) ap-northeast-1
region.
Credentials
Clients may sign up to generate sandbox API keys via the sandbox web client.
Collateral
Unlocking a wallet via the sandbox web client automatically deposits testnet USDC for testing and development purposes.
Client Libraries & SDKs
IDEX maintains an official TypeScript / JavaScript SDK, supporting REST and WebSocket APIs as well as real-time order books. Contract ABIs are also available in the SDK repo.
IDEX smart contracts, documentation and tests will also be available soon.
Bug Bounty
The IDEX API is covered by a bug bounty via Immunefi. Updates for the IDEX v4 API are coming soon.
Support
Support is available via the IDEX #developers
Discord channel or via [email protected].
REST API Interaction
URL & Contract Addresses
REST API: https://api.idex.io/
Exchange Contract (XCHAIN): 0x08ea6C351d08fAc8E177267898612A5fc6D92349
Sandbox REST API: https://api-sandbox.idex.io/
Sandbox Exchange Contract (XCHAIN Testnet): 0xBB9A5455869e99652D13Cd0aE1E45dc3A2e9914B
IDEX’s data centers are in the AWS Asia Pacific (Tokyo) ap-northeast-1
region. A sandbox environment is also available for development and testing.
Requests
All requests and responses use the application/json
content type with UTF-8 encoding. GET request parameters must be supplied in the query string, while POST and DELETE request parameters must be supplied as a JSON object in the body.
Successful requests return a 200
HTTP status code, while requests that generate errors return 4xx
or 5xx
status codes.
Error response body:
{
"code": "<Machine-readable short code>",
"message": "<Human-readable error message>"
}
Error responses include a machine-readable error short code and longer human-readable error message in the body. As a result, it is important to configure the requesting http library to provide message bodies for error responses. See Error Codes for a comprehensive list of error codes and descriptions.
Data Types
Times
Time parameters in API requests must be represented in Unix epoch time in either seconds or milliseconds. Times included in API responses are returned in Unix epoch time in milliseconds.
Numbers & Precision
IDEX normalizes all precision to 8 decimals, and price and quantity values in API requests must be fully zero-padded strings. For example:
- 100,000,000 Gwei of ETH (ie, 0.1 ETH) is represented as the string
"0.10000000"
. - 250.05 USDC is represented as the string
"250.05000000"
.
Price and quantity values included in API responses are returned in the same string format. Expressing values in fully zero-padded strings ensures that numeric values are always represented consistently for authentication signature verification.
Price and quantity values in API responses are exact and should not be treated as floating point numbers.
IDs
Resource identifiers are UUIDs. API requests may encode ids with or without hyphens.
Client IDs
Order requests may optionally include a client-specified id. Client ids are not public and are only included in authorized responses. Orders may also be queried by client id. Client ids are scoped to a wallet, meaning different wallets can use the same client id to refer to different orders. Client ids are interpreted as UTF-8 encoded strings with a maximum length of 40 bytes.
Sequence Numbers
IDEX provides two types of sequence numbers to synchronize data between the REST and WebSocket APIs.
Order book update sequence numbers: Changes to an order book are sequential for a market. Order book update sequence numbers allow API clients to reliably construct local copies of an order book.
Fill sequence numbers: Fills are sequential for a market independent of order book updates. Fill sequence numbers precisely align periodic data points, such as tickers and candles, to trade history. Non-order-book activity, such as liquidations and ADL actions, are not reported in tickers and candles and do not increment fill sequence numbers.
Pagination
Pagination is specified by several standard request parameters.
start: The earliest (oldest) timestamp of an object to include in the response. This value is inclusive, meaning objects with timestamps that exactly match
start
are included in the response.end: The latest (newest) timestamp of an object to include the response, inclusive.
end
must be a later timestamp than start.limit: The total number of objects to include in the response.
limit
is generally capped at 1,000 for all endpoints and defaults to 50 unless bothstart
andend
are present.fromId:
fromId
specifies id of the earliest (oldest) object to include in the response.
Any combination of start
, end
, limit
and fromId
are valid, but certain values take precedence over others. For example, if start
and end
are specified but not limit
, the response will include objects starting at start
and ending either at end
or at 1,000 objects. Specifying end
alone returns 50 objects closest to, but earlier (older) than end
. Specifying none of the pagination parameters returns the 50 most recent objects. fromId
takes precedence over start.
Response data is returned in ascending time order, with oldest objects first and newest objects last.
Authentication
API Keys
API keys may be generated via the IDEX API keys page and are only valid for requests by the generating API account. They include an accompanying secret value that is used to sign requests to some endpoints.
API keys have three access scopes which are set independently via the API keys page.
Read: Authorized for all read endpoints. All API keys have read access.
Trade: Authorized for trade endpoints, specifically creating and canceling orders.
Withdraw: Authorized for withdrawals.
Endpoint Security
Endpoints are protected by three security policies.
Public: No access restrictions, available to the public without credentials but including an API key with requests increases rate limits. Exchange and market data endpoints are public.
User Data: Requests to user data endpoints require a nonce, API key and HMAC signature for authentication.
Trade: Requests to trade and withdraw endpoints require a nonce, API key, HMAC signature and wallet signature for authentication.
Request Structure & HMAC Signature
To create the HMAC signature for GET requests, hash the request query string.
const axios = require("axios");
const crypto = require("crypto");
const uuid = require('uuid');
let params = {
nonce: uuid.v1(),
wallet: "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
};
// Important: URL encode parameters as a query string
let stringifiedParams = new URLSearchParams(params).toString();
let signature = crypto.createHmac("sha256", "<API secret>").update(stringifiedParams).digest("hex");
axios.get("https://api.idex.io/v4/fills", {
params: params,
headers: {
"IDEX-API-KEY": "<API key>",
"IDEX-HMAC-SIGNATURE": signature
}
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
$ echo -n "nonce=34b98930-c0a7-11ee-8e2b-79802eed094c&wallet=0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d" | openssl sha256 -hmac "<API secret>"
5998679166d343f3940530d8a8a4d2c776d093bcb426e10232987953a6ab4e1c
$ curl "https://api.idex.io/v4/fills?nonce=34b98930-c0a7-11ee-8e2b-79802eed094c&wallet=0xa71c4aeeaabbbb8d2910f41c2ca3964b81f7310d" \
-H "IDEX-API-Key: <API key>" \
-H "IDEX-HMAC-Signature: 5998679166d343f3940530d8a8a4d2c776d093bcb426e10232987953a6ab4e1c"
To create the HMAC signature for POST or DELETE requests, hash the request body.
const axios = require("axios");
const crypto = require("crypto");
const uuid = require('uuid');
let body = {
"parameters": {
"nonce": uuid.v1(),
"wallet": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"market": "ETH-USD",
"type": "market",
"side": "buy",
"quantity": "10.00000000"
},
"signature": "<Wallet signature>"
};
// Important: use JSON.stringify for parameters in the body
let stringifiedBody = JSON.stringify(body);
let signature = crypto.createHmac("sha256", "<API secret>").update(stringifiedBody).digest("hex");
axios.post("https://api.idex.io/v4/orders", body, {
headers: {
"IDEX-API-Key": "<API key>",
"IDEX-HMAC-Signature": signature,
}
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
$ echo -n '{"parameters":{"nonce":"d1e545b0-b7c8-11ee-ad06-2573b265c15a","wallet":"0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d","market":"ETH-USD","type":"market","side":"buy","quantity":"10.00000000"},"signature":"<Wallet signature>"}' | openssl sha256 -hmac "<API secret>"
ae1e6b454f6aa86bed9f8ef59b635cc948bcd5e5689acbfc1a73cd97ca2dc6c1
$ curl "https://api.idex.io/v4/orders" \
-X POST
-H "IDEX-API-Key: <API key>" \
-H "IDEX-HMAC-Signature: ae1e6b454f6aa86bed9f8ef59b635cc948bcd5e5689acbfc1a73cd97ca2dc6c1" \
-H "Content-Type: application/json" \
-d '{"parameters":{"nonce":"d1e545b0-b7c8-11ee-ad06-2573b265c15a","wallet":"0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d","market":"ETH-USD","type":"market","side":"buy","quantity":"10.00000000"},"signature":"<Wallet signature>"}'
The server-side validation checks the signature on the query string or request body as it is represented in the request.
For endpoints that require or benefit from authentication, the API key and HMAC signature must be included as request headers.
IDEX-API-Key
: API keyIDEX-HMAC-Signature
: Hex-encoded HMAC signature, not case sensitive
The HMAC signature is computed by signing the payload of the request via HMAC-SHA256
. The HMAC signature is computed differently for GET requests, where the payload is in the query string, and POSTs or DELETEs where the payload is in the body.
GET:
HMAC-SHA256(message: query string, key: API secret)
POST, DELETE:
HMAC-SHA256(message: request body, key: API secret)
Wallet Signature
IDEX Production EIP-712 Domain Separator
{
"name": "IDEX",
"version": "4.0.0",
"chainId": 94524,
"verifyingContract": "0x08ea6C351d08fAc8E177267898612A5fc6D92349"
}
IDEX Sandbox EIP-712 Domain Separator
{
"name": "IDEX",
"version": "4.0.0-sandbox",
"chainId": 64002,
"verifyingContract": "0xBB9A5455869e99652D13Cd0aE1E45dc3A2e9914B"
}
To create the wallet signature, encode the request parameters according to the relevant Wallet Signature Parameter Hash scheme.
const ethers = require("ethers");
const uuid = require('uuid');
let order = {
"nonce": uuid.v1(),
"wallet": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"market": "ETH-USD",
"type": 0, // enum value for market orders
"side": 0, // enum value for buy
"quantity": "10.00000000"
};
let domainSeparator = {
"name": "IDEX",
"version": "4.0.0", // "4.0.0-sandbox" for the sandbox environment
"chainId": "<XCHAIN chain ID>",
"verifyingContract": "0x..."
};
let typeData = {
Order: [
{ name: 'nonce', type: 'uint128' },
{ name: 'wallet', type: 'address' },
{ name: 'marketSymbol', type: 'string' },
{ name: 'orderType', type: 'uint8' },
{ name: 'orderSide', type: 'uint8' },
{ name: 'quantity', type: 'string' },
{ name: 'limitPrice', type: 'string' },
{ name: 'triggerPrice', type: 'string' },
{ name: 'triggerType', type: 'uint8' },
{ name: 'callbackRate', type: 'string' },
{ name: 'conditionalOrderId', type: 'uint128' },
{ name: 'isReduceOnly', type: 'bool' },
{ name: 'timeInForce', type: 'uint8' },
{ name: 'selfTradePrevention', type: 'uint8' },
{ name: 'isLiquidationAcquisitionOnly', type: 'bool' },
{ name: 'delegatedPublicKey', type: 'address' },
{ name: 'clientOrderId', type: 'string' }
]
};
// Nonce must be a uint128, not string representation
let nonceAsHexString = `0x${order.nonce.replace(/-/g, '')}`;
let nonceAsUint128 = BigInt.asUintN(128, BigInt(nonceAsHexString));
let zeroString = "0.00000000";
let value = {
"nonce": nonceAsUint128,
"wallet": order.wallet,
"marketSymbol": order.market,
"orderType": order.type,
"orderSide": order.side,
"quantity": order.quantity,
"limitPrice": zeroString,
"triggerPrice": zeroString,
"triggerType": 0, // None
"callbackRate": zeroString,
"conditionalOrderId": 0,
"isReduceOnly": false,
"timeInForce": 0, // gtc
"selfTradePrevention": 0, // dc
"isLiquidationAcquisitionOnly": false,
"delegatedPublicKey": ethers.ZeroAddress,
"clientOrderId": ""
};
new ethers.Wallet("<Wallet private key>").signTypedData(
domainSeparator,
typeData,
value
)
.then((walletSignature) => {
console.log(walletSignature);
});
As a non-custodial exchange, IDEX requires authorization from the funding wallet for placing and canceling orders and withdrawing funds. Specifically, all trade endpoint requests must include a wallet ECDSA signature, in addition to the standard HMAC signature, to be processable by the exchange.
Wallet ECDSA signatures are computed using the funding wallet keypair to sign typed and hashed data conformant to EIP-712. Data type specifications for each endpoint, along with the required domain separator (see sidebar), are documented below. Wallet signatures are included in the body of the request for endpoints that require them.
Associate Wallet Wallet Signature Type Data
Type Identifier: WalletAssociation
Position | Name | Type | Value |
---|---|---|---|
0 | nonce | uint128 | Nonce |
1 | wallet | address | Wallet address |
Create Order Wallet Signature Type Data
Type Identifier: Order
Position | Name | Type | Value |
---|---|---|---|
0 | nonce | uint128 | Nonce |
1 | wallet | address | Wallet address |
2 | marketSymbol | string | Market symbol |
3 | orderType | uint8 | Order type enum value |
4 | orderSide | uint8 | Order side enum value |
5 | quantity | string | Order quantity in base terms |
6 | limitPrice | string | Order price in quote terms, required for all limit orders, "0.00000000" for market orders |
7 | triggerPrice | string | Stop loss or take profit price, "0.00000000" for market and limit orders |
8 | triggerType | uint8 | Price type for trigger price enum value, None if triggerPrice is zero |
9 | callbackRate | string | Unused, always "0.00000000" |
10 | conditionalOrderId | uint128 | Unused, always 0 |
11 | isReduceOnly | bool | Reduce only setting |
12 | timeInForce | uint8 | Order time in force enum value |
13 | selfTradePrevention | uint8 | Order self-trade prevention enum value |
14 | isLiquidationAcquisitionOnly | bool | Unused, always false |
15 | delegatedPublicKey | address | Unused by the public API, always 0x0 |
16 | clientOrderId | string | Client order id or empty string |
Cancel Order Wallet Signature Type Data
Cancel Order requests use different types depending on the request parameters.
Type Identifier: OrderCancellationByWallet
Position | Name | Data | Value |
---|---|---|---|
0 | nonce | uint128 | Nonce |
1 | wallet | address | Wallet address |
2 | delegatedKey | address | Unused by the public API, always 0x0 |
Type Identifier: OrderCancellationByOrderId
Position | Name | Data | Value |
---|---|---|---|
0 | nonce | uint128 | Nonce |
1 | wallet | address | Wallet address |
2 | delegatedKey | address | Unused by the public API, always 0x0 |
3 | orderIds | string[] | Array of orderId s or clientOrderId s to cancel; prefix client-provided ids with client: |
Type Identifier: OrderCancellationByMarketSymbol
Position | Name | Data | Value |
---|---|---|---|
0 | nonce | uint128 | Nonce |
1 | wallet | address | Wallet address |
2 | delegatedKey | address | Unused by the public API, always 0x0 |
3 | marketSymbol | string | Market symbol |
Type Identifier: OrderCancellationByDelegatedKey
Position | Name | Data | Value |
---|---|---|---|
0 | nonce | uint128 | Nonce |
1 | wallet | address | Wallet address |
2 | delegatedKey | address | Unused by the public API, always 0x0 |
3 | orderDelegatedKey | address | Delegated key address |
Withdraw Funds Wallet Signature Type Data
Type Identifier: Withdrawal
Position | Name | Type | Value |
---|---|---|---|
0 | nonce | uint128 | Nonce |
1 | wallet | address | Wallet address |
2 | quantity | string | Withdrawal quantity |
3 | maximumGasFee | string | Maximum gas fee authorized for the withdrawal |
4 | bridgeAdapter | address | Coming soon |
5 | bridgeAdapterPayload | bytes | Coming soon |
Delegated Keys
IDEX v4 introduces a new authorization mechanism with delegated keys. Delegated keys are authorized by a custody wallet to submit order placements and cancellations on its behalf. The web client implements delegated keys in order to provide an experience similar to a centralized exchange, where no manual signing is necessary to trade. Deposits and withdrawals always require custody wallet signatures for security.
Delegated keys enable a number of use cases but are not officially supported by the public API. As a result, there are references to them in creating and canceling orders and signature authentication, but no details about authorization, revocation, and management. Delegated keys may be added to the public API in the future, so please get in touch if they might help your use case.
Wallet to API Account Association
A wallet must be associated with an API account to request private data from endpoints such as Get Orders or Get Fills. Several actions associate a wallet with an API account.
- Unlocking a wallet in the web client while signed in to an API account
- Calling the Associate Wallet endpoint via the REST API
- Withdrawing funds via the REST API
Under the hood, associating a wallet with an API account requires proving that the requester has access to the wallet's private key. The associating actions all include a wallet signature along with the request, satisfying the association requirement. Calling Associate Wallet is often the first step in requesting data from User Data endpoints.
Nonces
Use a standard UUID library to generate version 1 UUID nonces.
const uuid = require('uuid');
uuid.v1();
User data and trade endpoints requests must include a nonce. IDEX uses version 1 UUID nonces, eliminating the need to coordinate nonce increments between multiple agents operating on a single wallet. Version 1 UUIDs encode a timestamp in addition to other unique information, and thus serve both to prevent replay attacks as well as to enforce request timing. As a result, nonces must be generated at the time of a request. Nonces may be supplied with or without hyphens.
Order Nonce Invalidation
const fs = require("fs");
const ethers = require("ethers");
const uuid = require('uuid');
async function invalidateNonce() {
const idexAddress = "<IDEX exchange contract address>";
const txOptions = { gasPrice: ethers.parseUnits("<Gas price in gwei>", "gwei") };
// Connect a wallet to XCHAIN
const provider = new ethers.JsonRpcProvider("<XCHAIN RPC>");
const walletWithProvider = new ethers.Wallet("<Wallet private key>", provider);
// Load contract
const idexAbi = JSON.parse(fs.readFileSync("Exchange_v4.abi.json"));
const idexContract = new ethers.Contract(idexAddress, idexAbi, walletWithProvider);
const nonce = uuid.v1();
// Nonce must be a uint128, not string representation
const nonceAsHexString = `0x${nonce.replace(/-/g, '')}`;
const nonceAsUint128 = BigInt.asUintN(128, BigInt(nonceAsHexString));
console.log("Invalidating order nonce...")
const invalidateNonceTx = await idexContract.invalidateNonce(nonceAsUint128, txOptions);
console.log(`Dispatched invalidate order nonce call ${invalidateNonceTx.hash} awaiting mine...`);
await invalidateNonceTx.wait();
console.log("Mined");
}
invalidateNonce();
The IDEX exchange smart contract includes the ability to invalidate old order nonces. In the unlikely event that IDEX's off-chain components are compromised, it is theoretically possible that an attacker could submit a trade against an old, unfilled but canceled order. To limit risk in this scenario, clients may periodically invalidate old order nonces. Order nonce invalidation is a three-step process:
- Cancel all open orders.
- Call
invalidateNonce
on the IDEX exchange contract with a freshly generated nonce. This invalidates all order nonces generated in the past. - Re-place formerly-open orders with new orders.
Timing
IDEX only accepts recently-generated requests to prevent the inadvertent processing of out-of-date requests, regardless of the source of delay. Request timing is established by the nonce request parameter, which encodes a timestamp. IDEX rejects requests that have a nonce that is more than 60 seconds older or 5 second newer than the IDEX system clock. The Get Time endpoint returns the current IDEX time to synchronize the skew between IDEX and client clocks.
Rate Limits
IDEX enforces rate limits on all endpoints. Exceeding a rate limit returns a 429 Too Many Requests
HTTP status code. Rate limits vary between different types of endpoints, authentication, and the amount of data requested.
Single: Requests for a single object or with an object limit <= 100
Bundled: Requests for all objects or with an object limit > 100
Endpoint Type | Single | Bundled |
---|---|---|
Public, no API key | 5/s | 1/s |
Public, with API key | 10/s | 1/s |
User Data | 10/s | 1/s |
Trade | 10/s | n/a |
Public Data Endpoints
Get Ping
Tests connectivity to the REST API.
- HTTP Request:
GET /v4/ping
- Endpoint Security: Public
- API Key Scope: None required, an API Key increases rate limits
- Pagination: None
Request Parameters
$ curl "https://api.idex.io/v4/ping"
None
Response Object
JSON response
{}
Empty JSON object
Get Time
Returns the current server time.
- HTTP Request:
GET /v4/time
- Endpoint Security: Public
- API Key Scope: None required, an API Key increases rate limits
- Pagination: None
Request Parameters
$ curl "https://api.idex.io/v4/time"
None
Response Object
JSON response
{
"serverTime": 1704067200000
}
Field | Type | Description |
serverTime | integer | Current server time |
Get Exchange
Returns basic information about the exchange.
- HTTP Request:
GET /v4/exchange
- Endpoint Security: Public
- API Key Scope: None required, an API Key increases rate limits
- Pagination: None
Request Parameters
$ curl "https://api.idex.io/v4/exchange"
None
Response Object
JSON response
{
"timeZone": "UTC",
"serverTime": 1704067200000,
"exchangeContractAddress": "0x...",
"chainId": 94524,
"quoteTokenAddress": "0x...",
"stargateBridgeAdapterContractAddress": "0x...",
"totalOpenInterest": "436313641.14828522",
"volume24h": "1157766337.39181880",
"totalVolume": "27022612360.88700435",
"totalTrades": 23041409,
"idexTokenAddressArbitrum": "0x...",
"idexTokenAddressEthereum": "0x...",
"idexTokenAddressPolygon": "0x...",
"idexTokenPrice": "1.62",
"idexMarketCap": "954070759.33",
"defaultMakerFeeRate": "0.00010000",
"defaultTakerFeeRate": "0.00050000",
"withdrawalMinimum": "1.00000000",
}
Field | Type | Description |
timeZone | string | Server time zone, always UTC |
serverTime | integer | Current server time |
exchangeContractAddress | string | XCHAIN address of the exchange smart contract for deposits |
chainId | integer | XCHAIN chain identifier |
quoteTokenAddress | string | Address of the quote asset (USDC) on XCHAIN |
stargateBridgeAdapterContractAddress | string | Address of the Stargate bridge adapter contract |
totalOpenInterest | string | Total open interest across all markets in USD |
volume24h | string | Total exchange trading volume for the trailing 24 hours in USD |
totalVolume | string | Total exchange trading volume for IDEX v4 in USD |
totalTrades | integer | Total number of trade executions for IDEX v4 |
idexTokenAddressArbitrum | string | Token contract address for the IDEX token on Arbitrum One |
idexTokenAddressEthereum | string | Token contract address for the IDEX token on Ethereum |
idexTokenAddressPolygon | string | Token contract address for the IDEX token on Polygon PoS |
idexTokenPrice | string | Current price of the IDEX token in USD |
idexMarketCap | string | Market capitalization of the IDEX token in USD |
defaultMakerFeeRate | string | Default exchange-wide maker trade fee rate |
defaultTakerFeeRate | string | Default exchange-wide taker trade fee rate |
withdrawalMinimum | string | Minimum withdrawal amount in USD |
Get Markets
Returns information about the currently listed markets.
- HTTP Request:
GET /v4/markets
- Endpoint Security: Public
- API Key Scope: None required, an API Key increases rate limits
- Pagination: None
Request Parameters
$ curl "https://api.idex.io/v4/markets"
Parameter | Type | Required | Default | Description |
market | string | No | Target market, all markets are returned if omitted |
Response Array Objects
JSON response
[
{
"market": "ETH-USD",
"type": "perpetual",
"status": "active",
"baseAsset": "ETH",
"quoteAsset": "USD",
"stepSize": "0.00000100",
"tickSize": "0.01000000",
"indexPrice": "2236.32000000",
"indexPrice24h": "2101.81000000",
"indexPricePercentChange": "0.06399722",
"lastFundingRate": "0.00017100",
"currentFundingRate": "0.00010000",
"nextFundingTime": 1704182400000,
"makerOrderMinimum": "0.01000000",
"takerOrderMinimum": "0.01000000",
"marketOrderExecutionPriceLimit": "0.10000000",
"limitOrderExecutionPriceLimit": "0.40000000",
"minimumPositionSize": "0.01000000",
"maximumPositionSize": "500.00000000",
"initialMarginFraction": "0.05000000",
"maintenanceMarginFraction": "0.03000000",
"basePositionSize": "25.00000000",
"incrementalPositionSize": "5.00000000",
"incrementalInitialMarginFraction": "0.01000000",
"makerFeeRate": "-0.00010000",
"takerFeeRate": "0.00040000",
"volume24h": "294856820.05",
"trades24h": 221307,
"openInterest": "57178.63200000",
},
...
]
Field | Type | Description |
market | string | Market symbol |
type | string | Market type, always perpetual |
status | string | Market trading status, see values |
baseAsset | string | Base asset symbol |
quoteAsset | string | Quote asset symbol |
stepSize | string | Minimum quantity increment change in base terms |
tickSize | string | Minimum price increment change in quote terms |
indexPrice | string | Current index price of the market |
indexPrice24h | string | Index price 24h ago |
indexPricePercentChange | string | Percent change in index price from 24h ago to current |
lastFundingRate | string | Funding rate of the last payment |
currentFundingRate | string | Current funding rate |
nextFundingTime | integer | Time of the next funding payment |
makerOrderMinimum | string | Minimum size of an order that can rest on the order book in base terms |
takerOrderMinimum | string | Minimum order size that is accepted by the matching engine for execution in base terms |
marketOrderExecutionPriceLimit | string | Execution price limit for market orders; a value of 0.1 indicates that market orders must execute with 10% of the current index price |
limitOrderExecutionPriceLimit | string | Execution price limit for limit orders; a value of 0.4 indicates that limit orders must be priced with 40% of the current index price |
minimumPositionSize | string | Minimum position size in base terms; see Position Minimums for details |
maximumPositionSize | string | Maximum position size in base terms |
initialMarginFraction | string | Margin requirement to open a position expressed as a fraction |
maintenanceMarginFraction | string | Margin requirement to prevent liquidation expressed as a fraction |
basePositionSize | string | Maximum position size to which the initialMarginFraction applies |
incrementalPositionSize | string | If a position exceeds basePositionSize , each step of incrementalPositionSize increases the initialMarginFraction by incrementalInitialMarginFraction |
incrementalInitialMarginFraction | string | |
makerFeeRate | string | Maker trade fee rate for the market, supersedes the exchange default |
takerFeeRate | string | Taker trade fee rate for the market, supersedes the exchange default |
volume24h | string | Trailing 24h volume for the market in USD |
trades24h | integer | Number of trade executions in the market in the trailing 24h |
openInterest | string | Open interest quantity in base terms |
Market Data Endpoints
Get Tickers
Returns market statistics for the trailing 24-hour period.
- HTTP Request:
GET /v4/tickers
- Endpoint Security: Public
- API Key Scope: None required, an API Key increases rate limits
- Pagination: None
Request Parameters
$ curl "https://api.idex.io/v4/tickers"
Parameter | Type | Required | Default | Description |
market | string | No | Target market, all markets are returned if omitted |
Response Array Objects
JSON response
[
{
"market": "ETH-USD",
"time": 1704153660000,
"open": "2282.87000000",
"high": "2427.56000000",
"low": "2273.63000000",
"close": "2352.59000000",
"closeQuantity": "9.50000000",
"baseVolume": "118000.31500000",
"quoteVolume": "275058735.17000000",
"percentChange": "0.03054050",
"trades": 31201,
"ask": "2352.63000000",
"bid": "2352.61000000",
"markPrice": "2352.61000000",
"indexPrice": "2353.01000000",
"indexPrice24h": "2281.94000000",
"indexPricePercentChange": "0.03114455",
"lastFundingRate": "0.00017100",
"currentFundingRate": "0.00010000",
"nextFundingTime": 1704182400000,
"openInterest": "57178.63200000",
"sequence": 848728
},
...
]
Field | Type | Description |
market | string | Market symbol |
time | integer | Timestamp when the statistics were computed, the opening time of the period is 24 hours prior |
open | string | Price of the first trade in the period in quote terms |
high | string | Highest traded price in the period in quote terms |
low | string | Lowest traded price in the period in quote terms |
close | string | Price of the last trade in the period in quote terms |
closeQuantity | string | Quantity of the last trade in the period in base terms |
baseVolume | string | Trailing 24-hour trading volume in base terms |
quoteVolume | string | Trailing 24-hour trading volume in quote terms |
percentChange | string | Percentage change from open price to close price |
trades | integer | Number of trades in the period |
ask | string | Best ask price on the order book in quote terms |
bid | string | Best bid price on the order book in quote terms |
markPrice | string | Current mark price |
indexPrice | string | Current index price |
indexPrice24h | string | Index price 24h ago |
indexPricePercentChange | string | Percent change in index price from 24h ago to current |
lastFundingRate | string | Funding rate of the last payment |
currentFundingRate | string | Current funding rate |
nextFundingTime | string | Timestamp of the next funding payment |
openInterest | string | Current open interest |
sequence | integer | Fill sequence number of the last trade in the period |
Get Candles
Returns candle (OHLCV) data for a market.
- HTTP Request:
GET /v4/candles
- Endpoint Security: Public
- API Key Scope: None required, an API Key increases rate limits
- Pagination:
start
,end
,limit
Request Parameters
$ curl "https://api.idex.io/v4/candles?market=ETH-USD&interval=1d"
Parameter | Type | Required | Default | Description |
market | string | Yes | None | Target market |
interval | string | Yes | None | Time period for each data point, see values |
start | integer | No | None | Timestamp of the earliest (oldest) interval, inclusive |
end | integer | No | None | Timestamp of the latest (newest) interval, inclusive |
limit | integer | No | 50 | Maximum number of data points to return, 1-1,000 |
- If neither
start
norend
is specified, the most recent intervals are returned. See pagination for more details.
Response Array Objects
JSON response
[
{
"start": 1704067200000,
"open": "2282.87000000",
"high": "2427.56000000",
"low": "2273.63000000",
"close": "2352.59000000",
"baseVolume": "118000.31500000",
"quoteVolume": "275058735.17000000",
"trades": 31201,
"sequence": 848678
},
...
]
Field | Type | Description |
start | integer | Timestamp of the start of the interval |
open | string | Price of the first trade in the interval in quote terms |
high | string | Highest traded price in the interval in quote terms |
low | string | Lowest traded price in the interval in quote terms |
close | string | Price of the last trade in the interval in quote terms |
baseVolume | string | Trading volume in the interval in base terms, null for some historical chart data |
quoteVolume | string | Trading volume in the interval in quote terms, null for some historical chart data |
trades | integer | Number of trades in the interval, null for some historical chart data |
sequence | integer | Fill sequence number of the last trade in the interval, null for some historical chart data |
- In the case that no trades occur in an interval, no candle object is returned for the interval.
Get Trades
Returns trade data for a market. There is also a Get Fills endpoint that returns more detailed private information. In this documentation, "trades" refers to public information about trades, whereas "fills" refers to detailed non-public information about trades resulting from orders placed by the API account.
- HTTP Request:
GET /v4/trades
- Endpoint Security: Public
- API Key Scope: None required, an API Key increases rate limits
- Pagination:
start
,end
,limit
,fromId
Request Parameters
$ curl "https://api.idex.io/v4/trades?market=ETH-USD&start=1704067200000"
Parameter | Type | Required | Default | Description |
market | string | Yes | None | Target market |
start | integer | No | None | Timestamp of the earliest (oldest) trade, inclusive |
end | integer | No | None | Timestamp of the latest (newest) trade, inclusive |
limit | integer | No | 50 | Maximum number of data points to return, 1-1,000 |
fromId | string | No | None | fillId of the earliest (oldest) trade |
- If none of
start
,end
, orfromId
is specified, the most recent trades are returned. See pagination for more details.
Response Array Objects
JSON response
[
{
"fillId": "cfd05df0-b4df-11ee-aed5-c788337a7b62",
"price": "2375.22000000",
"quantity": "10.00000000",
"quoteQuantity": "23752.20000000",
"time": 1704067200050,
"makerSide": "sell",
"sequence": 844323,
},
...
]
Field | Type | Description |
fillId | string | Trade identifier |
price | string | Price of the trade in quote terms |
quantity | string | Quantity of the trade in base terms |
quoteQuantity | string | Quantity of the trade in quote terms |
time | integer | Timestamp of the trade |
makerSide | string | Maker side of the trade, buy or sell |
sequence | integer | Fill sequence number of the trade |
- The Get Trades response only includes order book fills. See Get Liquidations for liquidations and ADL actions.
Get Liquidations
Returns liquidation data for a market. Unlike trades, liquidations do not contribute to trading volume and are not included in tickers or candles.
- HTTP Request:
GET /v4/liquidations
- Endpoint Security: Public
- API Key Scope: None required, an API Key increases rate limits
- Pagination:
start
,end
,limit
,fromId
Request Parameters
$ curl "https://api.idex.io/v4/liquidations?market=ETH-USD&start=1704067200000"
Parameter | Type | Required | Default | Description |
market | string | Yes | None | Target market |
start | integer | No | None | Timestamp of the earliest (oldest) liquidation, inclusive |
end | integer | No | None | Timestamp of the latest (newest) liquidation, inclusive |
limit | integer | No | 50 | Maximum number of data points to return, 1-1,000 |
fromId | string | No | None | fillId of the earliest (oldest) liquidation |
- If none of
start
,end
, orfromId
is specified, the most recent liquidations are returned. See pagination for more details.
Response Array Objects
JSON response
[
{
"fillId": "e5132d50-b4df-11ee-815e-51c714db211c",
"price": "2113.90000000",
"quantity": "3.50000000",
"quoteQuantity": "7398.65000000",
"time": 1704067224778,
"liquidationSide": "sell"
},
...
]
Field | Type | Description |
fillId | string | Liquidation identifier |
price | string | Price of the liquidation in quote terms |
quantity | string | Quantity of the liquidation in base terms |
quoteQuantity | string | Quantity of the liquidation in quote terms |
time | integer | Timestamp of the liquidation |
liquidationSide | string | Liquidation side of the settlement, buy or sell |
Get Order Books
Returns a level-1 or level-2 order book of a market.
- HTTP Request:
GET /v4/orderbook
- Endpoint Security: Public
- API Key Scope: None required, an API Key increases rate limits
- Pagination:
limit
Request Parameters
The level-1 order book only includes the best bid and ask.
$ curl "https://api.idex.io/v4/orderbook?market=ETH-USD"
JSON response
{
"sequence": 71228121,
"bids": [
[ "2352.61000000", "13.88200000", 2 ],
],
"asks": [
[ "2352.63000000", "8.11400000", 1 ],
],
"lastPrice": "2352.60000000",
"markPrice": "2352.61000000",
"indexPrice": "2353.01000000"
}
Price level arrays for both bids and asks take the form of:
[ price, quantity available, number of orders at price level ]
The level-2 order book contains all price levels up to the specified
limit
.
$ curl "https://api.idex.io/v4/orderbook?market=ETH-USD&level=2"
JSON response
{
"sequence": 71228121,
"bids": [
[ "2352.61000000", "13.88200000", 2 ],
[ "2352.59000000", "29.95300000", 3 ],
...
],
"asks": [
[ "2352.63000000", "8.11400000", 1 ],
[ "2352.64000000", "7.29700000", 3 ],
...
],
"lastPrice": "2352.60000000",
"markPrice": "2352.61000000",
"indexPrice": "2353.01000000",
}
Parameter | Type | Required | Default | Description |
market | string | Yes | Target market | |
level | integer | No | 1 | Level of order book, 1 or 2 |
limit | integer | No | 50 | Number of bids and asks to return, only applicable to level-2 data, 0 returns the maximum of 500 price levels per side |
Level 1 Response Object
Level-1 order book data is limited to the best bid and ask for a market.
Field | Type | Description |
sequence | integer | Most recent order book update sequence number reflected in the returned snapshot |
bids | array | Single record of the best bid price level on the order book |
asks | array | Single record of the best ask price level on the order book |
lastPrice | string | Price of the last trade in quote terms |
markPrice | string | Mark price |
indexPrice | string | Index price |
Level 2 Response Object
Level-2 order book data includes price and quantity information for all price levels in the order book.
Field | Type | Description |
sequence | integer | Most recent order book update sequence number reflected in the returned snapshot |
bids | array | Bid price levels on the order book, limited by limit |
asks | array | Ask price levels on the order book, limited by limit |
lastPrice | string | Price of the last trade in quote terms |
markPrice | string | Mark price |
indexPrice | string | Index price |
Real-Time Order Book Tracking Algorithm
- Connect to the WebSocket API endpoint and subscribe to the L2 Order Book for the target market.
- Buffer the incoming order book update subscription messages.
- Request a level-2 order book snapshot for the market from the REST API Order Books endpoint with limit set to
0
. - If the sequence in the order book snapshot is less than the sequence of the first buffered order book update message, discard the order book snapshot and retry step 3.
- Discard all order book update messages with sequence numbers less than or equal to the snapshot sequence number.
- Apply the remaining buffered order book update messages and any incoming order book update messages to the order book snapshot.
- Order book update messages include the new absolute quantity and number of orders for a price level. Replace the current data for the price level with the update message data.
- Remove price levels with a quantity of
0
. - Re-synchronize the order book if there are any gaps in the order book update sequence numbers.
Get Funding Rates
Returns historical funding rate data for a market.
- HTTP Request:
GET /v4/fundingRates
- Endpoint Security: Public
- API Key Scope: None required, an API Key increases rate limits
- Pagination:
start
,end
,limit
Request Parameters
$ curl "https://api.idex.io/v4/fundingRates?market=ETH-USD&start=1704067200000"
Parameter | Type | Required | Default | Description |
market | string | Yes | None | Target market |
start | integer | No | None | Timestamp of the earliest (oldest) funding rate, inclusive |
end | integer | No | None | Timestamp of the latest (newest) funding rate, inclusive |
limit | integer | No | 50 | Maximum number of data points to return, 1-1,000 |
- If neither
start
norend
are specified, the most recent funding rates are returned. See pagination for more details.
Response Array Objects
JSON response
[
{
"fundingRate": "0.00017100",
"indexPrice": "2353.01000000",
"time": 1704153600000,
},
...
]
Field | Type | Description |
fundingRate | string | Funding rate for the period |
indexPrice | string | Index price of the market at the period time |
time | integer | Timestamp of the funding period |
- Responses that include the most recent full-period data point also include a data point of the current values for the market.
User Data Endpoints
Associate Wallet
// Example code for creating the required wallet signature. Note the IDEX SDKs
// automatically generate wallet signatures for endpoints that require them.
const ethers = require("ethers");
const uuid = require("uuid");
let data = {
"nonce": uuid.v1(),
"wallet": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d"
};
let domainSeparator = {
"name": "IDEX",
"version": "4.0.0", // "4.0.0-sandbox" for the sandbox environment
"chainId": "<XCHAIN chain ID>",
"verifyingContract": "0x..."
};
let typeData = {
WalletAssociation: [
{ name: 'nonce', type: 'uint128' },
{ name: 'wallet', type: 'address' },
]
};
// Nonce must be a uint128, not string representation
let nonceAsHexString = `0x${data.nonce.replace(/-/g, '')}`;
let nonceAsUint128 = BigInt.asUintN(128, BigInt(nonceAsHexString));
let value = {
"nonce": nonceAsUint128,
"wallet": data.wallet
};
new ethers.Wallet("<Wallet private key>").signTypedData(
domainSeparator,
typeData,
value
)
.then((walletSignature) => {
console.log(walletSignature);
});
Associates a wallet with an API account, allowing access to private data such as fills. Associating a wallet with an API account is often the first step in interacting with private read endpoints. A wallet is automatically associated with an API account when withdrawing funds. Unlocking a wallet in the web client also associates a wallet with an API account.
For further information, see Wallet to API Account Association. Note this endpoint requires Trade endpoint security and must include a wallet signature.
Request Parameters
Sample associate order request payload
{
"parameters": {
"nonce": "9436afa0-9ee6-11ea-8a53-71994564322f",
"wallet": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d"
},
"signature": "<Wallet signature>"
}
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Target wallet address |
Response Object
This endpoint responds with a single Get Wallets response object.
Get Wallets
Returns information about the wallets associated with the API account.
Request Parameters
$ curl "https://api.idex.io/v4/wallets?nonce=913ad4c0-9ee6-11ea-87e1-b75e864948fa" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | No | None | Wallet address |
includePositions | boolean | No | true | false excludes positions data from the response |
Response Array Objects
JSON response
[
{
"wallet": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"equity": "88141.77508743",
"freeCollateral": "87664.57508743",
"heldCollateral": "10000.00000000",
"availableCollateral": "86664.57508743",
"buyingPower": "1753291.50174860",
"leverage": "0.10828271",
"marginRatio": "0.00324840",
"quoteBalance": "87841.77508743",
"unrealizedPnL": "3544.23000000",
"makerFeeRate": "-0.00010000",
"takerFeeRate": "0.00040000",
"positions": [...],
},
...
]
Field | Type | Description |
wallet | string | Wallet address |
equity | string | Total account value |
freeCollateral | string | equity - total initial margin requirement; collateral funds beyond the baseline requirements of open positions |
heldCollateral | string | Free collateral committed to open limit orders |
availableCollateral | string | Free collateral available for order placement or withdrawal |
buyingPower | string | freeCollateral * maximum market leverage |
leverage | string | total absolute position notional value / equity |
marginRatio | string | total maintenance margin requirement / equity |
quoteBalance | string | Quote balance |
unrealizedPnL | string | Unrealized PnL of all open positions in quote terms at the index price |
makerFeeRate | string | Maker trade fee rate with promotions applied, supersedes exchange and market maker fee rate |
takerFeeRate | string | Taker trade fee rate with promotions applied, supersedes exchange and market taker fee rate |
positions | array | Array of position objects |
makerFeeRate
andtakerFeeRate
report the trade fee rates for a wallet inclusive of any discount programs. If a market offers lower fees as a promotion, however, the lower fees are applied. See fees for details.
Get Positions
Returns information about positions held by a wallet.
Request Parameters
$ curl "https://api.idex.io/v4/positions?nonce=913ad4c0-9ee6-11ea-87e1-b75e864948fa" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Wallet address |
market | string | No | None | Market symbol |
Response Array Objects
JSON response
[
{
"market": "ETH-USD",
"quantity": "3.00000000",
"maximumQuantity": "3.00000000",
"entryPrice": "2000.00000000",
"exitPrice": "0.00000000",
"markPrice": "3199.02000000",
"indexPrice": "3181.41000000",
"liquidationPrice": "0.00000000",
"value": "9544.23000000",
"realizedPnL": "-15.42000000",
"unrealizedPnL": "3544.23000000",
"marginRequirement": "477.21150000",
"leverage": "0.10828271",
"totalFunding": "-17.82000000",
"totalOpen": "3.00000000",
"totalClose": "0.00000000",
"adlQuintile": "1",
"openedByFillId": "da107420-b742-11ee-81fc-256a7a814967",
"lastFillId": "da107420-b742-11ee-81fc-256a7a814967",
"time": 1699488727919,
},
...
]
Field | Type | Description |
market | string | Market symbol |
quantity | string | Base quantity, negative for short positions |
maximumQuantity | string | Maximum absolute quantity of the position during its existence |
entryPrice | string | Average entry price of the position |
exitPrice | string | Average exit price of the position |
markPrice | string | Current mark price of the market |
indexPrice | string | Current index price of the market |
liquidationPrice | string | Index price beyond which the position will be liquidated |
value | string | Position value at index price |
realizedPnL | string | Realized PnL of the position in quote terms, including funding payments |
unrealizedPnL | string | Unrealized PnL of the position in quote terms at the index price |
marginRequirement | string | Current initial margin requirement of the position |
leverage | string | Cross-margined position leverage |
totalFunding | string | Net total of all funding payments for the position |
totalOpen | string | Total of all trade quantities that increased the position in base terms |
totalClose | array | Total of all trade quantities that decreased the position in base terms |
adlQuintile | integer | Position ADL risk, 0-5, 5 is highest risk |
openedByFillId | string | Id of the fill that opened the position |
lastFillId | string | Id of the fill that most recently updated the position |
time | integer | Timestamp of position opening |
Get Funding Payments
Returns funding payment history information for a wallet.
- HTTP Request:
GET /v4/fundingPayments
- Endpoint Security: User Data
- API Key Scope: Read
- Pagination:
start
,end
,limit
Request Parameters
$ curl "https://api.idex.io/v4/fundingPayments?nonce=d90fa580-b7bc-11ee-b206-1db81f570b53&wallet=0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Wallet address |
market | string | No | None | Market symbol |
start | integer | No | None | Timestamp of the earliest (oldest) funding payment, inclusive |
end | integer | No | None | Timestamp of the latest (newest) funding payment, inclusive |
limit | integer | No | 50 | Maximum number of data points to return, 1-1,000 |
- If neither
start
norend
is specified, the most recent funding payments are returned. See pagination for more details.
Response Array Objects
JSON response
[
{
"market": "ETH-USD",
"paymentQuantity": "-1.27090620",
"positionQuantity": "3.00000000",
"fundingRate": "0.00017100",
"indexPrice": "2477.40000000",
"time": 1705708800000,
},
...
]
Field | Type | Description |
market | string | Market symbol |
paymentQuantity | string | Quantity of the funding payment in quote terms |
positionQuantity | string | Quantity of the open position at payment time in base terms |
fundingRate | string | Funding rate for the period |
indexPrice | string | Index price of the market at payment time |
time | integer | Timestamp of the payment |
Get Historical PnL
Returns PnL history information for a wallet.
- HTTP Request:
GET /v4/historicalPnL
- Endpoint Security: User Data
- API Key Scope: Read
- Pagination:
start
,end
,limit
Request Parameters
$ curl "https://api.idex.io/v4/historicalPnL?nonce=a28f0d10-b7bd-11ee-ae1a-57c4747d3be9&wallet=0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Wallet address |
start | integer | No | None | Timestamp of the earliest (oldest) PnL data point, inclusive |
end | integer | No | None | Timestamp of the latest (newest) PnL data point, inclusive |
limit | integer | No | 50 | Maximum number of data points to return, 1-1,000 |
- If neither
start
norend
is specified, the most recent data points are returned. See pagination for more details.
Response Array Objects
JSON response
[
{
"equity": "88141.77508743",
"totalPnL": "29285.02191760",
"netDepositsWithdrawals": "0.00000000",
"time": 1705773780000,
},
...
]
Field | Type | Description |
equity | string | Total account value |
totalPnL | string | Total PnL for account since first deposit |
netDepositsWithdrawals | string | Net quantity deposited and withdrawn since the last data point in quote terms |
time | integer | Timestamp of the data point |
- Response data point period is 1h.
- Responses that include the most recent full-period data point also include a data point of the current values.
Orders & Trade Endpoints
Create Order
Create and submit an order to the matching engine.
Request Parameters
Sample
market
order request payload
{
"parameters": {
"nonce": "d1e545b0-b7c8-11ee-ad06-2573b265c15a",
"wallet": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"market": "ETH-USD",
"type": "market",
"side": "buy",
"quantity": "10.00000000"
},
"signature": "<Wallet signature>"
}
Standard order JSON response
{
"market": "ETH-USD",
"orderId": "92782120-a775-11ea-aa55-4da1cc97a06d",
"wallet": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"time": 1705778379471,
"status": "filled",
"type": "market",
"side": "buy",
"originalQuantity": "10.00000000",
"executedQuantity": "10.00000000",
"cumulativeQuoteQuantity": "24609.40000000",
"avgExecutionPrice": "2460.94000000",
"reduceOnly": false,
"selfTradePrevention": "dc",
"fills": [
{
"fillId": "974480d0-a776-11ea-895b-bfcbb5bdaa50",
"price": "2460.94000000",
"quantity": "3.78500000",
"quoteQuantity": "9314.65790000",
"time": 1705778379471,
"makerSide": "sell",
"sequence": 981372,
"fee": "3.72586316",
"liquidity": "taker",
"action": "open",
"position": "long",
"type": "market",
"txId": "0x01d28c33271cf1dd0eb04249617d3092f24bd9bad77ffb57a0316c3ce5425158",
"txStatus": "mined"
},
...
]
}
Sample
stopLossLimit
order request payload
{
"parameters": {
"nonce": "075996e0-b7cb-11ee-be5d-2f6099650fc5",
"wallet": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"market": "ETH-USD",
"type": "stopLossLimit",
"side": "sell",
"quantity": "4.95500000",
"price": "2440.00000000",
"triggerPrice": "2450.00000000",
"triggerType": "last",
"clientOrderId": "199283"
},
"signature": "<Wallet signature>"
}
Standard order JSON response
{
"market": "ETH-USD",
"orderId": "3a9ef9c0-a779-11ea-907d-23e999279287",
"clientOrderId": "199283",
"wallet": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"time": 1705779328613,
"status": "active",
"type": "stopLossLimit",
"side": "sell",
"originalQuantity": "4.95500000",
"executedQuantity": "0.00000000",
"cumulativeQuoteQuantity": "0.00000000",
"price": "2440.00000000",
"triggerPrice": "2450.00000000",
"triggerType": "last",
"reduceOnly": false,
"selfTradePrevention": "dc"
}
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Wallet address |
delegatedKey | string | No | None | Delegated key public address if authorized via delegated key |
market | string | Yes | None | Target market symbol |
type | string | Yes | None | Order type, see values |
side | string | Yes | None | Order side, buy or sell |
quantity | string | Yes | None | Order quantity in base terms |
price | string | No | None | Order price in quote terms, required for all limit orders, omitted for all market orders |
triggerPrice | string | No | None | Stop loss or take profit price for stopLossMarket , stopLossLimit , takeProfitMarket , takeProfitLimit orders, omitted for others |
triggerType | string | No | None | Price type for trigger price, last or index , required if triggerPrice is present |
clientOrderId | string | No | None | Client-specified order id, maximum of 40 bytes |
reduceOnly | boolean | No | false | Reduce only orders are only accepted opposite open positions and only reduce an opposite position’s size; see Position Minimums for additional usage |
timeInForce | string | No | gtc | Time in force policy, see values, only applies to all limit orders |
selfTradePrevention | string | No | dc | Self-trade prevention policy, see values, must be cn if fok timeInForce is specified |
- Wallets are limited to 250 open orders regardless of available collateral.
- Positions smaller than a market’s
minimumPositionSize
may be closed usingreduceOnly
. See Position Minimums for details.
Field | Type | Optional | Description |
market | string | No | Market symbol |
orderId | string | No | Exchange-assigned order identifier |
clientOrderId | string | Yes | Client-specified order identifier |
wallet | string | No | Wallet address |
time | integer | No | Timestamp of initial order processing by the matching engine |
status | string | No | Current order status, see values |
errorCode | string | Yes | Error short code explaining forced cancellation condition |
errorMessage | string | Yes | Error description explaining forced cancellation condition |
type | string | No | Order type, see values |
side | string | No | Order side, buy or sell |
originalQuantity | string | No | Original quantity specified by the order in base terms |
executedQuantity | string | No | Quantity that has been executed in base terms |
cumulativeQuoteQuantity | string | Yes | Cumulative quantity that has been spent (buy orders) or received (sell orders) in quote terms, omitted if unavailable for historical orders |
avgExecutionPrice | string | Yes | Weighted average price of fills associated with the order; only present with fills |
price | string | Yes | Original price specified by the order in quote terms, omitted for all market orders |
triggerPrice | string | Yes | Stop loss or take profit price for stopLossMarket , stopLossLimit , takeProfitMarket , and takeProfitLimit orders, omitted for others |
triggerType | string | Yes | Price type for trigger price, last or index |
reduceOnly | boolean | No | Reduce only orders are only accepted opposite open positions and only reduce an opposite position’s size |
timeInForce | string | Yes | Time in force policy, see values, only present for limit orders |
selfTradePrevention | string | No | Self-trade prevention policy, see values |
delegatedKey | string | Yes | Delegated key if present |
fills | array | Yes | Array of order fill objects |
Field | Type | Optional | Description |
fillId | string | No | Fill identifier |
price | string | No | Price of the fill in quote terms |
quantity | string | No | Quantity of the fill in base terms |
quoteQuantity | string | No | Quantity of the fill in quote terms |
realizedPnL | string | Yes | PnL realized by partial or complete closure of a position, omitted for open actions |
time | integer | No | Timestamp of the fill |
makerSide | string | No | Maker side of the fill, buy or sell |
sequence | integer | No | Fill sequence number |
fee | string | No | Fee amount collected on the fill |
liquidity | string | No | Whether the fill is the maker or taker in the trade from the perspective of the requesting API account, maker or taker |
action | string | No | Whether the fill increases or decreases the notional value of the position, open or close |
position | string | No | Resulting position side, long , short , or none |
type | string | No | Fill type, see values |
txId | string | No | Transaction id of the trade settlement transaction or null if not yet assigned |
txStatus | string | No | Status of the trade settlement transaction, see values |
- When order execution triggers self-trade prevention, the order response object may include a non-zero
executedQuantity
value without anyfills
objects, or thefills
objects may total less than theexecutedQuantity
.
Cancel Order
Cancel orders by exchange id or client id, or cancel all open orders for a market, all open orders placed by a delegated key, or all open orders placed by a wallet.
Request Parameters
Sample cancel order request payload
{
"parameters": {
"nonce": "91f460c0-9ee6-11ea-9026-c1542192a384",
"wallet": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"orderIds": ["3a9ef9c0-a779-11ea-907d-23e999279287"]
},
"signature": "<Wallet signature>"
}
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Placing wallet address |
delegatedKey | string | No | None | Delegated key public address if authorized via delegated key |
orderDelegatedKey | string | No | None | Authorizing delegated key public address of orders to cancel |
orderIds | array | No | None | Array of orderId s or clientOrderId s to cancel; prefix client-provided ids with client: |
market | string | No | None | Symbol of the market from which to cancel all open orders for the wallet |
orderDelegatedKey
,orderIds
, andmarket
are mutually exclusive.orderIds
accepts a maximum of 250 ids.- Cancel Order requests authorized by delegated key may cancel any open order placed by the custody wallet, not only those authorized by the delegated key.
Response Array Object
JSON response
[
{
"orderId": "3a9ef9c0-a779-11ea-907d-23e999279287",
"status": "canceled"
},
...
]
Field | Type | Optional | Description |
orderId | string | Yes | Exchange-assigned order identifier, not present for notFound orders specified by clientOrderId |
clientOrderId | string | Yes | Client-specified order identifier if present |
status | string | No | Order status, canceled or notFound |
- Cancels may be disabled at the exchange, API user, or wallet level. In this case a
403 Forbidden
error is returned.
Get Orders
Returns information about open and past orders.
- HTTP Request:
GET /v4/orders
- Endpoint Security: User Data
- API Key Scope: Read
- Pagination:
start
,end
,limit
,fromId
Request Parameters
$ curl "https://api.idex.io/v4/orders?nonce=03dc0c10-b7cf-11ee-9bda-73c0c048d465&wallet=0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d&market=ETH-USD" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Wallet address |
orderId | string | No | None | Single orderId or clientOrderId to return; prefix client-provided ids with client: |
market | string | No | None | Symbol of the market from which to query orders for the wallet, only applies if orderId is absent |
closed | boolean | No | false | false only returns active orders on the order book; true only returns orders that are no longer on the order book and resulted in at least one fill; only applies if orderId is absent |
start | integer | No | None | Timestamp of the earliest (oldest) order, inclusive, only applies if orderId is absent |
end | integer | No | None | Timestamp of the latest (newest) order, inclusive, only applies if orderId is absent |
limit | integer | No | 50 | Maximum number of data points to return, 1-1,000, only applies if orderId is absent |
fromId | string | No | None | orderId of the earliest (oldest) order, only applies if orderId is absent |
Response
This endpoint responds with either a single standard order response object, or an array of standard order response objects.
Get Fills
Returns information about trades involving orders placed by a wallet. Both this endpoint and the Trades endpoint return trade objects, but this endpoint includes additional private fields in its response. In this documentation, "trades" refers to public information about trades, whereas "fills" refers to detailed non-public information about trades resulting from orders placed by the API account.
- HTTP Request:
GET /v4/fills
- Endpoint Security: User Data
- API Key Scope: Read
- Pagination:
start
,end
,limit
,fromId
Request Parameters
$ curl "https://api.idex.io/v4/fills?nonce=92ba6fe0-9ee6-11ea-8a50-ad909d142fe6&wallet=0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d&market=ETH-USD" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Wallet address |
fillId | string | No | None | Single fillId to return |
orderId | string | No | None | orderId or clientOrderId from which to query fills for the order, only applies if fillId is absent; prefix client-provided ids with client: |
market | string | No | None | Symbol of the market from which to query fills for the wallet, only applies if fillId is absent |
start | integer | No | None | Timestamp of the earliest (oldest) fill, inclusive, only applies if fillId is absent |
end | integer | No | None | Timestamp of the latest (newest) fill, inclusive, only applies if fillId is absent |
limit | integer | No | 50 | Maximum number of fills to return, 1-1,000, only applies if fillId is absent |
fromId | string | No | None | fillId of the earliest (oldest) fill, only applies if fillId is absent |
- If none of
start
,end
, orfromId
is specified, the most recent fills are returned. See pagination for more details.
Response Array Objects
JSON response
[
{
"fillId": "974480d0-a776-11ea-895b-bfcbb5bdaa50",
"price": "2460.94000000",
"quantity": "3.78500000",
"quoteQuantity": "9314.65790000",
"time": 1705778379471,
"makerSide": "sell",
"sequence": 981372,
"market": "ETH-USD",
"orderId": "92782120-a775-11ea-aa55-4da1cc97a06d",
"side": "buy",
"fee": "3.72586316",
"liquidity": "taker",
"action": "open",
"position": "long",
"type": "market",
"txId": "0x01d28c33271cf1dd0eb04249617d3092f24bd9bad77ffb57a0316c3ce5425158",
"txStatus": "mined"
},
...
]
Field | Type | Optional | Description |
fillId | string | No | Fill identifier |
price | string | No | Price of the fill in quote terms |
quantity | string | No | Quantity of the fill in base terms |
quoteQuantity | string | No | Quantity of the fill in quote terms |
realizedPnL | string | Yes | PnL realized by partial or complete closure of a position, omitted for open actions |
time | integer | No | Timestamp of the fill |
makerSide | string | Yes | Maker side of the fill, buy or sell , omitted for liquidation actions |
sequence | integer | Yes | Fill sequence number, omitted for liquidation actions |
market | string | No | Market symbol |
orderId | string | Yes | Exchange-assigned order identifier, omitted for liquidations |
clientOrderId | string | Yes | Client-specified order identifier |
side | string | No | Order side, buy or sell |
fee | string | Yes | Fee amount collected on the fill in quote terms, may be negative due to promotions, omitted for some liquidation actions |
liquidity | string | Yes | Whether the fill is the maker or taker in the trade from the perspective of the requesting API account, maker or taker , omitted for liquidation actions |
action | string | No | Whether the fill increases or decreases the notional value of the position, open or close |
position | string | No | Resulting position side, long , short , or none |
type | string | No | Fill type, see values |
txId | string | No | Transaction id of the trade settlement transaction or null if not yet assigned |
txStatus | string | No | Status of the trade settlement transaction, see values |
- Unlike the distinction between Get Trades and Get Liquidations, Get Fills responses include fills, liquidations, and ADL actions.
Deposit Endpoints
Deposit Funds
const fs = require('fs');
const ethers = require('ethers');
async function deposit() {
// Set desired deposit amount
const depositAmount = BigInt(100000000); // 100 USDC
// Connect a wallet to mainnet
const provider = new ethers.JsonRpcProvider('<Arbitrum One RPC>');
const walletWithProvider = new ethers.Wallet(
'<Arbitrum One wallet private key>',
provider,
);
const usdcAddress = '<USDC token contract address on Arbitrum One>';
const stargatePoolAddress =
'<StargatePoolUSDC contract address on Arbitrum One>';
const exchangeStargateV2AdapterAddress =
'<ExchangeStargateV2Adapter contract address on XCHAIN>';
// https://docs.layerzero.network/v2/developers/evm/technical-reference/deployed-contracts#xchain
const xchainLayerZeroEndpointId = 30291;
// Load contracts
const usdcAbi = JSON.parse(fs.readFileSync('ERC20.abi.json'));
const usdcContract = new ethers.Contract(
usdcAddress,
usdcAbi,
walletWithProvider,
);
const stargateAbi = JSON.parse(fs.readFileSync('StargatePoolUSDC.abi.json'));
const stargateContract = new ethers.Contract(
stargatePoolAddress,
stargateAbi,
walletWithProvider,
);
// Approve USDC transfer
const approveTx = await usdcContract.approve(
stargatePoolAddress,
depositAmount,
);
console.log(`Dispatched approve ${approveTx.hash} awaiting mine...`);
await approveTx.wait();
console.log('Mined');
// Build SendParam
// https://docs.layerzero.network/v2/developers/evm/oft/composing#sending-token
// Configure the gas limit for the composed call on the destination chain. Encode as a tuple of
// (index, gasLimit) where index is 0 as there is only one call executed on the destination chain
// https://github.com/LayerZero-Labs/LayerZero-v2/blob/1fde89479fdc68b1a54cda7f19efa84483fcacc4/oapp/contracts/oapp/libs/OptionsBuilder.sol#L92
// https://github.com/LayerZero-Labs/LayerZero-v2/blob/1fde89479fdc68b1a54cda7f19efa84483fcacc4/protocol/contracts/messagelib/libs/ExecutorOptions.sol#L82
const gasLimitOption = ethers.solidityPacked(
['uint16', 'uint128'],
[0, 450_000],
);
// Build a new options container and add the gas limit option built above. Encode as a tuple of
// (optionsType, workerId, gasLimitOption.length+1, optionType, gasLimitOption) where optionsType
// is the constant 3, workerId is the constant 1, gasLimitOption.length is the packed byte width
// of the gas limit option, and optionType is the constant 3 indicating lzCompose
// https://github.com/LayerZero-Labs/LayerZero-v2/blob/1fde89479fdc68b1a54cda7f19efa84483fcacc4/oapp/contracts/oapp/libs/OptionsBuilder.sol#L133
// https://github.com/LayerZero-Labs/LayerZero-v2/blob/1fde89479fdc68b1a54cda7f19efa84483fcacc4/protocol/contracts/messagelib/libs/ExecutorOptions.sol#L10
// https://github.com/LayerZero-Labs/LayerZero-v2/blob/1fde89479fdc68b1a54cda7f19efa84483fcacc4/protocol/contracts/messagelib/libs/ExecutorOptions.sol#L14
const extraOptions = ethers.solidityPacked(
['uint16', 'uint8', 'uint16', 'uint8', 'bytes'],
[3, 1, 2 + 16 + 1, 3, gasLimitOption],
);
const sendParam = {
dstEid: xchainLayerZeroEndpointId, // Destination endpoint ID
to: ethers.zeroPadValue(exchangeStargateV2AdapterAddress, 32), // Recipient address
amountLD: depositAmount, // Amount to send in local decimals
minAmountLD: depositAmount, // Minimum amount to send in local decimals
extraOptions,
composeMsg: ethers.AbiCoder.defaultAbiCoder().encode(
['address'],
[walletWithProvider.address],
), // Additional options supplied by the caller to be used in the LayerZero message
oftCmd: '0x', // The OFT command to be executed, unused in default OFT implementations
};
// Estimate XCHAIN gas fee
const messagingFee = await stargateContract.quoteSend(sendParam, false, {
from: walletWithProvider.address,
});
// Bridge funds to XCHAIN
const sendTx = await stargateContract.send(
sendParam,
{ nativeFee: messagingFee.nativeFee, lzTokenFee: 0 },
walletWithProvider.address, // Refund address - extra gas (if any) is returned to this address
{
from: walletWithProvider.address,
// Native gas to pay for the cross chain message fee
value: messagingFee.nativeFee,
},
);
console.log(`Dispatched send ${sendTx.hash} awaiting mine...`);
await sendTx.wait();
console.log('Mined');
}
deposit();
IDEX uses USDC as its primary collateral asset, and USDC is the only token supported for deposits and withdrawals. Because IDEX operates on XCHAIN, IDEX integrates with the Stargate v2 bridging protocol for fast, seamless cross-chain deposits with no protocol fees. Specifically, IDEX exclusively supports Stargate v2 Hydra-wrapped USDC as its collateral token, allowing single-transaction deposits from Ethereum, Arbitrum, Optimism, Base, and other chains, often in less than a minute.
Deposits are initiated via smart contract calls on the source chain rather than via the IDEX REST API. At a high level, the depositing wallet calls StargatePoolUSDC.send
with the appropriate parameters on a chain where it holds USDC; the tokens are then bridged to XCHAIN by Stargate and deposited into the exchange. Only a single transaction on the source chain is necessary to complete the deposit.
ABIs for interacting with StargatePoolUSDC and exchange contracts are available in the official JavaScript SDK repo.
Source Chain Deposit
Any of the blockchains with a USDC asset listed in the Stargate V2 developer docs Supported Networks and Assets may be used as a source.
- Approve the USDC transfer. On the source chain,
approve
the Stargate pool contract to spend USDC up to at least the amount to be deposited. It is recommended to approve 2256 to avoidapprove
calls on future deposits. The correctUSDC
andStargatePoolUSDC
contract addresses are listed by source chain in the Stargate V2 developer docs Supported Networks and Assets and Mainnet Contracts respectively. - Build the
SendParam
struct that will be used both for estimating the destination chain gas fees as well as bridging funds. This struct encodes:- The destination XCHAIN LayerZero endpoint ID 30291
- The address of the destination
ExchangeStargateV2Adapter
contract (thestargateBridgeAdapterContractAddress
field returned by the Get Exchange endpoint) - The USDC quantity to be bridged
- The destination wallet on XCHAIN that will be credited with the funds on the
Exchange
contract. The destination wallet may be different from the sending wallet on the source chain, however you must have control of the destination wallet or funds will be permanently lost.
- Estimate the destination chain gas fees. On the source chain, call
quoteSend
on the Stargate pool contract using theSendParam
struct built in step 2. This will return the quantity of native asset (e.g. ETH) that must be sent in the source chain transaction to fund gas on XCHAIN to complete the deposit. No slippage or protocol fee is charged when bridging into XCHAIN, and the full quantity of tokens sent will be delivered and credited. - Call
send
on theStargatePoolUSDC
contract using theSendParam
struct built in step 2 and the native fee estimated in step 3. Tokens will be delivered to XCHAIN and deposited to theExchange
contract on behalf of the destination wallet.
Get Deposits
Returns information about deposits made by a wallet.
- HTTP Request:
GET /v4/deposits
- Endpoint Security: User Data
- API Key Scope: Read
- Pagination:
start
,end
,limit
,fromId
Request Parameters
$ curl "https://api.idex.io/v4/deposits?nonce=931d0240-9ee6-11ea-916a-4520a9090bcd&wallet=0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Depositing wallet address |
depositId | string | No | None | Single depositId to return |
start | integer | No | None | Timestamp of the earliest (oldest) deposit, inclusive, only applies if depositId is absent |
end | integer | No | None | Timestamp of the latest (newest) deposit, inclusive, only applies if depositId is absent |
limit | integer | No | 50 | Maximum number of deposits to return, 1-1,000, only applies if depositId is absent |
fromId | string | No | None | depositId of the earliest (oldest) deposit, only applies if depositId is absent |
- If none of
start
,end
, orfromId
is specified, the most recent trades are returned. See pagination for more details.
Response Array Objects
JSON response
[
{
"depositId": "57f88930-a6c7-11ea-9d9c-6b2dc98dcc67",
"asset": "USDC",
"quantity": "25000.00000000",
"bridgeSource": "stargate.ethereum",
"time": 1705784186231,
"bridgeTxId": "0x...",
"xchainTxId": "0x..."
},
...
]
Field | Type | Description |
depositId | string | Deposit identifier |
asset | string | Symbol of the deposited asset, always USDC |
quantity | string | Quantity of the deposit |
bridgeSource | string | Bridge and source chain of the deposit, see values |
time | integer | Timestamp of crediting the deposited funds on the exchange |
bridgeTxId | string | Transaction id of the Stargate v2 bridge transaction delivering funds to XCHAIN; also queryable for bridge details on https://layerzeroscan.com/ |
xchainTxId | string | Transaction id of the deposit transaction on XCHAIN |
Withdrawal Endpoints
Withdraw Funds
Withdraw funds from the exchange. Unlike deposits, withdrawals are initiated via this REST API endpoint. Once the withdrawal is validated, IDEX automatically dispatches the resulting transaction to return funds to the wallet.
- HTTP Request:
POST /v4/withdrawals
- Endpoint Security: Trade
- API Key Scope: Withdraw
- Pagination: None
Destination Chain Withdrawals
Similar to deposits, IDEX integrates with the Stargate v2 bridging protocol for fast, seamless cross-chain withdrawals with low protocol fees. Funds may be withdrawn to any of the destination blockchains listed under the withdrawal
field of Get Gas Fees. For a cross-chain withdrawal:
Populate the bridge adapter address and payload
const ethers = require('ethers');
// https://api.idex.io/v4/exchange
const exchangeStargateV2AdapterAddress =
'<ExchangeStargateV2Adapter contract address on XCHAIN>';
// https://docs.layerzero.network/v2/developers/evm/technical-reference/deployed-contracts#arbitrum
const arbitrumLayerZeroEndpointId = 30110;
const bridgeAdapterAddress = exchangeStargateV2AdapterAddress;
const bridgeAdapterPayload = ethers.AbiCoder.defaultAbiCoder().encode(
['uint32'],
[arbitrumLayerZeroEndpointId],
);
- Populate the
bridgeAdapterAddress
field with thestargateBridgeAdapterContractAddress
field returned by the Get Exchange endpoint. - Populate the
bridgeAdapterPayload
field with the ABI-encoded LayerZero endpoint ID of the desired destination chain. The correct endpoint IDs by destination chain are available in the Stargate V2 developer docs Mainnet Contracts list.
There are a few important considerations:
- Funds may only be withdrawn to destination chains listed under the
withdrawal
field of Get Gas Fees. - Gas required to bridge funds is deducted from the withdrawal amount in USDC. See Get Gas Fees for the prevailing rates.
- Stargate v2 additionally charges a fixed 6 basis point protocol fee that is deducted from the tokens delivered on the destination chain.
- If insufficient liquidity is available on the destination chain, withdrawal requests are rejected by the API. In the rare case of a bridging failure, the withdrawn funds are automatically redeposited into the exchange less gas fees for further use by the wallet.
For example, if a user wishes to withdraw 100.00000000
USDC from the exchange to Arbitrum and the current gas fee is 0.05000000
, then 99.95000000
USDC will be sent to the Stargate V2 bridge and 99.89003000
USDC will be delivered to the withdrawing wallet address on Arbitrum.
Request Parameters
Sample withdraw request payload
{
"parameters": {
"nonce": "43e74400-b7d9-11ee-b5b6-5d141649408f",
"wallet": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"quantity": "1000.00000000",
"maximumGasFee": "0.05000000",
"bridgeAdapterAddress": "0xB497DB22F82Cd4308F215518220d1fA76c459B8B",
"bridgeAdapterPayload": "0x...",
},
"signature": "<Wallet signature>"
}
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Depositing wallet address |
quantity | string | Yes | None | Quantity to withdraw |
maximumGasFee | string | Yes | None | Maximum gas fee authorized for the withdrawal in USDC |
bridgeAdapterAddress | string | No | None | Bridge contract adapter address; use stargateBridgeAdapterContractAddress from Get Exchange |
bridgeAdapterPayload | string | No | None | ABI-encoded destination chain, see Destination Chain Withdrawals |
Standard withdrawal JSON response
[
{
"withdrawalId": "3ac67790-a77c-11ea-ae39-b3356c7170f3",
"asset": "USDC",
"quantity": "1000.00000000",
"gas": "0.05000000",
"bridgeTarget": "stargate.arbitrum",
"time": 1705785508061,
"xchainTxId": "0x...",
"xchainTxStatus": "mined"
},
...
]
Field | Type | Description |
withdrawalId | string | Exchange-assigned withdrawal identifier |
asset | string | Symbol of the withdrawn asset |
quantity | string | Quantity of the withdrawal |
gas | string | Amount deducted from withdrawal to cover IDEX-paid gas |
bridgeTarget | string | Bridge and target chain of the withdrawal, see values |
time | integer | Timestamp of withdrawal API request |
xchainTxId | string | Transaction id of the withdrawal transaction on XCHAIN or null if not yet assigned; also queryable for Stargate v2 bridge details on https://layerzeroscan.com/ |
xchainTxStatus | string | Status of the withdrawal transaction on XCHAIN, see values |
Get Withdrawals
Returns information about withdrawals to a wallet.
- HTTP Request:
GET /v4/withdrawals
- Endpoint Security: User Data
- API Key Scope: Read
- Pagination:
start
,end
,limit
,fromId
Request Parameters
$ curl "https://api.idex.io/v4/withdrawals?nonce=2d47f840-b7e1-11ee-9507-37a5f6456897&wallet=0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Withdrawing wallet address |
withdrawalId | string | No | None | Single withdrawalId to return |
start | integer | No | None | Timestamp of the earliest (oldest) withdrawal, inclusive, only applies if withdrawalId absent |
end | integer | No | None | Timestamp of the latest (newest) deposit, inclusive, only applies if withdrawalId is absent |
limit | integer | No | 50 | Maximum number of deposits to return, 1-1,000, only applies if withdrawalId is absent |
fromId | string | No | None | withdrawalId of the earliest (oldest) deposit, only applies if withdrawalId is absent |
- If none of
start
,end
, orfromId
is specified, the most recent withdrawals are returned. See pagination for more details.
Response
This endpoint responds with either a single standard withdrawal response object, or an array of standard withdrawal response objects.
Get Gas Fees
Returns gas fee information. Because IDEX dispatches withdrawal transactions, IDEX pays for gas. This cost is deducted from the withdrawn amount as explained in Fees.
- HTTP Request:
GET /v4/gasFees
- Endpoint Security: Public
- API Key Scope: None required, an API Key increases rate limits
- Pagination: None
Request Parameters
$ curl "https://api.idex.io/v4/gasFees"
None
Response Object
JSON response
{
"withdrawal": {
"xchain.xchain": "0.05000000",
"stargate.arbitrum": "0.07008588",
"stargate.base": "0.05952947",
"stargate.ethereum": "2.26606465",
"stargate.optimism": "0.05289090"
}
}
Field | Nested Field | Type | Description |
withdrawal | xchain.xchain | string | Gas fee for withdrawals to XCHAIN |
stargate.arbitrum | string | Gas fee for withdrawals to Arbitrum via Stargate | |
stargate.base | string | Gas fee for withdrawals to Base via Stargate | |
stargate.ethereum | string | Gas fee for withdrawals to Ethereum via Stargate | |
stargate.optimism | string | Gas fee for withdrawals to Optimism via Stargate |
- Gas fees are estimates denominated in USDC.
- Withdrawal gas fees are capped via Withdraw Funds
maximumGasFee
parameter and are deducted from the quantity delivered in a withdrawal.
Exit Wallet
const fs = require("fs");
const ethers = require("ethers");
async function exitWallet() {
const walletAddress = "<Wallet address>";
const idexAddress = "<IDEX exchange contract address>";
const txOptions = { gasPrice: ethers.parseUnits("<Gas price in gwei>", "gwei") };
// Connect a wallet to mainnet
const provider = new ethers.JsonRpcProvider("<XCHAIN RPC>");
const walletWithProvider = new ethers.Wallet("<Wallet private key>", provider);
// Load contract
const idexAbi = JSON.parse(fs.readFileSync("Exchange_v4.abi.json"));
const idexContract = new ethers.Contract(idexAddress, idexAbi, walletWithProvider);
console.log("Exiting wallet...")
const exitWalletTx = await idexContract.exitWallet(txOptions);
console.log(`Dispatched exit ${exitWalletTx.hash} awaiting mine...`);
await exitWalletTx.wait();
console.log("Mined");
// Wait 24 hours, then
const withdrawExitTx = await idexContract.withdrawExit(walletAddress, txOptions);
console.log(`Dispatched withdraw ${withdrawExitTx.hash} awaiting mine...`);
await withdrawExitTx.wait();
console.log("Mined");
}
exitWallet();
While the Withdraw Funds REST API endpoint is the standard way to withdraw funds from the exchange, the exchange smart contract also includes a direct withdrawal mechanism. Funds can always be withdrawn directly from the contract, even if IDEX is offline or otherwise unresponsive.
The exit withdrawal mechanism automatically closes all open positions for a wallet. Importantly, in order to ensure the solvency of the system, positions are closed using exit pricing and may result in a lower returned equity than standard withdrawals.
- Exchange Contract (XCHAIN): 0x08ea6C351d08fAc8E177267898612A5fc6D92349
- Sandbox Exchange Contract (XCHAIN Testnet): 0xBB9A5455869e99652D13Cd0aE1E45dc3A2e9914B
ABIs for interacting with the exchange contracts are available in the official JavaScript SDK repo.
Exit Withdrawals require several smart contract function calls.
- Call the
exitWallet
function on the IDEX exchange contract. All future deposits, trades, and standard withdrawals are blocked. Any open orders associated with the wallet are cleared from the order books, and any open positions are closed at the exit price. - Wait 1 hour.
- Call the
withdrawExit
function with the wallet address. The exchange contract transfers the wallet’s USDC quote balance back to the wallet.
Rewards Endpoints
Get Market Maker Rewards Epoch List
Returns information about all market maker rewards epochs.
- HTTP Request:
GET /v4/marketMakerRewardsV1/epochs
- Endpoint Security: User Data
- API Key Scope: Read
- Pagination: None
Request Parameters
$ curl "https://api.idex.io/v4/marketMakerRewardsV1/epochs?nonce=30bd4470-bd69-11ee-97ca-77c58d38b233" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
Response Array Objects
JSON response
[
{
"epochId": 12,
"startsAt": "1704067200000",
"endsAt": "1705276799999",
"reviewEndsAt": "1705881599999"
},
...
]
Field | Type | Description |
epochId | string | Epoch identifier |
startsAt | integer | Timestamp of the epoch start |
endsAt | integer | Timestamp of the epoch end |
reviewEndsAt | integer | Timestamp of the epoch review period end |
Get Market Maker Rewards Epoch
Returns detailed information about a market maker rewards epoch configuration as well as wallet epoch performance.
- HTTP Request:
GET /v4/marketMakerRewardsV1/epoch
- Endpoint Security: User Data
- API Key Scope: Read
- Pagination: None
Request Parameters
$ curl "https://api.idex.io/v4/marketMakerRewardsV1/epoch?nonce=f56456b0-bd6e-11ee-b51e-9f55b06014d6&epochId=12&wallet=0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
epochId | string | No | None | Epoch identifier; if no epochId is supplied, the currently active epoch is returned if present |
wallet | string | No | None | Wallet address |
Response Object
JSON response
{
"epochId": 12,
"startsAt": "1704067200000",
"endsAt": "1705276799999",
"reviewEndsAt": "1705881599999",
"previousEpochReviewEndsAt": "1704671999999",
"totalRewardQuantity": "1000000.00000000",
"eligibilityVolumeRequirementPercent": "0.00500000",
"nextEpochEligibilityVolumeRequirementPercent": "0.00500000",
"alpha": "0.62000000",
"beta": "2.50000000",
"isWalletEligibleInEpoch": true,
"walletScorePercent": "0.12291563",
"walletRewardQuantity": "122915.63240000",
"walletRewardVolumePercent": "0.10432254",
"walletEligibilityVolumePercent": "0.09784802",
"markets": [
{
"market": "ETH-USD",
"rewardQuantity": "500000.00000000",
"maximumQualifiedOrderDistancePercent": "0.01000000",
"minimumQualifiedOrderQuantity": "1000.00000000",
"walletDepthScore": "6048991461.00000000",
"walletUptimePercent": "0.74980000",
"walletRewardVolumePercent": "0.08979059",
"walletEligibilityVolumePercent": "0.08234663",
"walletScorePercent": "0.09134663",
"walletRewardQuantity": "45673.31750000"
},
...
]
}
Field | Type | Optional | Description |
epochId | string | No | Epoch identifier |
startsAt | integer | No | Timestamp of the epoch start |
endsAt | integer | No | Timestamp of the epoch end |
reviewEndsAt | integer | No | Timestamp of the epoch review period end |
previousEpochReviewEndsAt | integer | Yes | Timestamp of the previous epoch’s review period end, only present if the value is in the future, i.e. the system is currently awaiting the previous epoch end |
totalRewardQuantity | string | No | Total token reward quantity |
eligibilityVolumeRequirementPercent | string | Yes | Qualified volume percent setting for the current epoch if defined. Wallet qualified maker volume for the prior epoch must meet or exceed this value as a percent of overall qualified maker volume to be eligible for the current epoch’s rewards. Omitted if no eligibility percent is defined for the epoch. |
nextEpochEligibilityVolumeRequirementPercent | string | Yes | Qualified volume percent setting for the next epoch if defined |
alpha | string | No | Score parameter |
beta | string | No | Score parameter |
isWalletEligibleInEpoch | boolean | Yes | true if wallet is eligible to earn rewards in the epoch, omitted for epochs that have not yet started. |
walletScorePercent | string | Yes | Epoch’s wallet score as a percent. For currently active epochs, this is the wallet’s estimated score at last cache time. |
walletRewardQuantity | string | Yes | Epoch’s wallet token reward quantity. For currently active epochs, this is the wallet’s estimated token reward quantity at last cache time. |
walletRewardVolumePercent | string | Yes | Epoch’s wallet qualified maker volume percent relative to eligible wallet qualified maker volume. This value is used as part of the current epoch’s reward calculation. |
walletEligibilityVolumePercent | string | Yes | Current epoch’s wallet qualified maker volume percent relative to total qualified maker volume. Wallet is eligible for the next epoch awards if this value exceeds nextEpochEligibilityVolumeRequirementPercent . |
markets | array | No | Array of epoch market objects |
Epoch Markets Array Objects
Field | Type | Optional | Description |
market | string | No | Market symbol |
rewardQuantity | string | No | Token reward quantity for the market |
maximumQualifiedOrderDistancePercent | string | No | Maximum qualified order distance from the midpoint of the spread as a percent |
minimumQualifiedOrderQuantity | string | No | Minimum qualified order quantity in quote terms |
walletDepthScore | string | Yes | Epoch’s wallet depth score for the market |
walletUptimePercent | string | Yes | Epoch’s wallet “uptime” score for the market as a percent |
walletRewardVolumePercent | string | Yes | Epoch’s wallet qualified maker volume for the market as a percent relative to eligible wallet qualified maker volume |
walletEligibilityVolumePercent | string | Yes | Epoch’s wallet qualified maker volume for the market as a percent relative to total qualified maker volume |
walletScorePercent | string | Yes | Epoch’s wallet score for the market as a percent |
walletRewardQuantity | string | Yes | Epoch’s wallet token reward quantity for the market |
- For currently active epochs, the
wallet*
fields return estimated values computed at last cache time.
Get Payouts
Returns information about the quantities earned and paid for the specified reward program.
Request Parameters
$ curl "https://api.idex.io/v4/payouts?nonce=5c821700-b7e4-11ee-9bb1-3d5efe3ca5f9&wallet=0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d&program=marketMakerRewards" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Wallet address |
program | string | Yes | None | Reward program name, tradingRewardsV2 or marketMakerRewards |
Response Object
JSON response
{
"assetAddress": "0x...",
"assetSymbol": "IDEX",
"escrowContractAddress": "0x...",
"quantityEarned": "1007.10901717",
"quantityPaid": "0.00000000",
"quantityOwed": "1007.10901717"
}
Field | Type | Description |
assetAddress | string | Contract address of the reward asset |
assetSymbol | string | Symbol of the reward asset |
escrowContractAddress | string | Address of the escrow contract |
quantityEarned | string | Total quantity earned for the wallet in the reward program |
quantityPaid | string | Total quantity paid to the wallet for the reward program |
quantityOwed | string | Quantity claimable by the wallet for the reward program |
Authorize Payout
Generate a payout authorization for the outstanding balance for the specified reward program.
Request Parameters
$ curl "https://api.idex.io/v4/payouts?nonce=1fb1c850-b7e6-11ee-8fb7-f5219a323177&wallet=0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d&program=marketMakerRewards" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Wallet address |
program | string | Yes | None | Reward program name, tradingRewardsV2 or marketMakerRewards |
Response Object
JSON response
{
"assetAddress": "0x...",
"assetSymbol": "IDEX",
"escrowContractAddress": "0x...",
"distribution": {
"nonce": "0d50c6b0-b7e7-11ee-a73d-815e4aa7e3b3",
"parentNonce": "0cecfbd0-b7e7-11ee-b1bb-c5414d03e411",
"walletAddress": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"assetAddress": "0x...",
"quantity": "1007.10901717",
"exchangeSignature": "0x85cb1df15f2ac2256f52df8681c8cd79405241097d66c55d5a34d62c69941cd36bce6baa6f06d942bb821d5e4b15f28498c2b182d7ba11d4330119383ea1f6da1c"
}
}
Field | Nested Field | Type | Description |
assetAddress | string | Contract address of the reward asset | |
assetSymbol | string | Symbol of the reward asset | |
escrowContractAddress | string | Address of the escrow contract | |
distribution | nonce | string | Payout distribution fields to be provided to the escrow contract’s distribute function |
parentNonce | string | ||
walletAddress | string | ||
assetAddress | string | ||
quantity | string | ||
exchangeSignature | string |
Claim Payout
Reward funds are escrowed in EarningsEscrow contracts hosted on Ethereum. Claim payouts by calling the distribute
function on the escrow contract at escrowContractAddress
using the distribution
field of the Authorize Payout response.
The ABI for interacting with EarningsEscrow contracts is available in the official JavaScript SDK repo.
- Call Authorize Payout on the IDEX REST API to retrieve the authorization necessary to claim rewards from the escrow contract.
- Call
distribute
on the EarningsEscrow contract atescrowContractAddress
on Ethereum using thedistribution
response object. The transaction must be sent by the wallet specified bydistribution.walletAddress
, and rewards funds are sent to the calling wallet.
WebSocket Authentication Endpoints
Get Authentication Token
Returns a single-use authentication token for access to private subscriptions in the WebSocket API.
Request Parameters
$ curl "https://api.idex.io/v4/wsToken?nonce=b42758f0-b7e7-11ee-95d1-bdf3011d0d73&wallet=0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d" \
-H "IDEX-API-KEY: <API key>" \
-H "IDEX-HMAC-SIGNATURE: <HMAC signature>"
Parameter | Type | Required | Default | Description |
nonce | string | Yes | None | Request nonce |
wallet | string | Yes | None | Wallet address |
Response Object
JSON response
{
"token": "<WebSocket authentication token>"
}
Field | Type | Description |
token | string | WebSocket subscription authentication token |
WebSocket API Interaction
The IDEX WebSocket API provides the most up-to-date public market and authenticated user data. It is the recommended integration point for time-sensitive applications.
URL
WebSocket API: wss://websocket.idex.io/v4
Sandbox WebSocket API: wss://websocket-sandbox.idex.io/v4
IDEX’s data centers are in the AWS Asia Pacific (Tokyo) ap-northeast-1
region. A sandbox environment is also available for development and testing.
Frame Encoding
Frames sent from the server include at least one JSON object with two top-level keys:
type: The subscription type of the message
data: The data payload of the message, also a JSON object
The server may send more than one JSON object in a single frame. The data object uses case-sensitive one or two-letter keys that map to equivalent REST API response object fields.
Subscriptions
Subscriptions specify which data is pushed to the client. Clients can subscribe either at connection time, via the supplied path, or by sending subscription message frames once connected.
Path Subscriptions
To subscribe to the
tickers
subscription for the ETH-USD via connection path:
$ wscat -c wss://websocket.idex.io/v4/ETH-USD@tickers
Path subscriptions are a quick and easy way to start receiving push updates. The WebSocket API interprets the URL path supplied at connection time to set an initial subscription.
Path subscription notation: wss://websocket.idex.io/v4/{market}@{subscription}_{option}
For example, to connect to the WebSocket API and start receiving tickers
updates for the ETH-USD market, connect to wss://websocket.idex.io/v4/ETH-USD@tickers
. For subsciptions that require option parameters, such as candles, use the option notation wss://websocket.idex.io/v4/ETH-USD@candles_15m
.
Only a single, non-authenticated subscription may be included in the path.
Frame Subscriptions
Sample
subscribe
frame for 1 minute candles for the ETH-USD market:
{
"method": "subscribe",
"subscriptions": [
{
"name": "candles",
"markets": ["ETH-USD"],
"interval": "1m"
}
]
}
There is also a shorthand for
subscribe
frames wheremarkets
are specified at the top level, resulting in subscriptions for all listed markets.
{
"method": "subscribe",
"markets": ["BTC-USD", "ETH-USD"],
"subscriptions": [
"tickers",
"trades"
]
}
Mixing both formats is valid, in which case, the markets defined at the subscription level take precedence.
{
"method": "subscribe",
"markets": ["BTC-USD", "ETH-USD"],
"subscriptions": [
"tickers",
"trades",
{
"name": "candles",
"markets": ["ETH-USD"],
"interval": "1m"
}
]
}
In the above example, a
candles
subscription applies only to the ETH-USD market.
Clients can subscribe, unsubscribe, and list any subscriptions by sending method frames.
Subscribe Request
After connecting, clients can initiate subscriptions by sending a subscribe
frame. subscribe
frames specify the requested subscriptions, applicable markets, and any subscription-specific options.
Request Frame Fields
Parameter | Type | Required | Default | Description |
cid | string | No | None | Customer-supplied request identifier; this value is included in response frames to the request if specified |
method | string | Yes | None | Subscription action, subscribe |
token | string | No | None | Authentication token, required for Deposits, Withdrawals, Positions, Funding Payments, and Orders subscriptions |
markets | array | No | None | Array of market symbols to apply to the specified subscriptions |
subscriptions | array | Yes | None | Array of subscription objects |
Subscription Request Object Fields
Parameter | Type | Required | Default | Description |
name | string | Yes | None | Subscription name |
markets | array | No | None | Array of market symbols for the subscription, optional if markets is defined at the top level |
* | Any additional options specific to the subscription |
subscribe
requests receive the standard frame subscription response.- Multiple subscribe requests are additive in that new subscriptions are added to the subscribed set.
Unsubscribe Request
{
"method": "unsubscribe",
"markets": ["ETH-USD"],
"subscriptions": [
"tickers",
"trades"
]
}
unsubscribe
requests follow the same format as subscribe
, but with additional flexibility. If the top-level markets
parameter is omitted, any listed subscriptions without specified markets are removed from all markets. If the top-level subscriptions
field is omitted, the top-level markets are removed from all subscriptions. Listing neither markets
nor subscriptions
at the top level unsubscribes all.
unsubscribe
requests receive the standard frame subscription response.
List Subscriptions Request
Returns the connection’s active subscriptions.
Request Frame Fields
{
"method": "subscriptions"
}
Parameter | Type | Required | Default | Description |
cid | string | No | None | Customer-supplied request identifier; this value is included in response frames to the request |
method | string | Yes | None | List subscriptions action, subscriptions |
subscriptions
requests receive the standard frame subscription response.
Frame Subscription Response
Standard subscription response frame. The response to
subscribe
requests includes all active subscriptions.
{
"type": "subscriptions",
"subscriptions": [
{
"name": "tickers",
"markets": [
"BTC-USD",
"ETH-USD"
]
},
{
"name": "trades",
"markets": [
"BTC-USD",
"ETH-USD"
]
},
{
"name": "candles",
"markets": ["ETH-USD"],
"interval": "1m"
}
]
}
All subscribe
, unsubscribe
, and subscriptions
requests return a standard response frame that enumerates active subscriptions.
Response Frame Fields
Field | Type | Description |
cid | string | Customer-supplied request identifier, only included if specified in the request |
type | string | Frame type, always subscriptions |
subscriptions | array | Array of subscription response objects |
Subscription Response Object Fields
Field | Type | Description |
name | string | Subscription name |
markets | array | Array of market symbols for the subscription |
* | Any additional options specific to the subscription |
Authenticated Subscriptions
{
"method": "subscribe",
"token": "<WebSocket authentication token>",
"subscriptions": ["positions"]
}
User authentication is required for the Deposits, Withdrawals, Positions, Funding Payments, and Orders subscriptions. Authentication is specified on a per-subscribe basis via a single-use authentication token.
Tokens are generated via the Get Authentication Token endpoint and are valid for 15 minutes, good for a one-time subscription request to an arbitrary number of subscriptions within a single subscribe, and good for the life of the subscription
Connection Maintenance
The WebSocket API includes several mechanisms to reduce stale connections.
- The server sends a ping frame every 3 minutes. The server must receive a pong frame from the client within a 10 minute period. Additional pongs are ignored by the server.
- Connections to the WebSocket API are only valid for 24 hours and automatically disconnect at 24 hours.
- WebSocket connections are terminated by the server after 60 seconds without a subscription.
Errors
{
"type": "error",
"data": {
"code": "<Error short code>",
"message": "<Error message>"
}
}
Errors are only expected in response to invalid client subscription requests. Error frames use type error
and include both code
, a machine-readable error short code, and message
, a longer human-readable error description.
WebSocket Subscriptions
Ping
Tests connectivity to the WebSocket API. All clients are automatically subscribed to Ping on connection.
- Subscription: None
- Request Parameters: None
- Authentication: None
- Update Speed: 3 minutes
Message Object
{
"type": "ping",
"data": {}
}
Empty JSON object
Tickers
Provides ticker data updates for a market.
- Subscription:
tickers
- Request Parameters:
markets
array - Authentication: None
- Update Speed: 1 second
Message Object
{
"type": "tickers",
"data": {
"m": "ETH-USD",
"t": 1704153660000,
"o": "2282.87000000",
"h": "2427.56000000",
"l": "2273.63000000",
"c": "2352.59000000",
"Q": "9.50000000",
"v": "118000.31500000",
"q": "275058735.17000000",
"P": "0.03054050",
"n": 31201,
"a": "2352.63000000",
"b": "2352.61000000",
"mp": "2352.61000000",
"ip": "2353.01000000",
"id": "2281.94000000",
"iP": "0.03114455",
"lf": "0.00017100",
"nf": "0.00010000",
"ft": 1704182400000,
"oi": "57178.63200000",
"u": 848728
}
}
Field | Inflated Field | Type | Description |
m | market | string | Market symbol |
t | time | integer | Timestamp when the statistics were computed, the opening time of the period is 24 hours prior |
o | open | string | Price of the first trade in the period in quote terms |
h | high | string | Highest traded price in the period in quote terms |
l | low | string | Lowest traded price in the period in quote terms |
c | close | string | Price of the last trade in the period in quote terms |
Q | closeQuantity | string | Quantity of the last trade in th period in base terms |
v | baseVolume | string | Trailing 24-hour trading volume in base terms |
q | quoteVolume | string | Trailing 24-hour trading volume in quote terms |
P | percentChange | string | Percentage change from open price to close price |
n | trades | integer | Number of trades in the period |
a | ask | string | Best ask price on the order book in quote terms |
b | bid | string | Best bid price on the order book in quote terms |
mp | markPrice | string | Current mark price |
ip | indexPrice | string | Current index price |
id | indexPrice24h | string | Index price 24h ago |
iP | indexPricePercentChange | string | Percent change in index price from 24h ago to current |
lf | lastFundingRate | string | Funding rate of the last payment |
nf | currentFundingRate | string | Current funding rate |
ft | nextFundingTime | integer | Timestamp of the next funding payment |
oi | openInterest | string | Current open interest |
u | sequence | integer | Fill sequence number of the last trade in the period |
- No ticker updates are sent for periods when no trades occur.
Candles
Provides candle (OHLCV) data updates for a market.
- Subscription:
candles
- Request Parameters:
markets
array,interval
(see Interval Values) - Authentication: None
- Update Speed: 1 second
Message Object
{
"type": "candles",
"data": {
"m": "ETH-USD",
"t": 1704067200000,
"i": "1d",
"s": 1703980800000,
"e": 1704067200000,
"o": "2282.87000000",
"h": "2427.56000000",
"l": "2273.63000000",
"c": "2352.59000000",
"v": "118000.31500000",
"q": "275058735.17000000",
"n": 31201,
"u": 848678
}
}
Field | Inflated Field | Type | Description |
m | market | string | Market symbol |
t | time | integer | Timestamp when the statistics were computed, time is always between the start and end timestamps of the interval |
i | interval | string | Interval duration, see Interval Values |
s | start | integer | Timestamp of the start of the interval |
e | end | integer | Timestamp of the end of the interval |
o | open | string | Price of the first trade in the interval in quote terms |
h | high | string | Highest traded price in the interval in quote terms |
l | low | string | Lowest traded price in the interval in quote terms |
c | close | string | Price of the last trade in the interval in quote terms |
v | baseVolume | string | Trading volume in the interval in base terms |
q | quoteVolume | string | Trading volume in the interval in quote terms |
n | trades | integer | Number of trades in the candle |
u | sequence | integer | Fill sequence number of the last trade in the interval |
- No candle object is opened or updated for intervals when no trades occur.
Trades
Provides real-time trade data for a market. In this documentation, "trades" refers to public information about trades, whereas "fills" refers to detailed non-public information about trades resulting from orders placed by the API account.
- Subscription:
trades
- Request Parameters:
markets
array - Authentication: None
- Update Speed: Real time, updates on new trades
Message Object
{
"type": "trades",
"data": {
"m": "ETH-USD",
"i": "cfd05df0-b4df-11ee-aed5-c788337a7b62",
"p": "2375.22000000",
"q": "10.00000000",
"Q": "23752.20000000",
"t": 1704067200050,
"s": "sell",
"u": 844323
}
}
Field | Inflated Field | Type | Description |
m | market | string | Market symbol |
i | fillId | string | Trade identifier |
p | price | string | Price of the trade in quote terms |
q | quantity | string | Quantity of the trade in base terms |
Q | quoteQuantity | string | Quantity of the trade in quote terms |
t | time | integer | Timestamp of the trade |
s | makerSide | string | Maker side of the trade, buy or sell |
u | sequence | integer | Fill sequence number of the trade |
- The Trades subscription only includes order book fills. See Liquidations for liquidations and ADL actions.
Liquidations
Provides real-time liquidation data for a market. Unlike trades, liquidations do not contribute to trading volume and are not included in tickers or candles.
- Subscription:
liquidations
- Request Parameters:
markets
array - Authentication: None
- Update Speed: Real time, updates on new liquidations
Message Object
{
"type": "liquidations",
"data": {
"m": "ETH-USD",
"i": "e5132d50-b4df-11ee-815e-51c714db211c",
"p": "2113.90000000",
"q": "3.50000000",
"Q": "7398.65000000",
"t": 1704067224778,
"s": "sell"
}
}
Field | Inflated Field | Type | Description |
m | market | string | Market symbol |
i | fillId | string | Liquidation identifier |
p | price | string | Price of the liquidation in quote terms |
q | quantity | string | Quantity of the liquidation in base terms |
Q | quoteQuantity | string | Quantity of the liquidation in quote terms |
t | time | integer | Timestamp of the liquidation |
s | liquidationSide | string | Liquidation side of the settlement, buy or sell |
L1 Order Book
Provides real-time level-1 order book data for a market. Level-1 order book data is limited to the best bid and ask for a market.
- Subscription:
l1orderbook
- Request Parameters:
markets
array - Authentication: None
- Update Speed: Real time; updates on new best ask, best bid, quantities, or pricing
Message Object
{
"type": "l1orderbook",
"data": {
"m": "ETH-USD",
"t": 1705797717794,
"b": "2352.61000000",
"B": "13.88204000",
"a": "2352.63000000",
"A": "8.11400000",
"lp": "2352.60000000",
"mp": "2352.61000000",
"ip": "2353.01000000"
}
}
Field | Inflated Field | Type | Description |
m | market | string | Market symbol |
t | time | integer | Timestamp of the order book update |
b | bidPrice | string | Best bid price |
B | bidQuantity | string | Quantity available at the best bid price |
a | askPrice | string | Best ask price |
A | askQuantity | string | Quantity available at the best ask price |
lp | lastPrice | string | Last trade price |
mp | markPrice | string | Mark price |
ip | indexPrice | string | Index price |
L2 Order Book
Provides real-time level-2 order book data for a market. Level-2 order book data includes price and quantity information for all limit order price levels in the order book.
- Subscription:
l2orderbook
- Request Parameters:
markets
array - Authentication: None
- Update Speed: Real time, updates on any order book or pricing change
Message Object
{
"type": "l2orderbook",
"data": {
"m": "ETH-USD",
"t": 1705797717821,
"u": 71228122,
"b": [["2352.60000000", "10.00000000", 1]],
"a": [],
"lp": "2352.60000000",
"mp": "2352.61000000",
"ip": "2353.01000000"
}
}
Field | Inflated Field | Type | Description |
m | market | string | Market symbol |
t | time | integer | Timestamp of the order book update |
u | sequence | integer | Order book update sequence number of the update |
b | bids | array | Array of bid price level updates |
a | asks | array | Array of ask price level updates |
lp | lastPrice | string | Last trade price |
mp | markPrice | string | Mark price |
ip | indexPrice | string | Index price |
- Price level updates are arrays of the form
[ {price level in quote terms}, {quantity available in base terms}, {number of orders} ]
. A price level update with 0 quantity indicates the price level should be deleted from the order book.
Deposits
Provides real-time deposit information for a wallet.
- Subscription:
deposits
- Request Parameters: None
- Authentication: token
- Update Speed: Real time, updates sent on deposit confirmation
Message Object
{
"type": "deposits",
"data": {
"w": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"i": "57f88930-a6c7-11ea-9d9c-6b2dc98dcc67",
"a": "USDC",
"q": "25000.00000000",
"qb": "87841.77508743",
"t": 1705784186231
}
}
Field | Inflated Field | Type | Description |
w | wallet | string | Wallet address |
i | depositId | string | Deposit identifier |
a | asset | string | Asset symbol, always USDC |
q | quantity | string | Quantity of the deposit |
qb | quoteBalance | string | Quote token balance after the deposit |
t | time | integer | Timestamp of crediting the deposited funds on the exchange |
Withdrawals
Provides real-time withdrawal information for a wallet.
- Subscription:
withdrawals
- Request Parameters: None
- Authentication: token
- Update Speed: Real time, updates sent on withdrawal debit
Message Object
{
"type": "withdrawals",
"data": {
"w": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"i": "3ac67790-a77c-11ea-ae39-b3356c7170f3",
"a": "USDC",
"q": "1000.00000000",
"g": "0.05000000",
"qb": "86841.72508743",
"t": 1705785508061
}
}
Field | Inflated Field | Type | Description |
w | wallet | string | Wallet address |
i | withdrawalId | string | Withdrawal identifier |
a | asset | string | Asset symbol, always USDC |
q | quantity | string | Quantity of the withdrawal |
g | gas | string | Amount collected to cover withdrawal settlement gas costs in quote terms |
qb | quoteBalance | string | Quote token balance after the withdrawal |
t | time | integer | Timestamp of debiting the withdrawn from the exchange |
Positions
Provides real-time position change information for a wallet.
- Subscription:
positions
- Request Parameters: None
- Authentication: token
- Update Speed: Real time, updates sent on any position change
Message Object
{
"type": "positions",
"data": {
"w": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"m": "ETH-USD",
"X": "open",
"q": "3.00000000",
"mq": "3.00000000",
"np": "2000.00000000",
"xp": "0.00000000",
"rn": "-15.42000000",
"f": "-17.82000000",
"to": "3.00000000",
"tc": "0.00000000",
"of": "da107420-b742-11ee-81fc-256a7a814967",
"lf": "da107420-b742-11ee-81fc-256a7a814967",
"qb": "87841.77508743",
"t": 1699488727919
}
}
Field | Inflated Field | Type | Description |
w | wallet | string | Wallet address |
m | market | string | Market symbol |
X | status | string | open or closed , only closed on last update |
q | quantity | string | Base quantity, negative for short positions |
mq | maximumQuantity | string | Maximum absolute quantity of the position during its existence |
np | entryPrice | string | Average entry price of the position |
xp | exitPrice | string | Average exit price of the position |
rn | realizedPnL | string | Realized PnL of the position in quote terms, includes funding payments |
f | totalFunding | string | Net total of all funding payments for the position |
to | totalOpen | string | Total of all trade quantities that increased the position in base terms |
tc | totalClose | string | Total of all trade quantities that decreased the position in base terms |
of | openedByFillId | string | Id of the fill that opened the position |
lf | lastFillId | string | Id of the fill that most recently updated the position |
qb | quoteBalance | string | Quote token balance |
t | time | integer | Timestamp of position opening |
Funding Payments
Provides real-time information about funding payments.
- Subscription:
fundingPayments
- Request Parameters: None
- Authentication: token
- Update Speed: Real time, updates sent on deposit confirmation
Message Object
{
"type": "fundingPayments",
"data": {
"w": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"m": "ETH-USD",
"Q": "-1.27090620",
"q": "3.00000000",
"f": "0.00017100",
"ip": "2477.40000000",
"t": 1705785508061
}
}
Field | Inflated Field | Type | Description |
w | wallet | string | Wallet address |
m | market | string | Market symbol |
Q | paymentQuantity | string | Quantity of the funding payment in quote terms |
q | positionQuantity | string | Quantity of the open position at payment time in base terms |
f | fundingRate | string | Funding rate for the period |
ip | indexPrice | string | Index price of the market at payment time |
t | time | integer | Timestamp of debiting the withdrawn from from the exchange |
Orders
Provides real-time updates on orders placed by a wallet and its delegated keys. This subscription includes granular updates for all order-related activity, including placement, cancellation, fills and stop triggers. Detailed order execution information is only available to the placing wallet. In this documentation, "trades" refers to public information about trades, whereas "fills" refers to detailed non-public information about trades resulting from orders placed by the API account.
This subscription also provides real-time updates on liquidations and ADL actions. Because these actions are not initiated by an order, they only include a subset of the update message fields. Message definitions for liquidations and ADL actions follow the primary message objects.
- Subscription:
orders
- Request Parameters: None
- Authentication: token
- Update Speed: Real time, updates on any state change of an order placed by the wallet
Orders Subscription Order Message
{
"type": "orders",
"data": {
"m": "ETH-USDC",
"i": "92782120-a775-11ea-aa55-4da1cc97a06d",
"w": "0xA71C4aeeAabBBB8D2910F41C2ca3964b81F7310d",
"t": 1705778379471,
"T": 1705778379471,
"x": "fill",
"X": "filled",
"u": 71228108,
"o": "market",
"s": "buy",
"q": "10.00000000",
"z": "10.00000000",
"Z": "24609.40000000",
"v": "2460.94000000",
"r": false,
"V": "dc",
"F": [
{
"i": "974480d0-a776-11ea-895b-bfcbb5bdaa50",
"p": "2460.94000000",
"q": "3.78500000",
"Q": "9314.65790000",
"t": 1705778379471,
"s": "sell",
"u": 981372,
"f": "3.72586316",
"l": "taker",
"a": "open",
"P": "long",
"y": "market",
"T": "0x01d28c33271cf1dd0eb04249617d3092f24bd9bad77ffb57a0316c3ce5425158",
"S": "mined"
},
...
]
}
}
Field | Inflated Field | Type | Optional | Description |
m | market | string | No | Market symbol |
i | orderId | string | No | Exchange-assigned order identifier |
c | clientOrderId | string | Yes | Client-specified order identifier |
w | wallet | string | No | Wallet address |
t | executionTime | integer | No | Timestamp of the most recent update |
T | time | integer | No | Timestamp of initial order processing by the matching engine |
x | update | string | No | Type of order update, see values |
X | status | string | No | Order status, see values |
u | sequence | integer | Yes | order book update sequence number, only included if update type triggers an order book update |
ec | errorCode | string | Yes | Error short code explaining forced cancellation condition |
em | errorMessage | string | Yes | Error description explaining forced cancellation condition |
o | type | string | No | Order type, see values |
s | side | string | No | Order side, buy or sell |
q | originalQuantity | string | No | Original quantity specified by the order in base terms |
z | executedQuantity | string | No | Quantity that has been executed in base terms |
Z | cumulativeQuoteQuantity | string | Yes | Cumulative quantity that has been spent (buy orders) or received (sell orders) in quote terms, omitted if unavailable for historical orders |
v | avgExecutionPrice | string | Yes | Weighted average price of fills associated with the order; only present with fills |
p | price | string | Yes | Original price specified by the order in quote terms, omitted for all market orders |
P | triggerPrice | string | Yes | Stop loss or take profit price for stopLossMarket , stopLossLimit , takeProfitMarket , and takeProfitLimit orders, omitted for others |
tt | triggerType | string | Yes | Price type for triggerPrice, last or index; only present with triggerPrice |
r | reduceOnly | string | No | Reduce only orders are only accepted opposite open positions and only reduce an opposite position’s size |
f | timeInForce | string | Yes | Time in force policy, see values, only present for limit orders |
V | selfTradePrevention | string | No | Self-trade prevention policy, see values |
dk | delegatedKey | string | Yes | Delegated key if present |
F | fills | array | Yes | Array of order fill objects |
Orders Subscription Order Fills Objects
Field | Inflated Field | Type | Description |
i | fillId | string | Fill identifier |
p | price | string | Price of the fill in quote terms |
q | quantity | string | Quantity of the fill in base terms |
Q | quoteQuantity | string | Quantity of the fill in quote terms |
rn | realizedPnL | string | PnL realized by partial or complete closure of a position, omitted for open actions |
t | time | integer | Timestamp of the fill |
s | makerSide | string | Maker side of the fill, buy or sell |
u | sequence | integer | Fill sequence number |
f | fee | string | Fee amount collected on the fill in quote terms, may be negative due to promotions |
l | liquidity | string | Whether the fill is the maker or taker in the trade from the perspective of the requesting API account, maker or taker |
a | action | string | Whether the fill increases or decreases the notional value of the position, open or close |
P | position | string | Whether the resulting position is long , short , or none |
y | type | string | Fill type, see values |
T | txId | string | Transaction id of the trade settlement transaction or null if not yet assigned |
S | txStatus | string | Status of the trade settlement transaction, see values |
- Only fills generated in the most recent order execution are included in Orders subscription message objects. A complete list of fills associated with an order are available from the Get Orders REST API endpoint.
- When order execution triggers self-trade prevention, the Orders subscription message object may include a non-zero
executedQuantity
value without anyfills
objects, or thefills
objects may total less than theexecutedQuantity
.
Orders Subscription Liquidation Message
Liquidations and ADL action updates include a subset of order-based message fields.
Field | Inflated Field | Type | Optional | Description |
m | market | string | No | Market symbol |
w | wallet | string | No | Wallet address |
t | executionTime | integer | No | Timestamp of the most recent update |
s | side | string | No | Order side, buy or sell |
F | fills | array | Yes | Array of order fill objects |
Orders Subscription Liquidation Fills Objects
Field | Inflated Field | Type | Description |
i | fillId | string | Fill identifier |
p | price | string | Price of the fill in quote terms |
q | quantity | string | Quantity of the fill in base terms |
Q | quoteQuantity | string | Quantity of the fill in quote terms |
rn | realizedPnL | string | PnL realized by partial or complete closure of a position |
t | time | integer | Timestamp of the fill |
f | fee | string | Fee amount collected on the fill in quote terms, may be negative due to promotions |
a | action | string | Whether the fill increases or decreases the notional value of the position, open or close |
P | position | string | Whether the resulting position is long , short , or none |
y | type | string | Fill type, see values |
T | txId | string | Transaction id of the trade settlement transaction or null if not yet assigned |
S | txStatus | string | Status of the trade settlement transaction, see values |
Error Codes
General Request Errors
Code | Description |
---|---|
INTERNAL_SERVER_ERROR | Unknown server error. |
SERVICE_UNAVAILABLE | Service is not available to accept the request. |
BAD_REQUEST | Request validation failure, message contains condition. |
ENDPOINT_NOT_FOUND | Endpoint not found. |
EXCEEDED_RATE_LIMIT | Rate limit exceeded. |
INVALID_PARAMETER | Invalid request parameter, message contains condition. |
REQUIRED_PARAMETER | Required parameter not present in request. |
INVALID_NONCE_TIMING | Nonce does not meet request timing constraints. |
DEPOSIT_NOT_FOUND | Deposit not found. |
EPOCH_NOT_FOUND | Epoch not found. |
FILL_NOT_FOUND | Fill not found. |
FILL_PUBLIC_ID_NOT_FOUND | Fill not found using fromId. |
LIQUIDATION_PUBLIC_ID_NOT_FOUND | Liquidation not found using fromId. |
MARKET_NOT_FOUND | Market not found. |
ORDER_NOT_FOUND | Order not found. |
ORDER_PUBLIC_ID_NOT_FOUND | Order not found using fromId. |
PAYOUT_PROGRAM_NOT_FOUND | Payout Program not found. |
WALLET_NOT_FOUND | Wallet not found. |
WITHDRAWAL_NOT_FOUND | Withdrawal not found. |
WITHDRAWAL_PUBLIC_ID_NOT_FOUND | Withdrawal not found using fromId. |
Authentication Errors
Code | Description |
---|---|
REQUIRED_API_KEY | Missing API key. |
INVALID_API_KEY | Invalid API key. |
REQUIRED_HMAC_SIGNATURE | Missing HMAC signature. |
INVALID_HMAC_SIGNATURE | Invalid HMAC signature. |
INVALID_HMAC_SIGNATURE_PAYLOAD | HMAC signature is present but no corresponding payload. |
REQUIRED_API_KEY_TRADE_SCOPE | API key does not have the required Trade permissions. |
REQUIRED_API_KEY_WITHDRAW_SCOPE | API key does not have the required Withdrawal permissions. |
INVALID_WALLET_SIGNATURE | Invalid wallet signature. |
WALLET_NOT_ASSOCIATED | Wallet is not associated with API key account. |
WALLET_BLOCKED | Wallet prohibited from accessing IDEX. |
Order Placement Errors
Code | errorMessage |
---|---|
DUPLICATE_CLIENT_ORDER_ID | Duplicate clientOrderId . |
EXCESSIVE_SLIPPAGE | Execution price for market order exceeds market order price limit. See Get Markets marketOrderExecutionPriceLimit . |
INSUFFICIENT_FUNDS | Unable to place order due to insufficient available collateral. |
LIMIT_PRICE_CROSSES_SPREAD | Post-only (GTX) order canceled. Order matched with existing limit order. |
LIMIT_PRICE_OUT_OF_BOUNDS | Unable to place order because limit price exceeds limit order price limit. See Get Markets limitOrderExecutionPriceLimit . |
MAXIMUM_ORDERS_EXCEEDED | Order exceeds the 250 maximum number of open orders for a wallet. |
MAXIMUM_CANCELS_EXCEEDED | Batch cancel request exceeds batch size limit. |
MAXIMUM_POSITION_SIZE_EXCEEDED | Position after order exceeds maximum position size. |
WOULD_EXCEED_MAXIMUM_POSITION_SIZE | Order execution would exceed maximum position size. |
QUANTITY_TOO_LOW | Order quantity does not meet the maker or taker minimum. |
REDUCE_ONLY_NO_POSITION | No position is open to reduce. |
REDUCE_ONLY_SAME_SIDE | Reduce-only order does not reduce the open position. |
REDUCE_ONLY_NOT_FILLABLE | Reduce-only order cannot be completely filled. |
TRADING_RESTRICTED_FOR_LOCATION | Access to IDEX is prohibited from some regions. |
WALLET_EXITED | Wallet exited. |
TRADING_DISABLED | Order placement is disabled at the exchange or market scope. |
CANCELS_DISABLED | Order cancellation is disabled at the exchange or market scope. |
Order Placement Cancellations
New order placements may result in order cancellation for several reasons. New order cancellations return a successful Create Order response with the following errorCode
and errorMessage
fields.
errorCode | errorMessage |
---|---|
QUANTITY_TOO_LOW | Order quantity does not meet the maker minimum. |
REDUCE_ONLY_POSITION_CLOSED | Remainder of order canceled because the position is closed. |
SELF_TRADE | Order matched another order placed by the same wallet or API account. |
TIME_IN_FORCE | Part or all of order canceled due to timeInForce setting. |
Existing Order Cancellation WebSocket Errors
Open orders may be canceled by the system for several reasons. Open order cancellations generate WebSocket Orders subscription updates with the following errorCode
and errorMessage
fields.
errorCode (ec) | errorMessage (em) |
---|---|
INSUFFICIENT_COLLATERAL | Order held funds exceeds wallet free collateral. |
LIQUIDATION | Wallet liquidated. |
MARGIN_REQUIREMENT | Order execution exceeds wallet margin requirements. |
MARKET_DEACTIVATED | Market deactivated. |
MAXIMUM_POSITION_SIZE_EXCEEDED | Order execution exceeds the maximum position size. |
WOULD_EXCEED_MAXIMUM_POSITION_SIZE | Order execution would exceed maximum position size. |
QUANTITY_TOO_LOW | Remaining order quantity is too low. |
REDUCE_ONLY_NO_POSITION | No position is open to reduce. |
REDUCE_ONLY_SAME_SIDE | Order execution does not reduce the open position. |
REDUCE_ONLY_NOT_FILLABLE | Reduce-only order cannot be completely filled. |
SELF_TRADE | Order matched another order placed by the same wallet or API account. |
WALLET_EXITED | Wallet exited. |
Withdrawal Errors
Code | Description |
---|---|
INSUFFICIENT_FUNDS | Withdrawal quantity exceeds available collateral. |
QUANTITY_TOO_LOW | Withdrawal quantity does not meet the minimum. |
MAXIMUM_GAS_FEE_TOO_HIGH | maximumGasFee must be less than or equal to quantity. |
MAXIMUM_GAS_FEE_TOO_LOW | maximumGasFee must greater than or equal to the current gas fee. |
INVALID_BRIDGE_ADAPTER_ADDRESS | Invalid bridge adapter address. |
EXCESSIVE_SLIPPAGE | Bridged withdrawal quantity exceeds the destination chain slippage tolerance. |
WITHDRAWALS_DISABLED | Withdrawals are disabled. |
Enums & Values
Wallet Signature Hash Enums
Order Type Enum
Value | Name |
---|---|
0 | Market |
1 | Limit |
2 | Stop loss market |
3 | Stop loss limit |
4 | Take profit market |
5 | Take profit limit |
Order Side Enum
Value | Name |
---|---|
0 | Buy |
1 | Sell |
Order Trigger Type Enum
Value | Name |
---|---|
0 | None |
1 | Last price |
2 | Index price |
Order Time-In-Force Enum
Value | Name |
---|---|
0 | Good-til-canceled (gtc) |
1 | Good-til-crossing (gtx) |
2 | Immediate-or-cancel (ioc) |
3 | Fill-or-kill (fok) |
Order Self-Trade Prevention Enum
Value | Name |
---|---|
0 | Decrement and cancel (dc) |
1 | Cancel oldest (co) |
2 | Cancel newest (cn) |
3 | Cancel both (cb) |
API Request & Response Values
Market Trading Status Values
Value | Description |
inactive | No orders or cancels accepted |
cancelsOnly | Cancels accepted but not new orders |
limitMakerOnly | Cancels and limitMaker orders only |
active | Cancels and all order types accepted |
Candle Interval Values
Value | Description |
1m | 1 minute |
5m | 5 minutes |
15m | 15 minutes |
30m | 30 minutes |
1h | 1 hour |
4h | 4 hours |
1d | 1 day |
Order Type Values
Value | Description |
market | See order types |
limit | |
stopLossMarket | |
stopLossLimit | |
takeProfitMarket | |
takeProfitLimit |
Order Time In Force Values
Value | Description |
gtc | See time in force policies |
gtx | |
ioc | |
fok |
Order Self-Trade Prevention Values
Value | Description |
dc | See self-trade prevention policies |
co | |
cn | |
cb |
Order Status Values
Value | Description |
active | See order states and lifecycle |
open | |
partiallyFilled | |
filled | |
canceled | |
rejected | |
notFound |
Order Update Values
Value | Description |
new | An order without a stopPrice has been accepted by the matching engine. new is not sent as a WebSocket state change event if the order matches on initial processing. |
activated | An order with a stopPrice has accepted into the matching engine and once the stopPrice is triggered, will go through other normal events starting with new . |
fill | An order has generated a fill, which is sent as a WebSocket event for both maker and taker orders. fill is the first WebSocket state change event sent if an order matches on initial processing. fill is also sent as a WebSocket event when an order is decremented by self-trade prevention. |
canceled | An order has been canceled. canceled is also sent as a WebSocket event when an order is canceled by self-trade prevention. |
expired |
|
Fill Type Values
Value | Description |
market | Fill resulting from any type of market order |
limit | Fill resulting from any type of limit order |
liquidation | Position closure resulting from forced liquidation or ADL |
deleverage | Position closure as the counterparty to an ADL action |
closure | Position closure for positions below the market minimum |
Bridge Target Values
Value | Description |
xchain.xchain | XCHAIN local |
stargate.ethereum | Ethereum via Stargate |
stargate.polygon | Polygon PoS via Stargate |
stargate.arbitrum | Arbitrum via Stargate |
stargate.optimism | Optimism via Stargate |
Settlement Transaction State Values
Value | Description |
pending | Not yet sent to Polygon or not yet mined. |
mined | Succesfully mined. |
failed | Transaction reverted. |