Upgrade to Unified Trading Account
Upgrade to Unified Trading Account
This guide walks you through upgrading your integration from the Classic account API (v2) to the Unified Trading Account API (v3).
Why Upgrade to the Unified Trading Account?â
The Unified Trading Account (UTA) offers the following advantages over the Classic account:
- Higher capital efficiency: Trade spot and derivatives from a single account, using multiple crypto assets as shared margin. You no longer need to transfer funds between separate spot, margin, and futures accounts, and profits/losses across products can offset each other.
- Lower order latency: UTA's unified account and matching architecture reduces the processing overhead of cross-account and cross-product operations, resulting in faster order placement and execution than the Classic account.
- Faster access to new features: New products and capabilities are prioritized for release on UTA, so upgrading gets you earlier access to the latest features.
How to Upgrade to the Unified Trading Accountâ
There are two ways to upgrade to UTA:
- Via the web: see this upgrade guide for step-by-step instructions.
- Via the API: call the Upgrade Account endpoint.The API supports the master account initiating the upgrade itself, as well as upgrading sub-accounts.
Authentication and Signatureâ
The signature mechanism is identical between v2 and v3.
Every REST request still needs these headers:
ACCESS-KEYACCESS-SIGN(HMAC-SHA256, base64-encoded)ACCESS-TIMESTAMPACCESS-PASSPHRASEContent-Type: application/json
Your existing v2 API Key automatically gains UTA access â there's no need to create a new key.
Interface and Parameter Mappingâ
Place / Cancel / Modify Orderâ
| Action | v2 (Classic) | v3 (UTA) |
|---|---|---|
| Place order | POST /api/v2/mix/order/place-order (futures)POST /api/v2/spot/trade/place-order (spot) | POST /api/v3/trade/place-order (all products) |
| Cancel order | POST /api/v2/mix/order/cancel-orderPOST /api/v2/spot/trade/cancel-order | POST /api/v3/trade/cancel-order |
| Modify order | POST /api/v2/mix/order/modify-orderPOST /api/v2/spot/trade/cancel-replace-orderNo WebSocket support | POST /api/v3/trade/modify-orderWebSocket modify supported, with new autoCancel parameter |
Key parameter changes:
| v2 Parameter | v3 Parameter | Note |
|---|---|---|
productType (e.g. usdt-futures) | category (e.g. USDT-FUTURES) | Same concept, renamed and uppercased in v3 |
marginCoin | (removed) | Not required â UTA determines margin coin automatically from account mode |
marginMode | (removed from order request) | Cross/isolated is set at the account/position level, not per order |
| â | posSide | New required field in v3 for specifying long/short in hedge mode |
| N/A (single order type per endpoint) | category covers SPOT, MARGIN, USDT-FUTURES, USDC-FUTURES, COIN-FUTURES in one endpoint | v3 unifies all product types under one place-order endpoint |
Query Orders / Fillsâ
| Action | v2 (Classic) | v3 (UTA) |
|---|---|---|
| Unfilled orders | GET /api/v2/spot/trade/unfilled-ordersGET /api/v2/mix/order/orders-pending | GET /api/v3/trade/unfilled-orders |
| Historical orders | GET /api/v2/spot/trade/history-ordersGET /api/v2/mix/order/orders-history | GET /api/v3/trade/history-orders |
| Fill details | GET /api/v2/spot/trade/fillsGET /api/v2/mix/order/fills | GET /api/v3/trade/fills |
Pagination parameter change:
| v2 Parameter | v3 Parameter | Note |
|---|---|---|
idLessThan | cursor | Same purpose (fetch older data), different parameter name |
Account Assetsâ
| Action | v2 (Classic) | v3 (UTA) |
|---|---|---|
| Get account info | GET /api/v2/spot/account/info | GET /api/v3/account/settings |
| Get balance | GET /api/v2/spot/account/assets (spot)GET /api/v2/mix/account/accounts (futures) | GET /api/v3/account/assets (single endpoint for all products) |
| Get funding account | N/A (separate funding account concept) | GET /api/v3/account/funding-assets |
| Set leverage | POST /api/v2/mix/account/set-leverage | POST /api/v3/account/set-leverage |
| Set position mode | POST /api/v2/mix/account/set-position-mode | POST /api/v3/account/set-hold-mode |
Market Dataâ
| Action | v2 (Classic) | v3 (UTA) |
|---|---|---|
| Get product configuration | GET /api/v2/spot/public/symbols (spot)GET /api/v2/mix/market/contracts (futures) | GET /api/v3/public/instruments (all products) |
| Get ticker | GET /api/v2/spot/market/tickers (spot)GET /api/v2/mix/market/ticker (futures) | GET /api/v3/market/tickers (all products) |
| Get order book (depth) | GET /api/v2/spot/market/orderbook (spot)GET /api/v2/mix/market/merge-depth (futures) | GET /api/v3/market/orderbook (all products) |
| Get candlestick data | GET /api/v2/spot/market/candles (spot)GET /api/v2/mix/market/candles (futures) | GET /api/v3/market/candles (all products) |
| Get recent trades | GET /api/v2/spot/market/fills (spot)GET /api/v2/mix/market/fills (futures) | GET /api/v3/market/fills (all products) |
WebSocket Public Channelsâ
| Channel | v2 (Classic) Subscription | v3 (UTA) Subscription |
|---|---|---|
| Ticker | {"instType": "SPOT", "channel": "ticker", "instId": "BTCUSDT"} | {"instType": "spot", "topic": "ticker", "symbol": "BTCUSDT"} |
| Trades | {"instType": "SPOT", "channel": "trade", "instId": "BTCUSDT"} | {"instType": "spot", "topic": "publicTrade", "symbol": "BTCUSDT"} |
| Candlesticks | {"instType": "SPOT", "channel": "candle1m", "instId": "BTCUSDT"} | {"instType": "spot", "topic": "kline", "symbol": "BTCUSDT", "interval": "1m"} |
| Order book | {"instType": "SPOT", "channel": "books5", "instId": "BTCUSDT"} | {"instType": "spot", "topic": "books5", "symbol": "BTCUSDT"} |
| Liquidation | Not available in Classic | {"instType": "usdt-futures", "topic": "liquidation"} |
- v2 encodes the candle interval into the channel name (e.g.
candle1m,candle5m). v3 keepstopic: "kline"fixed and passes the interval as a separateintervalfield. - v2's depth channel supports up to 15 levels (
books15). v3 renames the deepest tier tobooks50(up to 50 levels) and adds a parallelrpi-books*channel for RPI depth â see RPI Orderbook Channel. - The
liquidationchannel is new in UTA and has no v2 equivalent.
WebSocket Private Channelsâ
| Channel | v2 (Classic) Subscription | v3 (UTA) Subscription |
|---|---|---|
| Order updates | {"instType": "USDT-FUTURES", "channel": "orders", "instId": "default"} | {"instType": "UTA", "topic": "order"} |
| Account updates | {"instType": "SPOT", "channel": "account", "coin": "default"} | {"instType": "UTA", "topic": "account"} |
| Position updates | {"instType": "USDT-FUTURES", "channel": "positions", "instId": "default"} | {"instType": "UTA", "topic": "position"} |
v2 uses channel + instType + instId/coin to scope a subscription per product type. v3 simplifies this to a single instType: "UTA" + topic, since one UTA channel now covers all product types at once.
Migration Notesâ
posSide in Hedge ModeIf your account is in Hedge Mode, posSide (long or short) is required. Omitting it will cause the order to be rejected. In One-way Mode, posSide can be omitted.
In v2, size means different things depending on order type and side (base coin vs. quote coin for market buy). In v3, the field is renamed to qty, but the same base-coin/quote-coin distinction for market orders still applies â check the Place Order reference for the product you're trading.
Error code values and meanings are not guaranteed to be identical between v2 and v3, even for conceptually similar failures. Always check the UTA Error Code reference rather than reusing your v2 error-handling logic as-is.
Migration Checklistâ
- Switch or activate the chosen account mode via API or web
- Update your base URL and endpoint paths from
/api/v2/...to/api/v3/... - Update order request payloads: remove
marginCoin/marginMode, addcategoryandposSide, renamesizetoqty - Update pagination logic: rename
idLessThantocursor - Update WebSocket subscriptions: switch from
channel+instTypetoinstType: "UTA"+topic - Re-test order placement, modification, and cancellation end-to-end in demo trading first
- Update your error-handling logic against the UTA error code table
- Verify account/position WebSocket pushes match your expected field names (e.g.
createdTime/updatedTimeinstead ofcTime/uTime)
Code Example: Place Order (v2 vs v3)â
v2 (Classic) â placing a USDT-margined futures order:
curl -X POST "https://api.bitget.com/api/v2/mix/order/place-order" \
-H "ACCESS-KEY:*******" \
-H "ACCESS-SIGN:*******" \
-H "ACCESS-PASSPHRASE:*****" \
-H "ACCESS-TIMESTAMP:1659076670000" \
-H "locale:en-US" \
-H "Content-Type: application/json" \
-d '{
"symbol": "BTCUSDT",
"productType": "usdt-futures",
"marginMode": "crossed",
"marginCoin": "USDT",
"clientOid": "testBTC0123",
"side": "buy",
"orderType": "limit",
"price": "50000",
"size": "0.1"
}'
{
"code": "00000",
"msg": "success",
"data": {
"clientOid": "testBTC0123",
"orderId": "1234567890"
}
}
v3 (UTA) â placing the equivalent order:
curl -X POST "https://api.bitget.com/api/v3/trade/place-order" \
-H "ACCESS-KEY:*******" \
-H "ACCESS-SIGN:*******" \
-H "ACCESS-PASSPHRASE:*****" \
-H "ACCESS-TIMESTAMP:1659076670000" \
-H "locale:en-US" \
-H "Content-Type: application/json" \
-d '{
"category": "USDT-FUTURES",
"symbol": "BTCUSDT",
"clientOid": "testBTC0123",
"side": "buy",
"posSide": "long",
"orderType": "limit",
"price": "50000",
"qty": "0.1",
"timeInForce": "gtc"
}'
{
"code": "00000",
"msg": "success",
"requestTime": 1695806875837,
"data": {
"clientOid": "testBTC0123",
"orderId": "1234567890"
}
}
Notice the request body drops productType/marginMode/marginCoin in favor of category, and adds posSide. The response structure is otherwise the same.
Next Stepsâ
Once your migration is complete, see the Unified Trading Account Best Practices Guide for details on order lifecycle, WebSocket channel behavior, and self-trade prevention under UTA.