NodeJS

Client Classes

Auth, Data, Trading, Stream — initialization and usage

The SDK provides 4 specialized clients. All API methods are async and return Promise.

Auth

Root client — manages REST client, authentication, and tokens. All other clients take Auth as a parameter.

import { Auth, Config } from '@ssi.developer/ssi-sdk';

const config = new Config({
  clientId: 'YOUR_CLIENT_ID',
  apiKey: 'YOUR_API_KEY',
  apiSecret: 'YOUR_API_SECRET',
  privateKey: 'YOUR_PRIVATE_KEY',
});

const auth = new Auth(config);

const token = await auth.authenticate('YOUR_OTP');
console.log(`Token expires at (epoch seconds): ${token.expiresAt}`);

Authentication methods

// Request OTP (typed: OTPResponse { message, transactionId? })
await auth.requestOtpTyped();

// Authenticate with OTP
const token = await auth.authenticate('YOUR_OTP');

// Authenticate without OTP (market data only)
const token = await auth.authenticate();

// Refresh token
const token = await auth.refresh();

// Ensure authenticated (auto-refresh if expired)
await auth.ensureAuthenticated('YOUR_OTP');

ensureAuthenticated throws ReauthenticationRequired when the session cannot be refreshed and no OTP is given (see Error Handling). For details on each method see API Services.

Approve OTP (Smart OTP push-approval)

Accounts with Smart OTP enabled can approve directly in the app instead of entering a code. Call requestOtpTyped() to send the request and get a transactionId, then pass it to ensureAuthenticated() — the SDK polls automatically until the user approves.

// Step 1: send the approval request, get transactionId (Smart OTP only)
const otp = await auth.requestOtpTyped();

// Step 2: the SDK polls automatically until the user approves in the Smart OTP app
// (otp is undefined since we're using transactionId instead)
const token = await auth.ensureAuthenticated(undefined, otp.transactionId);

While waiting, the server returns HTTP 202 + code 401114 ("Push-approval is pending") — the SDK handles this automatically. If the poll attempts run out without approval, ensureAuthenticated rejects with an authentication error (SmartOTPPendingError or SmartOTPRejectedError, see Error Handling). You can also read the code in the Smart OTP app and pass it to authenticate('YOUR_OTP').

Token state

auth.getToken();   // get current token
auth.setToken(t);  // set token (cache)

auth.isTokenExpired;   // boolean
auth.hasRefreshToken;  // boolean
auth.canRefresh;       // is the refresh token still usable?

Data

Market data client. No OTP required — just auth.authenticate().

import { Auth, Data, Config } from '@ssi.developer/ssi-sdk';

const auth = new Auth(config);
await auth.authenticate();

const data = new Data(auth);

const ohlc = await data.marketData.getOhlc1Minute('SSI');
const indexes = await data.marketData.getIndexes();
const info = await data.marketData.getSecuritiesInfo('SSI');

Service: data.marketData (MarketDataService) — OHLC, indexes, securities.

Trading

Trading, account, and portfolio client. OTP required.

import { Auth, Trading, Config, OrderSide } from '@ssi.developer/ssi-sdk';

const auth = new Auth(config);
await auth.authenticate('YOUR_OTP');

const trading = new Trading(auth);

// Account
const accounts = await trading.account.getAccountInfo();

// Portfolio
const balance = await trading.portfolio.getEquityBalance('YOUR_ACCOUNT_NO');
const positions = await trading.portfolio.getEquityPositions('YOUR_ACCOUNT_NO');
const orders = await trading.portfolio.getTodayOrders('YOUR_ACCOUNT_NO');

// Trading
const result = await trading.trading.placeLimitOrder(
  'YOUR_ACCOUNT_NO', 'SSI', OrderSide.BUY, 100, 66000,
);

Services:

  • trading.account (AccountService) — account info.
  • trading.portfolio (PortfolioService) — balance, positions, order book, PPMMR.
  • trading.trading (TradingService) — place/modify/cancel orders, place/cancel batches of orders, buying power, conditional orders (FCO).

To place or cancel several orders in one signed request, see Batch Orders. Batches need Config.privateKey, and the per-batch order limit is Config.maxBatchOrders (see Configuration).

