# Spot REST API

## Spot Market Endpoints

### Query symbols

`GET ${SPOT_ENDPOINT}/markets/symbols`

*Get trading rules and symbol information for all spot symbols.*

```bash
curl -X GET ${SPOT_ENDPOINT}/markets/symbols \
  -H 'Accept: application/json'
```

#### Query Parameters

| Name     | Type     | Required | Description                    |
| -------- | -------- | -------- | ------------------------------ |
| `symbol` | `string` | `false`  | Symbol name, e.g. `vBTC_vUSDC` |

#### Response

| Field  | Type                | Description                                                                                                                                                               |
| ------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `Array<SpotSymbol>` | Response data when code is `0`. See [`SpotSymbol`](https://sodex.com/documentation/api/schema#spotsymbol) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query coins

`GET ${SPOT_ENDPOINT}/markets/coins`

*Get information for all coins.*

```bash
curl -X GET ${SPOT_ENDPOINT}/markets/coins \
  -H 'Accept: application/json'
```

#### Query Parameters

| Name   | Type     | Required | Description            |
| ------ | -------- | -------- | ---------------------- |
| `coin` | `string` | `false`  | Coin name, e.g. `vBTC` |

#### Response

| Field  | Type              | Description                                                                                                                                                           |
| ------ | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `Array<SpotCoin>` | Response data when code is `0`. See [`SpotCoin`](https://sodex.com/documentation/api/schema#spotcoin) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query tickers

`GET ${SPOT_ENDPOINT}/markets/tickers`

*Get 24hr rolling window price change statistics for all symbols.*

```bash
curl -X GET ${SPOT_ENDPOINT}/markets/tickers \
  -H 'Accept: application/json'
```

#### Query Parameters

| Name     | Type     | Required | Description                    |
| -------- | -------- | -------- | ------------------------------ |
| `symbol` | `string` | `false`  | Symbol name, e.g. `vBTC_vUSDC` |

#### Response

| Field  | Type                | Description                                                                                                                                                               |
| ------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `Array<SpotTicker>` | Response data when code is `0`. See [`SpotTicker`](https://sodex.com/documentation/api/schema#spotticker) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query mini tickers

`GET ${SPOT_ENDPOINT}/markets/miniTickers`

*Get 24hr rolling window price change statistics for all symbols.*

```bash
curl -X GET ${SPOT_ENDPOINT}/markets/miniTickers \
  -H 'Accept: application/json'
```

#### Query Parameters

| Name     | Type     | Required | Description                    |
| -------- | -------- | -------- | ------------------------------ |
| `symbol` | `string` | `false`  | Symbol name, e.g. `vBTC_vUSDC` |

#### Response

| Field  | Type                | Description                                                                                                                                                               |
| ------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `Array<MiniTicker>` | Response data when code is `0`. See [`MiniTicker`](https://sodex.com/documentation/api/schema#miniticker) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query book tickers

`GET ${SPOT_ENDPOINT}/markets/bookTickers`

*Best price/qty on the order book for symbols.*

```bash
curl -X GET ${SPOT_ENDPOINT}/markets/bookTickers \
  -H 'Accept: application/json'
```

#### Query Parameters

| Name     | Type     | Required | Description                    |
| -------- | -------- | -------- | ------------------------------ |
| `symbol` | `string` | `false`  | Symbol name, e.g. `vBTC_vUSDC` |

#### Response

| Field  | Type                | Description                                                                                                                                                               |
| ------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `Array<BookTicker>` | Response data when code is `0`. See [`BookTicker`](https://sodex.com/documentation/api/schema#bookticker) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query order book

`GET ${SPOT_ENDPOINT}/markets/{symbol}/orderbook`

*Get order book depth for a symbol.*

```bash
curl -X GET "${SPOT_ENDPOINT}/markets/vBTC_vUSDC/orderbook?limit=20" \
  -H 'Accept: application/json'
```

#### Path Parameters

| Name     | Type     | Required | Description                    |
| -------- | -------- | -------- | ------------------------------ |
| `symbol` | `string` | `true`   | Symbol name, e.g. `vBTC_vUSDC` |

#### Query Parameters

| Name    | Type     | Required | Description                             |
| ------- | -------- | -------- | --------------------------------------- |
| `limit` | `uint32` | `false`  | Depth limit. Default: `10`, Max: `1000` |

#### Response

| Field  | Type        | Description                                                                                                                                                             |
| ------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `OrderBook` | Response data when code is `0`. See [`OrderBook`](https://sodex.com/documentation/api/schema#orderbook) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query candles/klines

`GET ${SPOT_ENDPOINT}/markets/{symbol}/klines`

*Get candlestick/kline data for a symbol.*

```bash
curl -X GET "${SPOT_ENDPOINT}/markets/vBTC_vUSDC/klines?interval=1h&limit=100" \
  -H 'Accept: application/json'
```

#### Path Parameters

| Name     | Type     | Required | Description                    |
| -------- | -------- | -------- | ------------------------------ |
| `symbol` | `string` | `true`   | Symbol name, e.g. `vBTC_vUSDC` |

#### Query Parameters

| Name        | Type     | Required | Description                                                                               |
| ----------- | -------- | -------- | ----------------------------------------------------------------------------------------- |
| `interval`  | `string` | `true`   | Kline interval: `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `8h`, `12h`, `1D`, `3D`, `1W`, `1M` |
| `startTime` | `uint64` | `false`  | Start time in milliseconds                                                                |
| `endTime`   | `uint64` | `false`  | End time in milliseconds                                                                  |
| `limit`     | `uint32` | `false`  | Number of klines to return. Default: `500`, Max: `1500`                                   |

#### Response

| Field  | Type              | Description                                                                                                                                                           |
| ------ | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `Array<RPCKline>` | Response data when code is `0`. See [`RPCKline`](https://sodex.com/documentation/api/schema#rpckline) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query recent trades

`GET ${SPOT_ENDPOINT}/markets/{symbol}/trades`

*Get recent public trades for a symbol.*

```bash
curl -X GET "${SPOT_ENDPOINT}/markets/vBTC_vUSDC/trades?limit=50" \
  -H 'Accept: application/json'
```

#### Path Parameters

| Name     | Type     | Required | Description                    |
| -------- | -------- | -------- | ------------------------------ |
| `symbol` | `string` | `true`   | Symbol name, e.g. `vBTC_vUSDC` |

#### Query Parameters

| Name    | Type     | Required | Description                                           |
| ------- | -------- | -------- | ----------------------------------------------------- |
| `limit` | `uint32` | `false`  | Number of trades to return. Default: `50`, Max: `500` |

#### Response

| Field  | Type           | Description                                                                                                                                                     |
| ------ | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `Array<Trade>` | Response data when code is `0`. See [`Trade`](https://sodex.com/documentation/api/schema#trade) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

## Spot Accounts Endpoints

### Query balances

`GET ${SPOT_ENDPOINT}/accounts/{userAddress}/balances`

*Get current account balance.*

```bash
curl -X GET "${SPOT_ENDPOINT}/accounts/0x0123456789070ce8f0d6bab722103d12674bc257/balances" \
  -H 'Accept: application/json'
```

#### Path Parameters

| Name          | Type        | Required | Description      |
| ------------- | ----------- | -------- | ---------------- |
| `userAddress` | `HexString` | `true`   | User EVM address |

#### Query Parameters

| Name        | Type     | Required | Description                                                            |
| ----------- | -------- | -------- | ---------------------------------------------------------------------- |
| `accountID` | `uint64` | `false`  | The sub-account ID of the user. Primary account ID is used by default. |

#### Response

| Field  | Type                  | Description                                                                                                                                                                                 |
| ------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `SpotAccountBalances` | Response data when code is `0`. See [`SpotAccountBalances`](https://sodex.com/documentation/api/schema#spotaccountbalances) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query open orders

`GET ${SPOT_ENDPOINT}/accounts/{userAddress}/orders`

*Get all open orders for an account.*

```bash
curl -X GET "${SPOT_ENDPOINT}/accounts/0x0123456789070ce8f0d6bab722103d12674bc257/orders?symbol=vBTC_vUSDC" \
  -H 'Accept: application/json'
```

#### Path Parameters

| Name          | Type        | Required | Description      |
| ------------- | ----------- | -------- | ---------------- |
| `userAddress` | `HexString` | `true`   | User EVM address |

#### Query Parameters

| Name        | Type     | Required | Description                                                            |
| ----------- | -------- | -------- | ---------------------------------------------------------------------- |
| `symbol`    | `string` | `false`  | Filter by symbol name                                                  |
| `accountID` | `uint64` | `false`  | The sub-account ID of the user. Primary account ID is used by default. |

#### Response

| Field  | Type                   | Description                                                                                                                                                                                   |
| ------ | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `SpotAccountOpenOrder` | Response data when code is `0`. See [`SpotAccountOpenOrder`](https://sodex.com/documentation/api/schema#spotaccountopenorder) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query state for frontend

`GET ${SPOT_ENDPOINT}/accounts/{userAddress}/state`

*Get comprehensive account state for UI initialization. Includes balances, open orders, and sync metadata.*

```bash
curl -X GET "${SPOT_ENDPOINT}/accounts/0x0123456789070ce8f0d6bab722103d12674bc257/state" \
  -H 'Accept: application/json'
```

#### Path Parameters

| Name          | Type        | Required | Description      |
| ------------- | ----------- | -------- | ---------------- |
| `userAddress` | `HexString` | `true`   | User EVM address |

#### Query Parameters

| Name        | Type     | Required | Description                                                            |
| ----------- | -------- | -------- | ---------------------------------------------------------------------- |
| `accountID` | `uint64` | `false`  | The sub-account ID of the user. Primary account ID is used by default. |

#### Response

| Field  | Type          | Description                                                                                                                                                                 |
| ------ | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `WsSpotState` | Response data when code is `0`. See [`WsSpotState`](https://sodex.com/documentation/api/schema#wsspotstate) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query API Keys

`GET ${SPOT_ENDPOINT}/accounts/{userAddress}/api-keys`

*Get list of API keys.*

```bash
curl -X GET "${SPOT_ENDPOINT}/accounts/0x0123456789070ce8f0d6bab722103d12674bc257/api-keys" \
  -H 'Accept: application/json'
```

#### Path Parameters

| Name          | Type        | Required | Description      |
| ------------- | ----------- | -------- | ---------------- |
| `userAddress` | `HexString` | `true`   | User EVM address |

#### Query Parameters

| Name        | Type     | Required | Description                                                            |
| ----------- | -------- | -------- | ---------------------------------------------------------------------- |
| `accountID` | `uint64` | `false`  | The sub-account ID of the user. Primary account ID is used by default. |
| `name`      | `string` | `false`  | The name of the API key.                                               |

#### Response

| Field  | Type            | Description                                                                                                                                                       |
| ------ | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `Array<APIKey>` | Response data when code is `0`. See [`APIKey`](https://sodex.com/documentation/api/schema#apikey) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query fee rate

`GET ${SPOT_ENDPOINT}/accounts/{userAddress}/fee-rate`

*Get the current maker/taker fee rates for the account, including fee tier, staking tier, and maker rebate tier. Optionally pass a symbol to include the symbol-level fee discount.*

```bash
curl -X GET "${SPOT_ENDPOINT}/accounts/0x0123456789070ce8f0d6bab722103d12674bc257/fee-rate?symbol=vBTC_vUSDC" \
  -H 'Accept: application/json'
```

#### Path Parameters

| Name          | Type        | Required | Description      |
| ------------- | ----------- | -------- | ---------------- |
| `userAddress` | `HexString` | `true`   | User EVM address |

#### Query Parameters

| Name        | Type     | Required | Description                                                                              |
| ----------- | -------- | -------- | ---------------------------------------------------------------------------------------- |
| `accountID` | `uint64` | `false`  | The sub-account ID of the user. Primary account ID is used by default.                   |
| `symbol`    | `string` | `false`  | Symbol name, e.g. `vBTC_vUSDC`. When provided, the symbol-level fee discount is applied. |

#### Response

| Field  | Type      | Description                                                                                                                                                         |
| ------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `FeeRate` | Response data when code is `0`. See [`FeeRate`](https://sodex.com/documentation/api/schema#feerate) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query order history

`GET ${SPOT_ENDPOINT}/accounts/{userAddress}/orders/history`

*Get historical orders (filled, canceled, expired) for an account.*

```bash
curl -X GET "${SPOT_ENDPOINT}/accounts/0x0123456789070ce8f0d6bab722103d12674bc257/orders/history?symbol=vBTC_vUSDC" \
  -H 'Accept: application/json'
```

#### Path Parameters

| Name          | Type        | Required | Description      |
| ------------- | ----------- | -------- | ---------------- |
| `userAddress` | `HexString` | `true`   | User EVM address |

#### Query Parameters

| Name        | Type     | Required | Description                                                            |
| ----------- | -------- | -------- | ---------------------------------------------------------------------- |
| `accountID` | `uint64` | `false`  | The sub-account ID of the user. Primary account ID is used by default. |
| `symbol`    | `string` | `false`  | Filter by symbol name                                                  |
| `startTime` | `uint64` | `false`  | Start time in milliseconds                                             |
| `endTime`   | `uint64` | `false`  | End time in milliseconds                                               |
| `limit`     | `uint32` | `false`  | Number of orders to return. Default: `50`, Max: `500`                  |

#### Response

| Field  | Type               | Description                                                                                                                                                             |
| ------ | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `Array<SpotOrder>` | Response data when code is `0`. See [`SpotOrder`](https://sodex.com/documentation/api/schema#spotorder) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Query user trades

`GET ${SPOT_ENDPOINT}/accounts/{userAddress}/trades`

*Get historical trade executions for an account.*

```bash
curl -X GET "${SPOT_ENDPOINT}/accounts/0x0123456789070ce8f0d6bab722103d12674bc257/trades?symbol=vBTC_vUSDC&limit=100" \
  -H 'Accept: application/json'
```

#### Path Parameters

| Name          | Type        | Required | Description      |
| ------------- | ----------- | -------- | ---------------- |
| `userAddress` | `HexString` | `true`   | User EVM address |

#### Query Parameters

| Name        | Type     | Required | Description                                                            |
| ----------- | -------- | -------- | ---------------------------------------------------------------------- |
| `accountID` | `uint64` | `false`  | The sub-account ID of the user. Primary account ID is used by default. |
| `symbol`    | `string` | `false`  | Filter by symbol name                                                  |
| `orderID`   | `uint64` | `false`  | Filter by order ID                                                     |
| `startTime` | `uint64` | `false`  | Start time in milliseconds                                             |
| `endTime`   | `uint64` | `false`  | End time in milliseconds                                               |
| `limit`     | `uint32` | `false`  | Number of trades to return. Default: `100`, Max: `1000`                |

#### Response

| Field  | Type               | Description                                                                                                                                                             |
| ------ | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `Array<UserTrade>` | Response data when code is `0`. See [`UserTrade`](https://sodex.com/documentation/api/schema#usertrade) in [Schema](https://sodex.com/documentation/api/rest-v1/schema) |

### Transfer asset to EVM or perps

`POST ${SPOT_ENDPOINT}/accounts/transfers`

*Transfer assets between accounts.*

* Auth: signed write

```bash
curl -X POST ${SPOT_ENDPOINT}/accounts/transfers \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'X-API-Key: <API-Key>' \
  -H 'X-API-Sign: <API-Sign>' \
  -H 'X-API-Nonce: <API-Nonce>' \
  -d <TransferAssetRequest>
```

#### Request Body

See [`TransferAssetRequest`](https://sodex.com/documentation/api/schema#transferassetrequest) in [Schema](https://sodex.com/documentation/api/rest-v1/schema)

Additional Information:

* Number of decimal places of `transfer.amount` should not exceed coin precision. That is `transfer.amount % 10^{-coin.precision} = 0`.
* The `transfer.amount` must be a positive value.
* Transfer asset to EVM chain: `transfer.toAccountID=999`, `transfer.type=EVM_WITHDRAW`
* Transfer asset to perps chain: `transfer.toAccountID=999`, `transfer.type=PERPS_WITHDRAW`
* Internal transfer between spot chains is not supported yet.

#### Response

| Field  | Type           | Description                     |
| ------ | -------------- | ------------------------------- |
| `data` | `ResponseData` | Response data when code is `0`. |

* `ResponseData`

  | Name | Type     | Required | Description                                                                   |
  | ---- | -------- | -------- | ----------------------------------------------------------------------------- |
  | `id` | `uint64` | `true`   | Identifier for this transfer request. Same as `id` in `TransferAssetRequest`. |

## Spot Trading Endpoints

### Place multiple orders

`POST ${SPOT_ENDPOINT}/trade/orders/batch`

*Submit multiple orders atomically.*

* Auth: signed write

```bash
curl -X POST ${SPOT_ENDPOINT}/trade/orders/batch \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'X-API-Key: <API-Key>' \
  -H 'X-API-Sign: <API-Sign>' \
  -H 'X-API-Nonce: <API-Nonce>' \
  -d <BatchNewOrderParams>
```

#### Request Body

Find `BatchNewOrderRequest` and `BatchNewOrderItem` in [Schema](https://sodex.com/documentation/api/rest-v1/schema)

Additional Information:

* The batch cannot be empty.
* The length of batch should less than or equals to `100`.
* Basic Validation
  * The `order[i].clOrdID` must match `^[0-9a-zA-Z_-]{1,36}$`.
  * `order[i].clOrdID` must be unique among open orders. Reuse is allowed only after the previous order is filled.
  * For limit order
    * `order[i].timeInForce` can be `GTC`, `IOC`, `GTX`.
    * provide both `order[i].price` and `order[i].quantity`, do not send `order[i].funds`.
  * For market order
    * `order[i].timeInForce` must be `IOC`.
    * Provide either `order[i].quantity` or `order[i].funds`, not both. `order[i].funds` only available for market buy orders.
    * `order[i].price` optional for slippage protection.
  * The order will be rejected if basic validation failed.
* Price filter
  * The decimal precision of order price should not exceed `symbol.pricePrecision`. That is `order[i].price % 10^{-symbol.pricePrecision} = 0`.
  * The order price must be multiple of `symbol.tickSize`. That is `order[i].price % symbol.tickSize = 0`.
  * If `symbol.minPrice` is not `0`, the order price should greater than or equals to `symbol.minPrice`.
  * If `symbol.maxPrice` is not `0`, the order price should less than or equals to `symbol.maxPrice`.
  * The order will be rejected if price filter check failed.
* Lot size filter
  * The decimal precision of order quantity should not exceed `symbol.quantityPrecision`. That is `order[i].quantity % 10^{-symbol.quantityPrecision} = 0`.
  * The order quantity must be multiple of `symbol.stepSize`. That is `order[i].quantity % symbol.stepSize = 0`.
  * If `symbol.minQuantity` is not `0`, the order quantity should greater than or equals to `symbol.minQuantity`.
  * If `symbol.maxQuantity` is not `0`, the order quantity should less than or equals to `symbol.maxQuantity`.
  * The order will be rejected if lot size filter check failed.
* Market lot size filter
  * This is an additional check for market order.
  * If `symbol.marketMinQuantity` is not `0`, the order quantity should greater than or equals to `symbol.marketMinQuantity`.
  * If `symbol.marketMaxQuantity` is not `0`, the order quantity should less than or equals to `symbol.marketMaxQuantity`.
  * The order will be rejected if market lot filter check failed.
* Notional filter
  * For limit order, the order notional is `order[i].price * order[i].quantity`.
  * For market order with `order[i].funds` provided, the order notional is `order[i].funds`.
  * For market order without `order[i].funds`, the order notional is estimated as `symbol.lastTradePrice * order[i].quantity`.
  * If `symbol.minNotional` is not `0`, the order notional should greater than or equals to `symbol.minNotional`.
  * If `symbol.maxNotional` is not `0`, the order notional should less than or equals to `symbol.maxNotional`.
  * The order will be rejected if notional filter check failed.
* Other price limitation
  * for limit buy orders, the order price should less than or equal to `symbol.lastTradePrice * (1 + symbol.buyLimitUpRatio)`. Otherwise, the order is rejected.
  * for limit sell orders, the order price should greater than or equal to `symbol.lastTradePrice * (1 - symbol.sellLimitDownRatio)`. Otherwise, the order is rejected.
  * for market buy orders without price, the final execution price is bounded by `symbol.lastTradePrice * (1 + symbol.marketDeviationRatio)`. If price is provided, the final execution price is bounded by `min(order[i].price, symbol.lastTradePrice * (1 + symbol.marketDeviationRatio))`
  * for market sell orders without price, the final execution price is bounded by `symbol.lastTradePrice * (1 - symbol.marketDeviationRatio)`. If price is provided, the final execution price is bounded by `max(order[i].price, symbol.lastTradePrice * (1 - symbol.marketDeviationRatio))`

#### Response

| Field  | Type                  | Description                     |
| ------ | --------------------- | ------------------------------- |
| `data` | `Array<ResponseData>` | Response data when code is `0`. |

* `ResponseData`

  | Name      | Type     | Required | Description                                                                 |
  | --------- | -------- | -------- | --------------------------------------------------------------------------- |
  | `code`    | `int32`  | `true`   | Response status code, `0` for success and other code for failure.           |
  | `clOrdID` | `string` | `true`   | Client order id; same as `clOrdID` in `BatchNewOrderItem`.                  |
  | `error`   | `string` | `false`  | Error description for individual order. Only provided when code is not `0`. |
  | `orderID` | `uint64` | `false`  | Order id. Only provided when the code is `0`.                               |

The length of the response result array is usually the same as the length of batched request.

**Important**: Some errors are a deterministic function of the payload itself, and these are instead returned earlier as part of pre-validation. In this case, only one error is returned for the entire payload, as some of these errors do not apply to a specific order.

For API users that use batching, it's recommended to handle the case where a single error is returned for a batch of multiple orders. In this case, the response could be duplicated n times before being sent to the callback function, as the whole batch was rejected for this same reason.

### Cancel multiple orders

`DELETE ${SPOT_ENDPOINT}/trade/orders/batch`

*Submit multiple order cancellations atomically.*

* Auth: signed write

```bash
curl -X DELETE ${SPOT_ENDPOINT}/trade/orders/batch \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'X-API-Key: <API-Key>' \
  -H 'X-API-Sign: <API-Sign>' \
  -H 'X-API-Nonce: <API-Nonce>' \
  -d <BatchCancelOrderRequest>
```

#### Request Body

Find `BatchCancelOrderRequest` and `BatchCancelOrderItem` in [Schema](https://sodex.com/documentation/api/rest-v1/schema)

Additional Information:

* The batch cannot be empty.
* The length of batch should less than or equals to `100`.

#### Response

| Field  | Type                  | Description                     |
| ------ | --------------------- | ------------------------------- |
| `data` | `Array<ResponseData>` | Response data when code is `0`. |

* `ResponseData`

  | Name          | Type     | Required | Description                                                                 |
  | ------------- | -------- | -------- | --------------------------------------------------------------------------- |
  | `code`        | `int32`  | `true`   | Response status code, `0` for success and other code for failure.           |
  | `clOrdID`     | `string` | `true`   | Client order id; same as `clOrdID` in `BatchCancelOrderItem`.               |
  | `error`       | `string` | `false`  | Error description for individual order. Only provided when code is not `0`. |
  | `orderID`     | `uint64` | `false`  | Order id. Only provided when the code is `0`.                               |
  | `origClOrdID` | `string` | `false`  | Client order id of the canceled order. Only provided when code is `0`.      |

The length of the response result array is usually the same as the length of batched request.

**Important**: Some errors are a deterministic function of the payload itself, and these are instead returned earlier as part of pre-validation. In this case, only one error is returned for the entire payload, as some of these errors do not apply to a specific order.

For API users that use batching, it's recommended to handle the case where a single error is returned for a batch of multiple orders. In this case, the response could be duplicated n times before being sent to the callback function, as the whole batch was rejected for this same reason.

### Replace multiple orders

`POST ${SPOT_ENDPOINT}/trade/orders/replace`

*Replace/modify existing orders atomically.*

* Auth: signed write

```bash
curl -X POST ${SPOT_ENDPOINT}/trade/orders/replace \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'X-API-Key: <API-Key>' \
  -H 'X-API-Sign: <API-Sign>' \
  -H 'X-API-Nonce: <API-Nonce>' \
  -d <ReplaceOrderRequest>
```

#### Request Body

Find `ReplaceOrderRequest` and `ReplaceParams` in [Schema](https://sodex.com/documentation/api/rest-v1/schema)

Additional Information:

* Basic Validation
  * The batch cannot be empty.
  * The length of batch should less than or equals to `100`.
  * Only limit `GTC` and limit `GTX` can be replaced.
  * Only order with status `NEW` and `PARTIALLY_FILLED` can be replaced.
  * Either `replace.origOrderID` or `replace.origClOrdID` should be provided, but not both.
  * At least one of `replace.price` and `replace.quantity` should be provided.
* Price filter
  * The decimal precision of replacement price should not exceed `symbol.pricePrecision`, if provided. That is `replace.price % 10^{-symbol.pricePrecision} = 0`.
  * The replacement price must be multiple of `symbol.tickSize`. That is `replace.price % symbol.tickSize = 0`.
  * If `symbol.minPrice` is not `0`, the replacement price should greater than or equals to `symbol.minPrice`.
  * If `symbol.maxPrice` is not `0`, the replacement price should less than or equals to `symbol.maxPrice`.
  * The replacement will be rejected if price filter check failed.
* Lot size filter
  * The decimal precision of replacement quantity should not exceed `symbol.quantityPrecision`. That is `replace.quantity % 10^{-symbol.quantityPrecision} = 0`.
  * The replacement quantity must be multiple of `symbol.stepSize`. That is `replace.quantity % symbol.stepSize = 0`.
  * If `symbol.minQuantity` is not `0`, the replacement quantity should greater than or equals to `symbol.minQuantity`.
  * If `symbol.maxQuantity` is not `0`, the replacement quantity should less than or equals to `symbol.maxQuantity`.
  * The replacement will be rejected if lot size filter check failed.
* Notional filter
  * The replacement notional is `replace.price * replace.quantity`. If `replace.price` not provided, `order.price` is used. If `replace.quantity` not provided, `order.quantity` is used.
  * If `symbol.minNotional` is not `0`, the replacement notional should greater than or equals to `symbol.minNotional`.
  * If `symbol.maxNotional` is not `0`, the replacement notional should less than or equals to `symbol.maxNotional`.
  * The replacement will be rejected if notional filter check failed.

#### Response

| Field  | Type                  | Description                     |
| ------ | --------------------- | ------------------------------- |
| `data` | `Array<ResponseData>` | Response data when code is `0`. |

* `ResponseData`

  | Name      | Type     | Required | Description                                                                 |
  | --------- | -------- | -------- | --------------------------------------------------------------------------- |
  | `code`    | `int32`  | `true`   | Response status code, `0` for success and other code for failure.           |
  | `clOrdID` | `string` | `true`   | Client order id; same as `clOrdID` in `ReplaceParams`.                      |
  | `error`   | `string` | `false`  | Error description for individual order. Only provided when code is not `0`. |
  | `orderID` | `uint64` | `false`  | Order id of the replaced order. Only provided when the code is `0`.         |

The length of the response result array is usually the same as the length of batched request.

**Important**: Some errors are a deterministic function of the payload itself, and these are instead returned earlier as part of pre-validation. In this case, only one error is returned for the entire payload, as some of these errors do not apply to a specific order.

For API users that use batching, it's recommended to handle the case where a single error is returned for a batch of multiple orders. In this case, the response could be duplicated n times before being sent to the callback function, as the whole batch was rejected for this same reason.

### Schedule cancel orders

`POST ${SPOT_ENDPOINT}/trade/orders/schedule-cancel`

*Schedule a cancel-all operation at a future time. Omitting the time clears the scheduled cancel.*

* Auth: signed write

```bash
curl -X POST ${SPOT_ENDPOINT}/trade/orders/schedule-cancel \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'X-API-Key: <API-Key>' \
  -H 'X-API-Sign: <API-Sign>' \
  -H 'X-API-Nonce: <API-Nonce>' \
  -d <ScheduleCancelRequest>
```

#### Request Body

See [`ScheduleCancelRequest`](https://sodex.com/documentation/api/schema#schedulecancelrequest) in [Schema](https://sodex.com/documentation/api/rest-v1/schema)

| Name                 | Type     | Required | Description                                                             |
| -------------------- | -------- | -------- | ----------------------------------------------------------------------- |
| `accountID`          | `uint64` | `true`   | Account identifier.                                                     |
| `scheduledTimestamp` | `uint64` | `false`  | Unix timestamp in milliseconds when the cancel-all should be triggered. |

Additional Information:

* The scheduled time must be at least `5` seconds after the current time.
* When triggered, all open orders are canceled and a trigger count increments (max `10` per day, resets at `00:00 UTC`).
* Omitting `scheduledTimestamp` removes the scheduled cancel.

#### Response

* No endpoint-specific `data` payload.
