NodeJS

Models

TypeScript interfaces and streaming message types in Node.js SDK

Models are TypeScript interfaces (Token and OTPResponse are classes). Import from the main package.

Module Structure

@ssi.developer/ssi-sdk
├── Auth, Data, Trading, Stream  (client classes)
├── Config                        (configuration)
├── models/
│   ├── auth        → Token, OTPResponse
│   ├── account     → Account
│   ├── marketData  → OHLCData, MarketIndexes, MarketIndexSummary, SecuritiesInfo, SecuritiesSummary, MasterData,
│   │                 CorporateAction
│   ├── trading     → PlaceOrderResponse, ModifyOrderResponse, CancelOrderResponse, MaxBuySellResponse,
│   │                 BatchPlaceOrderItem, BatchCancelOrderItem, BatchOrderResponse, BatchOrderResult
│   ├── portfolio   → EquityAccountBalance, DerivativeAccountBalance, EquityPosition, DerivativePosition,
│   │                 AllDerivativePosition, Order
│   ├── streaming   → DataMessage, TradingMessage, HeartbeatMessage, IndexTickMessage, IntervalMessage,
│   │                 IndexSummaryMessage, FCOOrderUpdateMessage, ...
│   └── fco         → FCOInfo, FCOParams, FCOListResponse, FCOOrder, FCOOrderBookResponse, FCOPlaceResponse,
│                     FCOCancelResponse, FCOStatusHistoryItem
├── enums/          → OrderSide, OrderType, Board, Timeframe, FCOType, FCOOperator, FCOStatus, ...
├── exceptions      → SSIError, APIError, AuthenticationError, ...
└── Trading WebSocket
                    → asyncTradingWs, tradingWs, TradingWSClient, TradingWSService, MUTATING_METHODS,
                      TradingWSResponse, FcoParamsKind, FcoListOptions, OrderBookQuery

The feature groups below all point back to API Services, which describes how to use them:

  • Batch Orders: BatchPlaceOrderItem, BatchCancelOrderItem, BatchOrderResponse, BatchOrderResult.
  • Real-time Index Data: IndexTickMessage, IntervalMessage, IndexSummaryMessage.
  • Trading WebSocket: TradingWSResponse, FcoParamsKind, FcoListOptions and OrderBookQuery.

Authentication

Token

FieldTypeDescription
accessTokenstringAccess token
tokenTypestringToken type (default "Bearer")
expiresAtnumberWhen the access token expires, epoch seconds (0 = unknown, treated as expired)
refreshTokenstringRefresh token
refreshExpiresAtnumberWhen the refresh token expires, epoch seconds. Formerly named refreshTokenExpiresAt

Besides the fields, Token has:

MemberTypeDescription
effectiveExpiresAtnumber (getter)Epoch seconds after which this token set cannot be used without a new OTP: the earlier of the two expiries, ignoring an unknown one. 0 when both are unknown
canRefreshboolean (getter)A refresh token is present and not (about to be) expired. If the refresh expiry is unknown it still returns true, and the server rejects the token if it is dead
toDict()Record<string, unknown>The raw token values (use it only when you really need to persist them)

toString(), console.log and JSON.stringify of a Token mask accessToken and refreshToken. Only toDict() returns the real values, so do not log its result.

OTPResponse

Result of requestOtpTyped() (see Client Classes). OTPResponse is also a class and masks transactionId under JSON.stringify.

FieldTypeDescription
messagestringServer message ("" if none)
transactionIdstring?Only present for Smart OTP (push approval). SMS/e-mail OTP responses carry just message

Account

Account

FieldTypeDescription
accountNostringAccount number
accountTypeAccountType | string | number | undefinedAccount type. An AccountType when the SDK knows it, the raw value when it does not, undefined when the server omits it

Market Data

OHLCData

FieldTypeDescription
symbolstringSecurity symbol
tradingDatestringTrading date
openPricenumberOpen price
highPricenumberHigh price
lowPricenumberLow price
closePricenumberClose price
volumenumberVolume
valuenumberTrade value

MarketIndexes

