Trading

trade-order-batch-place

Place multiple new orders in a single request (Batch Order).

General rules

  • Up to 50 orders per request. Orders may belong to different accounts, but every account must be in the list of accounts granted to the API Key.
  • Validation is all-or-nothing: if any order in the batch is invalid, the entire request is rejected (HTTP 400) and no order is executed.
  • Once validation passes, each order is processed independently. An order rejected during processing (for example, insufficient buying power) does not affect the others; the outcome of each order is returned in results (success, errorCode, errorMessage).
  • Replay protection: batchRequestTime (epoch milliseconds, UTC) must be within 30 seconds of server time.
  • Idempotency: batchRequestId must be unique per API Key and per action (place/cancel) within a day. Resending the same batchRequestId is rejected as a duplicate request.
  • The X-Signature is computed over the entire request body (including batchRequestId, batchRequestTime and orders).
  • Each order in orders follows the same rules as the single-order API trade-order-place.

Required scope: trading:order:post.

POST
/api/v3/trading/order/batch

Authorization

Bearer
AuthorizationBearer <token>

Enter the JWT token in the format Bearer <token>.

In: header

Header Parameters

Content-Typestringrequired

The format of the request body content. Primarily application/json.

User-Agentstringoptional

Information about the client sending the request.

Accept-Languagestringoptional

The desired response language. If this header is absent, the system will default to en

X-Signaturestringrequired

The HMAC-SHA256 signature used to verify the integrity of the request.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

bodyobjectrequired
batchRequestIdstringrequired

Batch identifier created by the client. Must be unique per API Key and per action (place/cancel) within a day. Used as the idempotency key; resending the same value is rejected as a duplicate request.

batchRequestTimeintegerrequired

The time the client created the batch, in epoch milliseconds (UTC). Must be within 30 seconds of server time, otherwise the request is rejected (replay protection).

ordersarrayrequired

List of orders to place, up to 50. Each element has the same structure as the single-order placement request.

orders[]objectrequired
clientRequestIdstring | nulloptional

An order identifier created by the client, used for reconciliation in subsequent responses. This field is optional, but if provided it should be unique to avoid confusion when processing responses. When left empty, the system will automatically generate an order identifier for the customer and return it in the response & streaming.

accountNostringrequired

The trading account number.

symbolstringrequired

The securities symbol.

sidestringrequired

The buy or sell side of the trading order. (B - Buy, S - Sell)

orderTypestringrequired

The type of the trading order. (LO - Limit Order, ATO - At The Open, ATC - At The Close, MP - Market Price, MAK - Match and Kill, MOK - Match or Kill, MTL - Match then Limit, PLO)

quantitynumberrequired

The order quantity.

pricestringrequired

The order price. Required when orderType is LO (Limit Order); not required for other order types (ATO, ATC, MP, MAK, MOK, MTL, PLO).

deviceIdstringrequired

The identifier of the device sending the order placement request. Typically the device's MAC address or IMEI.

userAgentstringoptional

Information about the browser or application sending the request.

ipAddressstringoptional

The IP address of the device sending the request.

isReturnOrderIdboolean | nulloptional

Optional — whether the response should include `orderId`. When omitted (or `null`), the system uses a default based on the account type: - Equity accounts: default `true` (the response includes `orderId`). - Derivatives accounts: default `false` (the response has no `orderId`; get it from streaming or the order book). For derivatives accounts, send `true` to receive `orderId` in the response. When the effective value is `false`, `orderId` in the response is `null`; the order is still placed normally and can still be modified/cancelled by `clientRequestId`. For the WebSocket API (`order.place`, `order.batchNew`), the `PD` ack never includes `orderId` regardless of this value; `orderId` arrives on the `order.{accountNo}` channel.

Response Headers

X-RATELIMIT-LIMITstringoptional

The request limit within the cycle.

X-RATELIMIT-REMAININGstringoptional

The number of requests remaining in the current cycle.

X-RATELIMIT-RESETstringoptional

The time at which the request limit resets.

Response Body

application/json

application/json

curl -X POST "https://api.ssi.com.vn/api/v3/trading/order/batch" \  -H "Content-Type: application/json" \  -H "X-Signature: sha256=abc123..." \  -H "Content-Type: application/json" \  -d '{    "batchRequestId": "string",    "batchRequestTime": 1760400000000,    "orders": [      {        "accountNo": "string",        "symbol": "string",        "side": "B",        "orderType": "LO",        "quantity": 0.1,        "price": "string",        "deviceId": "string"      }    ]  }'

The request is valid and has been processed. The outcome of each order is in results.

{
  "batchRequestId": "string",
  "results": [
    {
      "clientRequestId": "string",
      "orderId": "string",
      "orderStatus": "string",
      "success": true,
      "errorCode": "string",
      "errorMessage": "string"
    }
  ]
}

Invalid request.

{
  "code": "400",
  "msg": "Invalid request"
}