Trading WebSocket

The Trading WebSocket is exported from the main package @ssi.developer/ssi-sdk. The factory asyncTradingWs(auth, options?) (alias tradingWs) is not a method of Auth/Data/Trading/Stream: Trading and Stream never connect to it on their own, you have to call it explicitly. It takes an Auth that is already authenticated with an OTP and returns a TradingWSService. For details, examples and caveats see API Services, section 7.

import { Auth, asyncTradingWs } from '@ssi.developer/ssi-sdk';

const ws = await asyncTradingWs(auth);
// ... use ws ...
await ws.close();

Stream

Realtime streaming client via WebSocket. OTP required.

import { Auth, Stream, Config } from '@ssi.developer/ssi-sdk';

const auth = new Auth(config);
await auth.authenticate('YOUR_OTP');

const stream = new Stream(auth);

// Register callbacks
stream.streaming.onData = (msg) => {
  console.log('[DATA]', msg);
};

stream.streaming.onTrading = (msg) => {
  console.log('[TRADING]', msg);
};

stream.streaming.onHeartbeat = (msg) => {
  console.log('[HEARTBEAT]', msg);
};

// Connect and subscribe
await stream.streaming.connect();

await stream.streaming.subscribeSymbol(['SSI', 'HPG']);
await stream.streaming.subscribeOrderStatus();

await stream.streaming.wait();

Service: stream.streaming (StreamingService) — subscribe/unsubscribe realtime data. Every subscribe/unsubscribe method returns Promise<void>: always use await.

Callbacks:

PropertyTypeDescription
onData(msg: DataMessage) => voidReceives market data
onTrading(msg: TradingMessage) => voidReceives trading events (regular order status, FCO conditional orders, portfolio)
onHeartbeat(msg: HeartbeatMessage) => voidReceives heartbeat
onMarketFlag(msg: MarketFlagMessage) => voidMarket session flag (needs subscribeMarketFlag())
onIndexSummary(msg: IndexSummaryMessage) => voidIndex summary (subscribeIndexSummary)
onOrder, onOrderMatch, onPortfoliotyped callbacksOrder, fill and portfolio events
onConnection(event: ConnectionEvent) => voidConnection state: connected, reconnected, disconnected, failed

Setting a callback subscribes to nothing. With Config.autoReconnect on (the default) the SDK reconnects and re-subscribes by itself, see API Services, section 6.8. Data of the index itself (ticks, 1m/5m candles, summaries) is in section 6.7.

Token update:

// Update the stream token after a refresh (pass the new access token)
stream.updateToken(auth.accessToken);

Full Example

import { Auth, Data, Trading, Stream, Config, OrderSide } from '@ssi.developer/ssi-sdk';

const config = new Config({
  clientId: 'YOUR_CLIENT_ID',
  apiKey: 'YOUR_API_KEY',
  apiSecret: 'YOUR_API_SECRET',
  privateKey: 'YOUR_PRIVATE_KEY',
});

const auth = new Auth(config);
await auth.authenticate('YOUR_OTP');

// Market data
const data = new Data(auth);
const ohlc = await data.marketData.getOhlc1Minute('SSI');
console.log(ohlc);

// Trading
const trading = new Trading(auth);
const accounts = await trading.account.getAccountInfo();
console.log(accounts);

// Streaming
const stream = new Stream(auth);

stream.streaming.onData = (msg) => {
  console.log('[DATA]', msg);
};

stream.streaming.onTrading = (msg) => {
  console.log('[TRADING]', msg);
};

await stream.streaming.connect();

await stream.streaming.subscribeSymbol(['SSI', 'HPG']);
await stream.streaming.subscribeOrderStatus();

await stream.streaming.wait();

await stream.disconnect();

Notes

  • All API methods are async — use await or .then().
  • All clients share the HTTP connection via Auth.
  • Call await stream.disconnect() to clean up WebSocket resources.
  • Common errors: AuthenticationError (auth, including SmartOTPPendingError, SmartOTPRejectedError, ReauthenticationRequired), WebSocketError (stream and Trading WebSocket), APIError (HTTP errors), RateLimitError, ValidationError, ConfigurationError. AuthenticationError does not extend APIError, see Error Handling.

On this page