FieldTypeDescription
indexstringIndex code
indexNamestringIndex name
boardBoard | string | undefinedBoard. A Board when the SDK knows it, the raw string when it does not
boardRawstring?The board exactly as the server sent it

MarketIndexSummary

FieldTypeDescription
tradingDatestringTrading date
indexValuenumberIndex value
indexChangenumberChange
indexChangePercentnumberChange (%)
totalTradenumberTotal trade volume
totalTradeValuenumberTotal trade value
totalAdvanceStocknumberAdvancing stocks
totalDeclineStocknumberDeclining stocks
totalSteadyStocknumberUnchanged stocks
totalMatchnumberTotal matched volume
totalMatchValuenumberTotal matched value
totalDealnumberTotal deal volume
totalDealValuenumberTotal deal value
totalCeilingStocknumberCeiling stocks
totalFloorStocknumberFloor stocks
totalPropBuynumberTotal proprietary buy volume
totalPropBuyValuenumberTotal proprietary buy value
totalPropSellnumberTotal proprietary sell volume
totalPropSellValuenumberTotal proprietary sell value
totalBuyForeignnumber?Foreign buy volume
totalBuyForeignValuenumber?Foreign buy value
totalSellForeignnumber?Foreign sell volume
totalSellForeignValuenumber?Foreign sell value
netPurchasesForeignVolumenumber?Net foreign purchase volume
netPurchasesForeignValuenumber?Net foreign purchase value

The foreign fields are undefined when the server omits them.

SecuritiesInfo

A numeric field that the server omits or leaves empty is undefined (not 0). An empty string also becomes undefined.

FieldTypeDescription
symbolstringSecurity symbol
boardBoard | string?Board
indexstring?Index
symbolNameVistring?Vietnamese name
symbolNameEnstring?English name
lotSizenumber?Trading lot size
listedSharesnumber?Listed shares
icbCodestring?ICB code
icbNamestring?ICB name
maturityDatestring?Maturity date
firstTradingDatestring?First trading date
lastTradingDatestring?Last trading date
cwUnderlyingSymbolstring?CW underlying symbol
cwExercisePricenumber?CW exercise price
cwExecutionRationumber?CW execution ratio
iIndexnumber?I index
iNavnumber?iNAV value
openInterestnumber?Open interest (OI)
settlementPricenumber?Settlement price
stockTypestring?Security type code

SecuritiesSummary

FieldTypeDescription
symbolstringSecurity symbol
tradingDatestringTrading date
priceChangenumberPrice change
priceChangePercentnumberPrice change (%)
openPricenumberOpen price
highPricenumberHigh price
lowPricenumberLow price
closePricenumberClose price
totalMatchnumberTotal matched volume
totalMatchValuenumberTotal matched value
averagePricenumberAverage price
totalBuynumberTotal buy volume
totalTradeBuynumberTotal buy value
totalSellnumberTotal sell volume
totalTradeSellnumberTotal sell value
totalForeignBuynumberForeign buy volume
totalForeignBuyValuenumberForeign buy value
totalForeignSellnumberForeign sell volume
totalForeignSellValuenumberForeign sell value
remainForeignRoomnumberRemaining foreign room
totalForeignRoomnumberTotal foreign room
totalDealnumberTotal deal volume
totalDealValuenumberTotal deal value
openInterestnumberOpen interest (OI)
settlementPricenumberSettlement price
ceiling / floor / refPricenumber?Ceiling / floor / reference price. securitiesSummary does not send these, so they are always undefined: use getMasterData() (see MasterData)

MasterData

Ceiling, floor and reference price of a symbol, from getMasterData() (see API Services, section 3.6).

FieldTypeDescription
boardBoard | string?Board
symbolstringSecurity symbol
tradingDatestringTrading date
ceilingnumberCeiling price
floornumberFloor price
refPricenumberReference price

CorporateAction

One corporate action (dividend, bonus shares, rights issue, ...) of a security, from getCorporateActions() and getCorporateActionsHistorical() (see API Services, section 3.7). Every field is the string the server sends: dates stay YYYY/MM/DD text and ratio is not parsed, because its meaning depends on the event type. A field the server leaves blank (for example a newly announced event with no ex-right date or ratio yet) is "".

FieldTypeDescription
symbolstringSecurity symbol
eventTitlestringEvent title
exrightDatestringEx-right date
recordDatestringRecord date
issueDatestringIssue date
exchangestringExchange code, e.g. "HOSE"
ratiostringEvent ratio as text, e.g. "0.9388"

Portfolio

EquityAccountBalance

FieldTypeDescription
accountNostringAccount number
accountBalancenumberAccount balance
totalDebtnumberTotal debt
interestLoannumberLoan interest
overdueFeeLoannumberOverdue fee
withdrawablenumberWithdrawable amount
onHoldCashnumberOn-hold cash
sellUnmatchednumberSell unmatched
sellT0numberSell T+0
sellT1numberSell T+1
sellT2numberSell T+2
buyUnmatchednumberBuy unmatched
buyT0numberBuy T+0
buyT1numberBuy T+1
buyT2numberBuy T+2
advanceCashT0numberAdvance cash T+0
advanceCashT1numberAdvance cash T+1
holdSubscriptionnumberHold subscription
dividendnumberDividend

DerivativeAccountBalance

FieldTypeDescription
accountNostringAccount number
accountBalancenumberAccount balance
feenumberFee
commissionnumberCommission
interestnumberInterest
extInterestnumberExtended interest
loannumberLoan
deliveryAmountnumberDelivery amount
floatingPlnumberUnrealized P/L
tradingPlnumberTrading P/L
totalPlnumberTotal P/L
withdrawablenumberWithdrawable
cashSsinumberCash at SSI
validNonCashSsinumberValid non-cash at SSI
withdrawableSsinumberWithdrawable at SSI
cashVsdcnumberCash at VSDC
validNonCashVsdcnumberValid non-cash at VSDC
withdrawableVsdcnumberWithdrawable at VSDC

cashWithdrawableSsi and cashWithdrawableVsdc can still be read but are deprecated: use withdrawableSsi and withdrawableVsdc.

EquityPosition

FieldTypeDescription
accountNostringAccount number
symbolstringSecurity symbol
quantitynumberTotal quantity
sellableQuantitynumberSellable quantity
costPricenumberCost price
buyingQuantitynumberBuying quantity
sellingQuantitynumberSelling quantity
mortgageQuantitynumberMortgage quantity
blockQuantitynumberBlocked quantity
dividendQuantitynumberDividend quantity
boughtQuantitynumberBought quantity
soldQuantitynumberSold quantity
t1SellQuantitynumberT+1 sell quantity
t2SellQuantitynumberT+2 sell quantity
t1BuyQuantitynumberT+1 buy quantity
t2BuyQuantitynumberT+2 buy quantity
restrictedQuantitynumberRestricted quantity

DerivativePosition

FieldTypeDescription
accountNostringAccount number
symbolstringContract symbol
long / short / netnumberLong / Short / Net position (net may be negative)
bidAvgPrice / askAvgPricenumberAvg bid / ask price
floatingPl / tradingPlnumberP/L
tradePricenumberTrade price

AllDerivativePosition

Derivative positions of one account, split into open and closed. It lives in Position.derivative; Position.equity is an EquityPosition[]. Both are undefined when the account has no such section (see how the positions methods return undefined in API Services).

FieldTypeDescription
openPositionsDerivativePosition[]Open positions
closedPositionsDerivativePosition[]Closed positions
accountNostringAccount number

Order

FieldTypeDescription
accountNostringAccount number
clientRequestIdstringClient request ID (at most 20 characters)
orderIdstringOrder ID
symbolstringSecurity symbol
sideOrderSide | string | undefinedBuy/Sell. The raw string if the SDK does not know it
orderTypeOrderType | string | undefinedOrder type
pricenumber | OrderType | stringOrder price. A market-priced order carries a word such as "ATO"
avgPricenumberAvg fill price
quantitynumberOrder quantity
osQuantitynumber?Outstanding quantity. The REST order book does not send it, so it is undefined there
filledQuantitynumberFilled quantity
cancelQuantitynumberCancelled quantity
statusOrderStatus | string | undefinedOrder status
inputTime / modifyTimestringInput / Modify time (yyyy/MM/dd HH:mm:ss)
messagestringServer message (the reason, for a rejected order)

Trading Responses

PlaceOrderResponse

orderId, clientRequestId, status

ModifyOrderResponse

clientModifyId, orderId, clientRequestId, status

CancelOrderResponse

clientCancelId, orderId, clientRequestId, status

MaxBuySellResponse

FieldTypeDescription
accountNostringAccount number
symbolstringSecurity symbol (upper-cased)
maxBuyQuantitynumberMaximum buy quantity
maxSellQuantitynumberMaximum sell quantity
marginRatiostring?Margin ratio, kept as the string the server sent
purchasingPowernumber?Purchasing power

Derivative accounts get only the two quantities. For them marginRatio and purchasingPower are undefined, which is not the same as 0. purchasePower (a string, "" when absent) can still be read but is deprecated: use purchasingPower.

Batch Orders

Types for placeBatchOrders and cancelBatchOrders. Usage, signing, idempotency and retry are in API Services, section 5.6. For the batch size limit see Configuration, and for errors see Error Handling.

BatchPlaceOrderItem

One order of placeBatchOrders, with the same arguments as placeOrder.

FieldTypeDescription
accountNostringAccount number
symbolstringSecurity symbol
sideOrderSideBuy/Sell
quantitynumberQuantity
pricePriceLike | null?Price (number or a decimal string). May be omitted for market-priced types (ATO/ATC/MP...)
orderTypeOrderTypeOrder type
clientRequestIdstring?Idempotency key, at most 20 characters. Generated by the SDK when omitted

BatchCancelOrderItem

One order of cancelBatchOrders: accountNo plus exactly one of the two ids.

FieldTypeDescription
accountNostringAccount number
orderIdstring?Order ID to cancel
clientRequestIdstring?Client request ID of the order to cancel

BatchOrderResponse

FieldTypeDescription
batchRequestIdstringBatch id (generated by the SDK)
resultsBatchOrderResult[]One result per order, in request order. A missing or non-array value is an empty list

BatchOrderResult

FieldTypeDescription
clientRequestIdstringClient request ID of the order
orderIdstringOrder ID ("" if none)
statusOrderStatus | stringOrder status
successbooleanWhether this order was accepted
errorCodestringError code ("" if none)
errorMessagestringError message ("" if none)
clientCancelIdstringCancel id ("" if none)

Not confirmed

How the response really behaves when only some orders of a batch fail has not been confirmed from source. According to the SDK's description the server accepts or rejects the whole batch, yet the response always carries one BatchOrderResult per order. Walk results and check success, errorCode and errorMessage for each order instead of treating the whole batch as successful. The batch size limit is also not reconciled (SDK default 20, API reference states a maximum of 50): see Configuration.

Conditional Orders (FCO)

FCOPlaceResponse

Result of placing a conditional order — fcoId

FCOCancelResponse

Result of cancelling a conditional order — fcoId

FCOListResponse

List of conditional orders (paginated).

FieldTypeDescription
pageIndexnumberCurrent page
pageSizenumberPage size
itemsCountnumberTotal records
pagesCountnumberTotal pages
fcoListFCOInfo[]List of FCO orders

FCOInfo

Detailed information of a conditional order.

FieldTypeDescription
fcoIdstringFCO order ID
clientIdstringUsername / Client ID
accountNostringAccount number
quantitynumberOrder quantity
pricestringOrder price, or a word such as "MP" for market-priced orders
priceSlipnumber?Price slippage
symbolstringSecurity symbol
typeFCOType?Conditional order type
orderTypeOrderType | string?Order type placed when the condition triggers
fromDatestringEffective start date
toDatestringEffective end date
matchedQuantitynumberMatched quantity
isPlaceOrderbooleanWhether the order has been placed into the order book
statusFCOStatus?FCO order status
detailstringStatus detail
paramsFCOParams?Trigger parameters of the FCO order

FCOParams

Trigger parameters of a conditional order.

