Upcoming Changes
WebSocket Orders Channel: Push Behavior Adjustment
Last update: Jul 22, 2026
To help clients more clearly determine the final status of post-only new orders (including mmp_and_post_only) and upcoming rpi new orders β and to avoid scenarios where an order is still canceled after the client has already received a state: live event β OKX will adjust the state: live event behavior for post-only and rpi orders in the Order channel.
Impact details
- The
state: liveevent will be pushed only after the order has successfully entered the order book, instead of immediately upon order receipt (a delay of approximately 1 ms). - In failed order placement scenarios (price crosses the BBO and is canceled), the
state: liveupdate will be removed entirely β only astate: canceledupdate will be pushed.
| Scenario | Before | After |
|---|---|---|
post-only order placement failure(price crosses the BBO and is canceled) |
state: live β state: canceled |
Only state: canceled (no state: live) |
post-only order placed successfully |
state: live pushed immediately |
state: live (delayed ~1 ms) |
post-only order placed successfully,then filled by one taker order |
state: live β state: filled |
state: live (delayed ~1 ms) β state: filled |
post-only order placed successfully,then filled by multiple partial fills |
state: live β state: partially_filled β state: filled |
state: live (delayed ~1 ms) β state: partially_filled β state: filled |
post-only order with reduceOnly: true,size modified |
state: live β state: live (amendSource: 4, amendResult: 0) |
state: live (amendSource: 4, amendResult: 0) β state: live |
Upcoming rpi order, rpiPxRound: false,order placement failure (canceled due to not meeting the price spacing rule) |
N/A | Only state: canceled (no state: live) |
Upcoming rpi order, rpiPxRound: true,and price is modified |
N/A | state: live (amendSource: 6, amendResult: 0) β state: live |
Effective date
- For
rpiorders (includingelporders, which will be deprecated): demo trading β July 23, 2026; production β July 28, 2026. - For
post_onlyandmmp_and_post_onlyorders: both demo trading and production β mid-August, 2026.
Scope of impact
The order types affected are: post_only, mmp_and_post_only, and rpi (Retail Price Improvement).
Other order types β such as limit (regular limit orders), market (market orders), ioc, and fok β will have their push behavior remain unchanged.
OKX trading fee scheme update
Last updated: 2025/11/3
OKX will update the trading fee scheme for improved fee differentiation across tiers. Please refer to the announcement for more details.
Instruments endpoint/channel
- Add a new response parameter groupId to indicate which group a specific symbol belongs to.
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| groupId | String | Instrument trading fee group ID Spot: 1: Spot USDT2: Spot USDC & Crypto3: Spot TRY4: Spot EUR5: Spot BRL7: Spot AED8: Spot AUD9: Spot USD10: Spot SGD11: Spot zero12: Spot group one13: Spot group two14: Spot group threeExpiry futures: 1: Expiry futures crypto-margined2: Expiry futures USDT-margined3: Expiry futures USDC-margined4: Expiry futures premarket5: Expiry futures group one6: Expiry futures group twoPerpetual futures: 1: Perpetual futures crypto-margined2: Perpetual futures USDT-margined3: Perpetual futures USDC-margined4: Perpetual futures group one5: Perpetual futures group twoOptions: 1: Options crypto-margined2: Options USDC-marginedinstType and groupId should be used together to determine a trading fee group. Users should use this endpoint together with fee rates endpoint to get the trading fee of a specific symbol. Some enum values may not apply to you; the actual return values shall prevail. |
Response Example
{
"code":"0",
"msg":"",
"data":[
{
"alias": "",
"auctionEndTime": "",
"baseCcy": "BTC",
"category": "1",
"ctMult": "",
"ctType": "",
"ctVal": "",
"ctValCcy": "",
"contTdSwTime": "1704876947000",
"expTime": "",
"futureSettlement": false,
"groupId": "13"
"instFamily": "",
"instId": "BTC-USDT",
"instType": "SPOT",
"lever": "10",
"listTime": "1606468572000",
"lotSz": "0.00000001",
"maxIcebergSz": "9999999999.0000000000000000",
"maxLmtAmt": "1000000",
"maxLmtSz": "9999999999",
"maxMktAmt": "1000000",
"maxMktSz": "",
"maxStopSz": "",
"maxTriggerSz": "9999999999.0000000000000000",
"maxTwapSz": "9999999999.0000000000000000",
"minSz": "0.00001",
"optType": "",
"openType": "call_auction",
"preMktSwTime": "",
"quoteCcy": "USDT",
"tradeQuoteCcyList": [
"USDT"
],
"settleCcy": "",
"state": "live",
"ruleType": "normal",
"stk": "",
"tickSz": "0.1",
"uly": "",
"instIdCode": 1000000000
}
]
}
Get fee rates endpoint
- Add new response parameter feeGroup. Fields that will be deprecated: maker, makerU, makerUSDC, taker, takerU, takerUSDC.
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| feeGroup | Array of objects | Fee groups. Applicable to SPOT/MARGIN/SWAP/FUTURES/OPTION |
| > taker | String | Taker fee |
| > maker | String | Maker fee |
| > groupId | String | Instrument trading fee group ID instType and groupId should be used together to determine a trading fee group. Users should use this endpoint together with instruments endpoint to get the trading fee of a specific symbol. |
Response Example
{
"code": "0",
"msg": "",
"data": [{
"category": "1", //Deprecated
"delivery": "",
"exercise": "",
"feeGroup": [
{
"taker": "0.001",
"maker": "0.0001",
"groupId": "1"
},
{
"taker": "0.01",
"maker": "0.001",
"groupId": "2"
},
{
"taker": "0.1",
"maker": "0.01",
"groupId": "3"
},
......
],
"instType": "SPOT",
"level": "lv1",
"maker": "-0.0008", //Deprecated
"makerU": "", //Deprecated
"makerUSDC": "", //Deprecated
"taker": "-0.001", //Deprecated
"takerU": "", //Deprecated
"takerUSDC": "", //Deprecated
"ruleType": "normal",
"ts": "1608623351857",
"fiat": []
}
]
}
2026-07-28
Rebranding ELP to RPI (Retail Price Improvement) Program
OKX is rebranding Enhanced Liquidity Program (ELP) to Retail Price Improvement (RPI). This includes a new consolidated RPI order book (books-rpi) over WebSocket and REST, a renamed rpi maker order type (replacing elp), an expanded rpiTakerAccess order parameter (replacing isElpTakerAccess), a new rpiPxRound parameter for the RPI maker spacing rule, and renamed rpi/rpiMaker account fields.
ELP name deprecation deadline: October 31, 2026
OKX will run the ELP and RPI names in parallel until this date, in two distinct ways:
- Renamed fields β both accepted; the RPI-named field wins when a request or response carries both:
isElpTakerAccessβrpiTakerAccesselpβrpielpMakerβrpiMaker
- Renamed values β mutually exclusive; send or expect one or the other, not both:
ordType: elpβordType: rpibooks-elpβbooks-rpi
Existing integrations continue to operate without changes. The ELP names will be retired after the sunset date above β migrate every integration to the RPI names before then.
New consolidated order book: books-rpi (WS + REST)
- Added
books-rpi, consolidating organic and RPI liquidity into a single depth stream β available as a public WebSocket channel (/ws/v5/public, 400 depth levels, full snapshot + incremental updates every 100 ms) and a REST endpoint (GET /api/v5/market/books-rpi, refreshed every 200 ms server-side). Nochecksum; WS sequencing relies onseqId/prevSeqId. Supersedesbooks-elp(see migration note above).
Each asks/bids element is [price, totalQty, nonRpiQty, count] β totalQty is the total depth at that price level, nonRpiQty is the organic-only portion, count is the aggregated order count at that level.
REST request: instId (required), sz (depth per side, max 400, default 1).
Taker parameter: rpiTakerAccess (replaces isElpTakerAccess)
rpiTakerAccessrenames and expandsisElpTakerAccessto apply to all standard order types (limit,market,fok,ioc; previouslyioconly) and to be settable on amend.isElpTakerAccessremains accepted as an alias until the sunset date (see migration note above).- Error code
54045(previously returned when a non-iocorder attempted to take RPI liquidity) is retired β unreachable now thatrpiTakerAccessis valid on all order types.
Applies to place / amend, REST + WS: - POST / Place order - POST / Place multiple orders - POST / Amend order - POST / Amend multiple orders - WS / Place order - WS / Place multiple orders - WS / Amend order - WS / Amend multiple orders
| Parameter | Type | Required | Description |
|---|---|---|---|
| rpiTakerAccess | Boolean | No | Default false.When true, the order can access RPI liquidity, for all standard order types (previously ioc only).A speedbump mechanism applies to all ordType, including post_only, on both placement and amend when rpiTakerAccess is true.Not inherited on amend β must be re-specified on each amend request (omitted = false for that amend). |
Maker order type: rpi (replaces elp)
- To place an RPI maker order, set
ordTypetorpiinstead ofelp.elpremains accepted until the sunset date (see migration note above) βordTypetakes a single value, so send one or the other, not both.
Applies to place, REST + WS: - POST / Place order - POST / Place multiple orders - WS / Place order - WS / Place multiple orders
Maker parameter: rpiPxRound
rpiPxRoundis a new parameter for the RPI maker spacing rule (see below). Effective only on RPI maker orders (ordType: rpi); silently ignored on non-RPI orders and onOPTION/EVENTS.
Applies to place / amend, REST + WS (same interfaces as rpiTakerAccess above).
| Parameter | Type | Required | Description |
|---|---|---|---|
| rpiPxRound | Boolean | No | Default false. When true, a price that violates the spacing rule is auto-rounded outward to the nearest placeable, non-crossing level instead of being rejected. |
- Added a new
amendSourcevalue6on theordersWS private channel: order price adjusted (rounded) by the system to satisfy the RPI maker spacing rule, triggered byrpiPxRound.
RPI maker spacing rule
RPI maker orders are subject to a spacing rule (rpiMinLevel / rpiMinPxBand below). An order that violates it is rejected unless rpiPxRound is true, in which case the price is auto-rounded to the nearest compliant level instead (see rpiPxRound above).
- Added new response parameters
rpiMinLevelandrpiMinPxBandto expose the per-instrument spacing thresholds.
| Parameter | Type | Description |
|---|---|---|
| rpiMinLevel | String | Minimum spacing between the RPI bid and RPI ask, in organic price levels. Default 4; 0 for Event Contracts. |
| rpiMinPxBand | String | Minimum distance from the opposite-side organic best price required to satisfy the spacing rule, in basis points (bps), e.g. 20. |
RPI maker permission field: rpi (replaces elp)
- Added new response parameter
rpito indicate RPI maker permission.elpremains accepted as an alias until the sunset date (see migration note above).
| Parameter | Type | Description |
|---|---|---|
| rpi | String | RPI maker permission.0: not enabled for this instrument1: enabled, but the current user has no permission to place RPI orders2: enabled and permittedA 1/2 value does not imply RPI liquidity is present. |
RPI maker fee rate field: rpiMaker (replaces elpMaker)
- Added new response parameter
rpiMakerto indicate the RPI maker effective fee rate.elpMakerremains accepted as an alias until the sunset date (see migration note above).
| Parameter | Type | Description |
|---|---|---|
| rpiMaker | String | RPI maker effective fee rate. Returns "" if RPI is not applicable to the instrument. |
Trade source field: source
- Response field
sourcevalue1onGET /api/v5/market/tradesis now described as RPI order (previously ELP order). The returned value1itself is unchanged β only the description text is updated.
Error code changes
Error messages updated from ELP to RPI:
| Error Code | Previous Message | Updated Message |
|---|---|---|
| 54039 | ELP orders can't be reduce-only orders. | RPI orders can't be reduce-only orders. |
| 54040 | ELP orders can't be used with TP/SL settings. | RPI orders can't be used with TP/SL settings. |
| 54041 | ELP orders aren't supported for {param0}. | RPI orders aren't supported for {param0}. |
| 54042 | You don't have permission to place ELP orders for {param0}. | You don't have permission to place RPI orders for {param0}. |
| 54043 | You can only place up to {param1} ELP orders for {param0}. | You can only place up to {param1} RPI orders for {param0}. |
| 54044 | ELP is not enabled for {param0}. You can't place orders that take ELP liquidity of it. | RPI is not enabled for {param0}. You can't place orders that take RPI liquidity of it. |
| 54046 | You can't place orders to take ELP liquidity. | You can't place orders to take RPI liquidity. |
| 54049 | API users can't place orders that take ELP liquidity now because system is busy. To proceed, set isElpTakerAccess:false. | API users can't place orders that take RPI liquidity now because system is busy. To proceed, set rpiTakerAccess:false. |
Deprecated error code:
| Error Code | Message | Reason |
|---|---|---|
| 54045 | OpenAPI users can only place IOC orders that take ELP liquidity. | Retired β rpiTakerAccess now applies to all order types, not IOC-only. |
2026-07-23
GLP Performance API for market makers
Two new read-only endpoints for Global Liquidity Program (GLP) market makers to query their assessment performance metrics. Only enrolled GLP accounts can access these endpoints; sub-accounts resolve to their master account.
- The following new endpoints have been added:
GET / Get GLP today performance
Retrieve the current day and month-to-date (MTD) GLP performance snapshot for the authenticated account, covering all enrolled programs (Spot / Perp / Expiry & Nitro). No request parameters; the account is resolved from the API key.
Rate Limit: 5 requests per 2 seconds
Rate limit rule: User ID
Permission: Read
HTTP Request
GET /api/v5/users/glp/today-performance
Request Example
GET /api/v5/users/glp/today-performance
Request Parameters
None. The account is resolved from the authenticated session.
Response Example
{
"code": "0",
"msg": "",
"data": [
{
"dataReady": true,
"dataDate": "2026-07-13",
"account": {
"masterAccountId": "832545488879789797",
"combinedAccountIds": ["832545488879789798"]
},
"programs": [
{
"program": "SPOT",
"marketMakerBusinessId": "1",
"enrollmentStatus": "ENROLLED",
"marketMakerLevelId": "42",
"enrolledTierDisplay": "Tier 1 Class A",
"qualifyingPool": "TYPE_A",
"qualifyingRows": ["TOTAL"],
"daily": {
"volume": {
"typeA": {"maker": "1000000.00", "taker": "1000000.00"},
"typeBTotal": {"maker": "1000000.00", "taker": "1000000.00"},
"tradfiX2": {"maker": "1000000.00", "taker": "1000000.00"},
"total": {"maker": "2000000.00", "taker": "2000000.00"}
},
"share": {
"typeA": {"maker": "0.0000", "taker": "0.0000"},
"typeBAdj": {"maker": "0.0000", "taker": "0.0000"},
"total": {"maker": "0.0000", "taker": "0.0000"}
}
},
"mtd": {
"volume": {
"typeA": {"maker": "30000000.00", "taker": "30000000.00"},
"typeBTotal": {"maker": "30000000.00", "taker": "30000000.00"},
"tradfiX2": {"maker": "30000000.00", "taker": "30000000.00"},
"total": {"maker": "60000000.00", "taker": "60000000.00"}
},
"share": {
"typeA": {"maker": "0.0000", "taker": "0.0000"},
"typeBAdj": {"maker": "0.0000", "taker": "0.0000"},
"total": {"maker": "0.0000", "taker": "0.0000"}
},
"mtdStatus": "QUALIFIED",
"qualifyingShare": {"maker": "0.0000", "taker": "0.0000"}
}
}
]
}
]
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| dataReady | Boolean | Whether data is available for the dataDate. When false, programs is an empty array |
| dataDate | String | Data snapshot date in yyyy-MM-dd format (UTC+8). Typically T-1; falls back to T-2 when T-1 computation is incomplete |
| account | Object | Account identity block |
| > masterAccountId | String | Master account ID |
| > combinedAccountIds | Array of strings | Sibling account IDs in the same institutional group (excludes self). Empty array if no group |
| programs | Array of objects | Performance data for each enrolled GLP program. Empty when dataReady is false |
| > program | String | GLP business line identifier.SPOTPERPFUT_NTO: Expiry & Nitro |
| > marketMakerBusinessId | String | Market maker business ID for this program |
| > enrollmentStatus | String | Enrollment status. Currently always ENROLLED |
| > marketMakerLevelId | String | Current tier level ID |
| > enrolledTierDisplay | String | Current tier display name, e.g. Tier 1 Class A |
| > qualifyingPool | String | Pool that determines current tier.TYPE_ATYPE_B_ADJTYPE_A_AND_B |
| > qualifyingRows | Array of strings | Keys of qualifying rows for UI highlighting, e.g. ["TOTAL"] |
| > daily | Object | Today's performance metrics. Contains volume and share (see structure below) |
| > mtd | Object | Month-to-date performance metrics. Contains volume, share (same structure as daily), plus the additional fields below |
| >> mtdStatus | String | MTD qualification status.QUALIFIEDUPGRADEDOWNGRADE |
| >> qualifyingShare | Object | Share in the qualifying pool. Contains maker (String) and taker (String) |
Volume and share structure
Both daily and mtd contain a volume Object and a share Object. Each Object holds category keys, and each category is itself an Object with maker (String) and taker (String) fields.
| Category | In volume |
In share |
Description |
|---|---|---|---|
| typeA | Yes | Yes | Type A. null for FUT_NTO |
| typeBTotal | Yes | No | Type B total. null for FUT_NTO |
| typeBAdj | No | Yes | Type B adjusted. null for FUT_NTO |
| tradfiX2 | Yes | No | TradFi volume doubled. null for FUT_NTO |
| total | Yes | Yes | Total across all types. Always present |
volumevalues: USD notional as String with 2 decimal places (e.g."1000000.00")sharevalues: decimal string with 4 decimal places, no%suffix (e.g."0.0000")
GET / Get GLP historical performance
Retrieve daily GLP performance history for a single program. Results are sorted newest-first (descending by date).
Rate Limit: 5 requests per 2 seconds
Rate limit rule: User ID
Permission: Read
HTTP Request
GET /api/v5/users/glp/historical-performance
Request Example
GET /api/v5/users/glp/historical-performance?program=SPOT
GET /api/v5/users/glp/historical-performance?program=SPOT&begin=1751299200000&end=1753804800000&limit=31
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| program | String | Yes | GLP business line identifier.SPOTPERPFUT_NTO |
| begin | String | No | Begin date filter (inclusive). Unix ms String, e.g. "1751299200000". Default: first day of current month (UTC+8) |
| end | String | No | End date filter (inclusive). Unix ms String. Default: today (UTC+8) |
| limit | String | No | Max records per page. Default "31", max "100" |
Response Example
{
"code": "0",
"msg": "",
"data": [
{
"date": "2026-07-13",
"volume": {
"typeA": {"maker": "1000000.00", "taker": "1000000.00"},
"typeBTotal": {"maker": "1000000.00", "taker": "1000000.00"},
"tradfiX2": {"maker": "1000000.00", "taker": "1000000.00"},
"total": {"maker": "2000000.00", "taker": "2000000.00"}
},
"share": {
"typeA": {"maker": "0.0012", "taker": "0.0010"},
"typeBAdj": {"maker": "0.0008", "taker": "0.0007"},
"total": {"maker": "0.0010", "taker": "0.0009"}
}
},
{
"date": "2026-07-12",
"volume": {
"typeA": {"maker": "950000.00", "taker": "980000.00"},
"typeBTotal": {"maker": "850000.00", "taker": "900000.00"},
"tradfiX2": {"maker": "800000.00", "taker": "820000.00"},
"total": {"maker": "1800000.00", "taker": "1880000.00"}
},
"share": {
"typeA": {"maker": "0.0011", "taker": "0.0009"},
"typeBAdj": {"maker": "0.0007", "taker": "0.0006"},
"total": {"maker": "0.0009", "taker": "0.0008"}
}
}
]
}
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| date | String | Date in yyyy-MM-dd format (UTC+8) |
| volume | Object | Trading volume by pool type (USD notional, 2 decimal places). Same structure as the today performance endpoint's daily.volume |
| share | Object | Market share by pool type (decimal string, 4 decimal places, no % suffix). Same structure as the today performance endpoint's daily.share |
Error Codes
| Error Code | HTTP Status Code | Error Message |
|---|---|---|
| 50030 | 200 | You don't have permission to use this API endpoint |
| 50014 | 200 | Parameter {param0} can not be empty |
| 51000 | 200 | Parameter error |
| 50016 | 200 | Parameter {param0} does not match parameter {param1} |
Chase limit order for FUTURES/SWAP trigger orders
FUTURES and SWAP trigger orders now support a chase limit order as the post-trigger execution type. When advanceOrdType is set to chase, the trigger order places a chase order instead of a regular limit or market order once the trigger fires. The chase parameters are carried in a new advChaseParams array, and the read endpoints return the spawned chase order's algoId in a new subAlgoIdList field. Chase values can be amended while the trigger order is still pending (pre-trigger). Attached TP/SL (attachAlgoOrds) is not supported with chase in this iteration.
Place algo order
- Added a new
advanceOrdTypevaluechaseand a newadvChaseParamsrequest parameter array;orderPxis now conditional (not applicable to a chase).
| Parameter | Type | Required | Description |
|---|---|---|---|
| advanceOrdType | String | No | Sub-order type for trigger orders.fok, ioc, or chase.chase is only applicable to FUTURES and SWAP.Default empty (a limit or market order per orderPx). |
| orderPx | String | Conditional | Price of the order placed when the trigger fires. -1 for market. Not applicable when advanceOrdType is chase (a chase has no fixed price). |
| advChaseParams | Array of objects | Conditional | Chase parameters. Required when advanceOrdType is chase. |
| > chaseType | String | Conditional | Chase distance unit.distance (default): absolute price distance from the best bid/ask, in settlement currency.ratio: percentage. |
| > chaseVal | String | Conditional | Chase value. When chaseType is distance, the distance from the best bid/ask in settlement currency; when ratio, 0.1 = 10%.Default 0 tracks the best bid/ask directly; a value >0 sets a distance. |
| > maxChaseType | String | Conditional | Maximum chase distance unit. distance or ratio. Must pair with maxChaseVal. |
| > maxChaseVal | String | Conditional | Maximum chase distance value. Positive. Must pair with maxChaseType. The chase auto-cancels when its deviation reaches this value. |
Amend algo order
- Added
advChaseParamsamend fields to adjust the chase values while the trigger order is pending (pre-trigger).chaseType,maxChaseType, and the chase-price mode are fixed at placement and cannot be amended.
| Parameter | Type | Required | Description |
|---|---|---|---|
| advChaseParams | Array of objects | Conditional | Chase parameters to amend. Only for a pending trigger order with advanceOrdType chase. |
| > newChaseVal | String | Conditional | New chase value. Non-negative, interpreted per the order's existing chaseType. It cannot cross the 0 β non-0 boundary of the original chaseVal β tracking the best bid/ask directly (0) and a distance offset (>0) are not interchangeable. |
| > newMaxChaseVal | String | Conditional | New maximum chase distance value. Positive, interpreted per the existing maxChaseType. Only applicable when maximum chase is enabled. |
Read endpoints (order details, order lists, WS channel)
- Added
advanceOrdType(with the newchasevalue),advChaseParams, and a newsubAlgoIdListresponse parameter.
| Parameter | Type | Description |
|---|---|---|
| advanceOrdType | String | Sub-order type for trigger orders. fok, ioc, chase, or empty. |
| advChaseParams | Array of objects | Chase parameters. Present when advanceOrdType is chase. |
| > chaseType | String | Chase distance unit. distance or ratio. |
| > chaseVal | String | Chase value. 0 tracks the best bid/ask directly; >0 is a distance. |
| > maxChaseType | String | Maximum chase distance unit. distance or ratio. |
| > maxChaseVal | String | Maximum chase distance value. |
| subAlgoIdList | Array of strings | algoId(s) of the algo order(s) spawned when the trigger fires. For advanceOrdType chase, holds the spawned chase order's algoId after the trigger fires; empty before then. Mirrors ordIdList, which records spawned regular orders and stays empty for a chase. |
2026-06-23
Deprecation of checksum field in order book channels
To improve the efficiency and stability of the market data feed, the following order book channels have deprecated the checksum field in both snapshot and incremental updates. The checksum field is still present in snapshot and incremental updates, but its value is fixed to 0 and must no longer be used for integrity verification. Please use seqId/prevSeqId to verify the data continuity and accuracy.
- Deprecated the
checksumfield in both snapshot and incremental updates (the field remains in the push but its value is fixed to0).- WS / Order book channel
booksbooks-l2-tbtbooks50-l2-tbt
- WS / Order book channel
Note:
1. books5 and bbo-tbt channels do not carry a checksum field and are not affected by this change.
2. The WebSocket connection now fully enforces TLS (wss://), providing protection against eavesdropping and tampering, and ensuring data integrity. Together with rigorous validation of seqId and prevSeqId, it effectively prevents out-of-order messages, partial data loss, or malicious injection, providing integrity protection equivalent to or stronger than the original checksum mechanism.
2026-05-07
New Endpoints
- The following new endpoint is added. Only applicable to the demo trading environment:
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | String | Yes | Direction of adjustment.increase: add to balancereduce: deduct from balanceOne direction per request; increase and reduce cannot be mixed. |
| adjustments | Array | Yes | List of currency adjustments. At least one item required. Duplicate currencies are not allowed. |
| > ccy | String | Yes | Currency. Supported values: BTC ETH USDT OKB |
| > amt | String | Yes | Adjustment amount. Must be non-negative. Decimal places must not exceed the precision defined for the currency. Increase limits per request: BTC: 1, ETH: 1, USDT: 5000, OKB: 100. Reduce has no per-request amount limit β only constrained by available balance β₯ 0. |
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| remainCnt | String | Remaining daily increase quota. Also returned for reduce requests, but reduce does not consume quota. |
| totalCnt | String | Total daily increase quota (default: 3). |
| details | Array | Per-currency operation details. |
| > ccy | String | Currency. |
| > amt | String | Adjustment amount applied. |
| > bal | String | Post-operation balance for this currency. |
Error Codes
| Error code | HTTP status code | Error message |
|---|---|---|
| 59691 | 200 | Daily increase limit reached {param0}. Please retry after UTC 0:00 or reset your demo account. |
| 59692 | 200 | Insufficient {param0} balance. Balance cannot go below zero after operation. |
| 59693 | 200 | {param0} transferable balance insufficient. Some funds are occupied by open orders or positions. Please cancel orders or close positions and try again. |
2026-05-06
- OKX is introducing customisable slippage tolerance for spot and spot margin market-side orders via OpenAPI and WebSocket.
- A new
post_onlyinstrument state is added forSWAPcontracts, restricting accepted order types to post-only limit orders.
Changes to Existing Endpoints
- New optional request parameter
slippagePctfor spot and spot margin market-side orders (wheretgtCcyis the received currency:base_ccyfor buy,quote_ccyfor sell):
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| slippagePct | String | No | Maximum acceptable slippage for spot and spot margin market-side orders, where tgtCcy is the received currency (base_ccy for buy, quote_ccy for sell).Range: 0 to 0.05 (0% to 5%, inclusive). Up to 2 decimal places of the percentage, e.g., 0.01 (1%) and 0.0123 (1.23%) are accepted; 0.01234 (1.234%) is rejected.If not specified or empty, defaults to 0.00%.Slippage cannot be modified on an existing order. Cancel and resubmit to change the slippage setting. Only applicable to SPOT and SPOT margin market orders. |
Error Codes
| Error code | HTTP status code | Error message |
|---|---|---|
| 54084 | 200 | Your slippage setting must be between 0% and 5% (inclusive). |
| 54085 | 200 | Your slippage percentage can't exceed 2 decimal places. |
- Response parameter
stateadds new enum valuepost_only. When a contract is inpost_only, only post-only limit orders are accepted (along with amend and cancel of existing post-only orders); market, IOC, FOK and normal limit orders are rejected. Only applicable toSWAP:
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| state | String | Instrument statuspost_only: only post-only orders are accepted; existing post-only orders can be amended and cancelled. Other order types (market, IOC, FOK, normal limit) are rejected. Only applicable to SWAP |
2026-04-07
Trading Fee Tier Requirement Changes
- Channels that previously required VIP6/VIP5 or above are now accessible from VIP4 and above
- Error codes 60029 and 60030 have been deprecated and unified to error code 64003
- The following table shows the changes in VIP tier requirements for accessing various Open API features:
| Endpoint or Channel | Before | After (Current) | Error Code Change |
|---|---|---|---|
| SBE trades channel and books-l2-tbt channel | >= VIP6 | >= VIP4 | 64003 unchanged |
| JSON books-l2-tbt channel | >= VIP6 | >= VIP4 | 60029 β 64003 |
| JSON books50-l2-tbt channel | >= VIP5 | >= VIP4 | 60030 β 64003 |
| JSON fills channel | >= VIP6 | >= VIP4 | 60029 β 64003 |
Deprecate instId Request Parameter in WS Order Operation Channels
To reduce latency in WS order operations, the instId request parameter from the following order operation channels has been deprecated.
- Deprecate
instIdrequest parameter in the following channels:
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| instId | String | - | Instrument ID Deprecated, will be ignored |
Note: You can use the Get instruments endpoint to map instIdCode to instId.
KYC Level 2 Required for Placing Orders
OKX will require users to complete KYC Level 2 or above in order to place orders via WebSocket and REST API endpoints. Users who have not completed KYC Level 2 will receive error code 59113 when attempting to place orders. This requirement applies to live trading only β demo trading is not affected.
Affected Endpoints
| Endpoint or Channel | Description |
|---|---|
| WS / Place order | Place a single order |
| WS / Place multiple orders | Place orders in batch |
| POST / Place order | Place a single order |
| POST / Place multiple orders | Place orders in batch |
Error Code
| Error Code | Description |
|---|---|
| 59113 | KYC level 2 or above is required for placing orders |
Notes:
- Users must complete KYC Level 2 verification before placing orders via WebSocket / REST API endpoints
- This requirement applies to live trading only β demo trading is not affected
2026-03-26
- Delisted
instIdrequest parameter from the following channels.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| instId | String | - | Instrument ID Delisted. Any value provided will be ignored. |
Note: Users can use the Get instruments interface to map instIdCode to instId.
2026-02-12
- Added new parameters
| Parameter | Type | Description |
|---|---|---|
| instCategory | String | The category of the instrumentβs base currency (the first part of the instrument ID). For example, for BTC-USDT-SWAP, the instCategory refers to the category of BTC. 1: Crypto |
2025-11-20
- Added new request parameter
instIdCode
| Request Parameter Name | Type | Required | Description |
|---|---|---|---|
| > instIdCode | Integer | Conditional | Instrument ID code. If both instId and instIdCode are provided, instIdCode takes precedence. |
| > instId | String | Conditional | Instrument ID Will be deprecated on March 2026. |
Note: You can use the Get instruments interface to map instIdCode to instId.
2025-08-20
Unified USD orderbook revamp
To revamp unified USD orderbook, more details for the first type users, more details for the second type users.
OKX delisted the Crypto-USDC trading pairs and upgrade the Crypto-USD trading pairs for accessibility to all users.
Users are categorized into two types based on their country or region, with varying solutions for each. If you get valid data from GET /api/v5/account/instruments?instType=SPOT&instId=BTC-USD, you belong to the first type users, if you get an empty array [] data from that URL, you belong to the second type.
- If you are going to trade
Crypto-USDCpairs after the revamp:- The
instIdshould be set toCrypto-USD, such asBTC-USD. - The
tradeQuoteCcyis used to determine the settlement quote currency and must be set asUSDC. - The value for
tradeQuoteCcyshould be one of the enumerated values fromtradeQuoteCcyList, which can be obtained from the endpoint Get instruments (private).
- The
- What you need to do:
- For the first type users:
- Regarding Trade, Algo Trading and and in Block Trading, you currently have two options to trade
Crypto-USDC. The first option is to trade directly with"instId": "Crypto-USDC"without specifyingtradeQuoteCcy. The second option is to trade using"instId": "BTC-USD"with"tradeQuoteCcy": "USDC". The first option will not be available after the revamp. For more details, please refer to the Example 1 below.
- Regarding Trade, Algo Trading and and in Block Trading, you currently have two options to trade
- For the second type of users, you are allowed to trade only with
"instId": "Crypto-USDC"before the revamp. Afterward, you must use"instId": "Crypto-USD"with"tradeQuoteCcy": "USDC". - When trading
Crypto-USDCafter the revamp, Get maximum available balance/equity and Get maximum order quantity will also need to use"instId": "BTC-USD"with"tradeQuoteCcy": "USDC". - For market data related
Crypto-USDCandCrypto-USDtrading, after the revamp, they will share the same order book, both using"instId": "Crypto-USD", such asBTC-USD. ThetradeQuoteCcyis not supported.
- For the first type users:
Example 1: Placing an order with BTC-USDC:
| Type | Before upgrading | After upgrading |
|---|---|---|
| Operation | Trading BTC-USDC |
Trading BTC-USDC |
Request fields for "op": "order" |
First option: { "instId": "BTC-USDC", "tradeQuoteCcy": "" } Second option: { "instId": "BTC-USD", "tradeQuoteCcy": "USDC" } |
Only option: { "instId": "BTC-USD", "tradeQuoteCcy": "USDC" } |
| Response body from Get instruments (private) |
[ { "instId": "BTC-USDC", "tradeQuoteCcyList": ["USDC"], ...... }, { "instId": "BTC-USD", "tradeQuoteCcyList": ["USD", "USDC"], ...... } ] |
[ { "instId": "BTC-USD", "tradeQuoteCcyList": ["USD", "USDC"], ...... } ] |
2025-07-02
Added new endpoint
Added new response parameter
| Parameter | Type | Description |
|---|---|---|
| notes | String | Notes |
2025-04-17
Added endpoints
Added new error codes
| Error code | Error Message |
|---|---|
| 59515 | You are currently not on the custody whitelist. Please contact customer service for assistance. |
| 59516 | Please create the Copper custody funding account first. |
| 59517 | Please create the Komainu custody funding account first. |
| 59518 | You canβt create a sub-account using the API; please use the app or web. |
| 59519 | You canβt use this function/feature while it's frozen, due to: {freezereason} |
2025-03-03
Withdrawal API adjustment for Turkey entity users
Due to compliance requirements, Bahamas entity users need to pass in the field rcvrInfo when making withdrawal.
Withdraw assets to the exchange wallet
If users withdraw assets to the exchange wallet, they need to provide exchange info & recipient information.
- Users can query supported exchanges through the endpoint of Get exchange list (public)
- Users need to pass in the following field information of the recipient (rcvrFirstName, rcvrLastName, rcvrCountry, rcvrCountrySubDivision, rcvrTownName, rcvrStreetName). For the exchange wallet belongs to business recipient,
rcvrFirstNamemay input the company name,rcvrLastNamemay input "N/A", location info may input the registered address of the company. The examples are as follows:
Withdraw assets to the private wallet
If users withdraw assets to the private wallet, they need to provide recipient information.
- Users need to pass in the following field information of the recipient (rcvrFirstName, rcvrLastName, rcvrCountry, rcvrCountrySubDivision, rcvrTownName, rcvrStreetName). For the exchange wallet belongs to business recipient,
rcvrFirstNamemay input the company name,rcvrLastNamemay input "N/A", location info may input the registered address of the company. The examples are as follows:
2025-02-12
- Added new parameters
| Parameter | Type | Description |
|---|---|---|
| notionalUsdForBorrow | String | Notional value for Borrow in USDApplicable to Spot mode/Multi-currency margin/Portfolio margin |
| notionalUsdForSwap | String | Notional value of positions for Perpetual Futures in USDApplicable to Multi-currency margin/Portfolio margin |
| notionalUsdForFutures | String | Notional value of positions for Expiry Futures in USDApplicable to Multi-currency margin/Portfolio margin |
| notionalUsdForOption | String | Notional value of positions for Option in USDApplicable to Spot mode/Multi-currency margin/Portfolio margin |
2024-11-14
- Adjusted response parameters
Before
| Parameter | Type | Description |
|---|---|---|
| minFee | String | The minimum withdrawal fee for normal address Apply to on-chain withdrawal |
| maxFee | String | The maximum withdrawal fee for normal address Apply to on-chain withdrawal |
| minFeeForCtAddr | String | The minimum withdrawal fee for contract address Apply to on-chain withdrawal |
| maxFeeForCtAddr | String | The maximum withdrawal fee for contract address Apply to on-chain withdrawal |
After
| Parameter | Type | Description |
|---|---|---|
| fee | String | The fixed withdrawal fee Apply to on-chain withdrawal |
| minFee | String | Apply to on-chain withdrawal(Deprecated) |
| maxFee | String | Apply to on-chain withdrawal(Deprecated) |
| minFeeForCtAddr | String | Apply to on-chain withdrawal(Deprecated) |
| maxFeeForCtAddr | String | Apply to on-chain withdrawal(Deprecated) |
- Added new endpoint
2024-10-10
- Added new response parameters
| Parameter | Type | Description |
|---|---|---|
| burningFeeRate | String | Burning fee rate, e.g "0.05" represents "5%". Some currencies may charge combustion fees. The burning fee is deducted based on the withdrawal quantity (excluding gas fee) multiplied by the burning fee rate. Apply to on-chain withdrawal |
- Added new response parameters
| Parameter | Type | Description |
|---|---|---|
| burningFeeRate | String | Burning fee rate, e.g "0.05" represents "5%". Some currencies may charge combustion fees. The burning fee is deducted based on the withdrawal quantity (excluding gas fee) multiplied by the burning fee rate. |
| feeCcy | String | Fixed withdrawal fee unit |
Nitro spread supports market orders, the request and response parameter ordType adds the enumeration value
market.Nitro spread adds a new order cancellation scenario, the cancelSource response parameter adds the enumeration value
15: Order canceled: The order price is beyond the limit.
2024-10-04
- Added call auction details WebSocket channel
2024-10-01
- Added public feature for endpoint:
2024-09-19
- Added new response parameters
| Parameter | Type | Description |
|---|---|---|
| enableSpotBorrow | Boolean | Whether borrow is allowed or not in Spot modetrue: Enabledfalse: Disabled |
| spotBorrowAutoRepay | Boolean | Whether auto-repay is allowed or not in Spot modetrue: Enabledfalse: Disabled |
- Added new response parameters
| Parameter | Type | Description |
|---|---|---|
| ccy | String | Currency |
- Added new response parameters
| Parameter | Type | Description |
|---|---|---|
| isTradeBorrowMode | String | Whether borrowing currency automatically true false Only applicable to trigger order, trailing order and twap order |
2024-09-18
- Added new endpoints: