WebSocket API

ping_pong

Clients may send method: "ping_pong" (or "ping_only") at any time to check the connection is alive; the server acks immediately on channel HEARTBEAT. This message requires no signature and carries no id.

Client sends ping:

{ "method": "ping_pong" }

Server replies pong:

{ "method": "ping_pong", "channel": "HEARTBEAT", "status": "ok", "message": "pong" }

The server also periodically broadcasts a heartbeat message (every 30 seconds) to every open connection — clients aren't required to send their own ping, but doing so is still recommended to detect a half-open connection early.

Response Body

application/json

Sample Request

wscat -c wss://api.ssi.com.vn/ws/v3/trading -x '{
  "method": "ping_pong"
}'

Sample Response

{
  "method": "ping_pong",
  "channel": "HEARTBEAT",
  "status": "ok",
  "message": "pong"
}

Connect WebSocket APIWS

Establish a WebSocket connection via an HTTP Upgrade request to `/ws/v3/trading`. The server returns `HTTP 101 Switching Protocols` when the connection succeeds. **Authentication:** pass the JWT access token one of two ways (checked in this order): - Query string: `wss://.../ws/v3/trading?token=<jwt>` - Header: `Authorization: Bearer <jwt>` The token must be valid (not expired, not revoked) and the API Key must be granted the `tradingws:*:*` scope — the `trading:*:*` scope used by the REST Trading API **does not work** for this WS connection; it must be granted separately. **Connection limits:** at most 10 concurrent connections per API Key; exceeding the limit is rejected with reason `Connection limit exceeded`. **⚠️ Client implementation note:** except when the request is not a valid WebSocket upgrade (a real HTTP `400` returned before connecting), every other rejection reason (401/403/429) happens AFTER the connection has already succeeded (HTTP 101) — the server accepts the connection first, sends a message describing the reason, then closes it. Reason: most WebSocket client libraries cannot reliably surface the HTTP status code of the connection step. Clients **should read the first message** after connecting to know whether the connection is actually ready to send commands. **Sample rejection message:** ```json { "code": 401, "msg": "Invalid or expired token" } ``` Possible rejection reasons: `401` missing/invalid/expired/revoked token, `403` missing `tradingws:*:*` scope, `429` concurrent-connection limit exceeded, `500` system error.

order.placeWS

Place a new order. The system **responds immediately** (`orderStatus: "PD"`) to confirm the order was accepted — the real fill status arrives later via the `order.{accountNo}` notification channel (see "Place/amend/cancel orders: fast acknowledgment, result arrives later" at the top of this document). Requires a `signature` (RSA+SHA256) per UBCKNN's data-integrity regulation for trading operations. Required scope: `tradingws:order:post`.