FieldTypeDescription
stopPricenumber?Stop / trigger price
sideOrderSide?Order side (Buy/Sell)
activePricenumber?Trigger price (Trailing Stop)
trailingAmountnumber?Trailing amount
tpActivePricenumber?Take Profit trigger price
slActivePricenumber?Stop Loss trigger price
tpPricestring?Take profit price
slPricestring?Stop loss price
tpSlipnumber?Take profit slippage
slSlipnumber?Stop loss slippage
operatorFCOOperator?Trigger comparison operator

FCOOrderBookResponse

Execution log of an FCO order (paginated).

FieldTypeDescription
pageIndexnumberCurrent page
pageSizenumberPage size
itemsCountnumberTotal records
pagesCountnumberTotal pages
orderBookFCOOrder[]List of FCO order book entries

FCOOrder

A trade / execution entry of an FCO order.

FieldTypeDescription
fcoIdstringParent FCO order ID
accountNostringAccount number
quantitynumberQuantity
pricestringOrder price
symbolstringSecurity symbol
sideOrderSide?Order side
orderTypeOrderType?Child order type
isMainOrderbooleanIs the main order
isAttachedOrderbooleanIs an attached order
createdTime / updatedTimestringCreated / updated time
uniqueIdstringUnique ID
orderIdstringExchange order ID
matchedQuantitynumberMatched quantity
osQuantitynumberOutstanding quantity
avgPricenumberAverage matched price
statusOrderStatus?Child order status
detailstringDetail

FCOStatusHistoryItem

One status transition of an FCO order, returned by getFcoStatusHistory(fcoId) (see API Services, section 5.5). An empty list when the server returns 204.

FieldTypeDescription
statestringState
timestringWhen the transition happened
codestring?Code (if the server sent one)
detailstringDetail

Streaming Messages

DataMessage

Market data received via the onData callback. DataMessage is a union of the types below (a frame whose topic the SDK has no model for arrives as a raw object):

  • TradeMessage — trades of one symbol (type: 'trade')
  • IndexTickMessage — tick of the index itself (see below)
  • IntervalMessage — 1-minute / 5-minute candle (see below)
  • QuoteMessage — bid/ask (type: 'quote')
  • ForeignRoomMessage — foreign room (type: 'room')
  • MarketFlagMessage — market session flag (ATO, LO, ATC...), topic market.flag
  • IndexSummaryMessage — index summary (see below)
  • MarketDataMessage — ceiling / floor / reference price of one symbol, topic market.<symbol>
  • MarketStatusMessage — market status (market, status, tradingDate)
  • PutMessage — put-through (type: 'put')
  • OddLotMessage — odd lot (type: 'oddlot')

TradingMessage

Trading events received via the onTrading callback. TradingMessage is a union of:

  • OrderStatusMessage — regular order status updates (type: 'orderEvent')
  • OrderMatchMessage — order match events (type: 'orderMatchEvent')
  • PortfolioMessage — portfolio changes, derivative accounts only (type: 'clientPortfolioEvent')
  • FCOOrderUpdateMessage — conditional (FCO) order status updates (eventType: 'fcoEvent')

An unknown event type arrives as a raw object.

FCOOrderUpdateMessage

Conditional (FCO) order status update (streaming, received via onTrading). This message does not carry type: 'fcoOrderEvent': recognise it by eventType (for example "fcoEvent") or by fcoId.

FieldTypeDescription
fcoIdstringFCO order ID
processStatusFCOStatus?FCO processing status (INIT, WAIT, WC, TER, ...)
matchedQuantitynumberMatched quantity
isPlaceOrderbooleanWhether the order has been placed into the order book
symbolstringSecurity symbol
quantitynumberOrder quantity
pricestringOrder price
accountNostringAccount number
updatedTimestringUpdate time
statusstringStatus code
messagestringDetail message / trigger or disconnect reason
usernamestringUsername that placed the order
eventTypestringEvent type (e.g. "fcoEvent")
typeFCOType | string?Conditional order type (GTD, STOP, ...)

HeartbeatMessage

method, channel, status, message

ConnectionEvent

Connection event passed to the Stream onConnection handler (see API Services, section 6.8). Import from the main package.

FieldTypeDescription
state'connected' | 'reconnected' | 'disconnected' | 'failed'Connection state
reconnectCountnumberHow many times it has reconnected
errorError?The accompanying error, if any

