# 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)](https://www.bitget.com/support/articles/12560603818930) 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](https://www.bitget.com/support/articles/12560603830157) for step-by-step instructions.
- **Via the API**: call the [Upgrade Account](https://www.bitget.com/api-doc/classic/spot/account/Upgrade_Account) endpoint. The API supports the master account initiating the upgrade itself, as well as upgrading sub-accounts.

## Authentication and Signature

:::tip{title="No changes required"}
The signature mechanism is identical between v2 and v3.
:::

Every REST request still needs these headers:

- `ACCESS-KEY`
- `ACCESS-SIGN` (HMAC-SHA256, base64-encoded)
- `ACCESS-TIMESTAMP`
- `ACCESS-PASSPHRASE`
- `Content-Type: application/json`

:::tip{title="No changes required"}
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)<br/>`POST /api/v2/spot/trade/place-order` (spot) | `POST /api/v3/trade/place-order` (all products) |
| Cancel order | `POST /api/v2/mix/order/cancel-order`<br/>`POST /api/v2/spot/trade/cancel-order` | `POST /api/v3/trade/cancel-order` |
| Modify order | `POST /api/v2/mix/order/modify-order`<br/>`POST /api/v2/spot/trade/cancel-replace-order`<br/>No WebSocket support | `POST /api/v3/trade/modify-order`<br/>WebSocket 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-orders`<br/>`GET /api/v2/mix/order/orders-pending` | `GET /api/v3/trade/unfilled-orders` |
| Historical orders | `GET /api/v2/spot/trade/history-orders`<br/>`GET /api/v2/mix/order/orders-history` | `GET /api/v3/trade/history-orders` |
| Fill details | `GET /api/v2/spot/trade/fills`<br/>`GET /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)<br/>`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)<br/>`GET /api/v2/mix/market/contracts` (futures) | `GET /api/v3/public/instruments` (all products) |
| Get ticker | `GET /api/v2/spot/market/tickers` (spot)<br/>`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)<br/>`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)<br/>`GET /api/v2/mix/market/candles` (futures) | `GET /api/v3/market/candles` (all products) |
| Get recent trades | `GET /api/v2/spot/market/fills` (spot)<br/>`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"}` |

:::info{title="Key structural changes"}
- v2 encodes the candle interval into the channel name (e.g. `candle1m`, `candle5m`). v3 keeps `topic: "kline"` fixed and passes the interval as a separate `interval` field.
- v2's depth channel supports up to 15 levels (`books15`). v3 renames the deepest tier to `books50` (up to 50 levels) and adds a parallel `rpi-books*` channel for RPI depth — see [RPI Orderbook Channel](/docs/uta/websocket/public/RPI-OrderBook-Channel).
- The `liquidation` channel 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"}` |

:::info{title="Key structural change"}
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.
:::

## SDK V3 Version Notes

Bitget V3 will provide official SDKs in the following languages:

- ☕ **[Java](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-java-sdk-api)**
- 🐍 **[Python](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-python-sdk-api)**
- 🟩 **[Node.js](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-node-sdk-api)**
- 🐹 **[Golang](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-golang-sdk-api)**
- 🐘 **[PHP](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-php-sdk-api)**

## Migration Notes

:::warning{title="Note 1 — Forgetting to set `posSide` in Hedge Mode"}
If 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.
:::

:::warning{title="Note 2 — Expecting order size to mean the same thing across product types"}
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](/docs/catalog/trading/order-management) reference for the product you're trading.
:::

:::warning{title="Note 3 — Assuming error codes are unchanged"}
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](/docs/uta/error-code/restapi) reference rather than reusing your v2 error-handling logic as-is.
:::

## Migration Checklist

- [ ] Switch the account mode to UTA via Web/API
- [ ] Update your base URL and endpoint paths from `/api/v2/...` to `/api/v3/...`
- [ ] Update order request payloads: remove `marginCoin`/`marginMode`, add `category` and `posSide`, rename `size` to `qty`
- [ ] Update pagination logic: rename `idLessThan` to `cursor`
- [ ] Update WebSocket subscriptions: switch from `channel`+`instType` to `instType: "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`/`updatedTime` instead of `cTime`/`uTime`)

## Code Example: Place Order (v2 vs v3)

**v2 (Classic) — placing a USDT-margined futures order:**

```bash title="Request Example"
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"
}'
```

```json title="Response Example"
{
  "code": "00000",
  "msg": "success",
  "data": {
    "clientOid": "testBTC0123",
    "orderId": "1234567890"
  }
}
```

**v3 (UTA) — placing the equivalent order:**

```bash title="Request Example"
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"
}'
```

```json title="Response Example"
{
  "code": "00000",
  "msg": "success",
  "requestTime": 1695806875837,
  "data": {
    "clientOid": "testBTC0123",
    "orderId": "1234567890"
  }
}
```

:::info{title="Note"}
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](https://www.bitget.com/api-doc/uta/best-practices) for details on order lifecycle, WebSocket channel behavior, and self-trade prevention under UTA.