Real-time Index Data

Types for the index topics (trade.index.<code> and indexsummary.<code>). How to subscribe, and the rules for index codes and intervals, are in API Services, section 6.7. These types arrive through onData (IndexSummaryMessage can also be received through onIndexSummary).

IndexTickMessage

Tick of the index itself (not its constituent stocks), from subscribeIndexTrade.

Field meanings are not confirmed

The server sends abbreviations only. The SDK field names follow the abbreviations, but the meaning was inferred from the abbreviation and has not been confirmed on a real frame. If you need certainty, check against raw (the original data object) before using a field in critical logic.

FieldTypeSource keyDescription (inferred from the abbreviation)
typeDataTypeMessage type ('trade')
symbolstringsIndex code, for example "VN30"
boardstringbBoard
statusstringssStatus
tradingTimestringtTrading time
valuenumber?vIndex value
changenumber?cChange
changePercentnumber?crChange (%)
advancesnumber?advAdvancing stocks
declinesnumber?decDeclining stocks
noChangenumber?ncUnchanged stocks
ceilingsnumber?ceCeiling stocks
floorsnumber?flFloor stocks
totalMatchValuenumber?tmvTotal matched value
totalMatchQuantitynumber?tmqTotal matched volume
totalPutValuenumber?tvpTotal put-through value
totalPutQuantitynumber?tqpTotal put-through volume
totalQuantitynumber?tqTotal volume
totalValuenumber?tvTotal value
rawRecord<string, unknown>The frame's data object, untouched

A numeric field is undefined (not 0) when the server does not send it. Among the DataMessage types only IndexTickMessage has a raw field, so 'raw' in msg is a simple way to recognise it (see the example in section 6.7).

IntervalMessage

1-minute / 5-minute candle, received when you subscribe with an interval of 1m or 5m.

FieldTypeSource keyDescription
typeDataTypeMessage type ('trade')
intervalTimestringstStart time of the candle
tradingTimestringtTrading time
symbolstringsSecurity symbol or index code
opennumberoOpen price
highnumberhHigh price
lownumberlLow price
closenumbercClose price
volumenumbervVolume

IndexSummaryMessage

Summary of one index, from indexsummary.<code>.

FieldTypeDescription
indexstringIndex code taken from the topic, upper-case ("" if unknown)
dataRecord<string, unknown>The payload the server sent, untouched

The public API documentation does not list the fields of this payload, so the SDK guesses none and has no typed fields. Read values with indexSummaryGet(message, keys, defaultValue?): it returns the value of the first key in keys that is present in message.data, or defaultValue if none is.

import { indexSummaryGet } from '@ssi.developer/ssi-sdk';

s.onIndexSummary = (msg) => {
  // 'someField' is an example: replace it with a key you see in msg.data
  const value = indexSummaryGet<number>(msg, ['someField'], 0);
  console.log(`${msg.index}: ${value}`);
};

Trading WebSocket

The types below are imported from the main package @ssi.developer/ssi-sdk. For usage see API Services, section 7.

TradingWSResponse

Result of each command sent over the Trading WebSocket.

FieldTypeDescription
idstringRequest id
methodstringCommand name
statusnumberResponse status (defaults to 200 when the frame has none)
resultunknownThe result body, as the server sent it
rateLimitRecord<string, unknown>Rate limit info the server sent along ({} if none)
receivedTimenumber?When the server received it, if the frame carries it

An error frame does not return a TradingWSResponse; it throws TradingWSError (see Error Handling).

FcoParamsKind, FcoListOptions, OrderBookQuery

Parameter types of the FCO and order book commands on the Trading WebSocket.

TypeDescription
FcoParamsKindA union with a kind that selects the FCO type: 'gtd', 'stop', 'trailingStop', 'oco', 'bullBear', with the matching params
FcoListOptionsFCO list filter, all fields optional: fcoId, type, processStatus, symbol, side, fromDate, toDate, pageIndex, pageSize
OrderBookQueryOrder book filter, all fields optional: fromDate, toDate, symbol, orderStatus, pageIndex, pageSize

On this page