> For the complete documentation index, see [llms.txt](https://docs.kryptox.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kryptox.finance/api/websocket-stream.md).

# WebSocket Stream

## WebSocket Market Data Push

### Connection

1. endpoint: wss\://stream.kryptox.finance/ws/public
2. Each connection is valid for no more than 24 hours. Please handle disconnects and reconnects properly.
3. Send a ping command within every 3 minutes to keep the connection alive. Otherwise, the server will close the connection.
4. The WebSocket server accepts at most 10 client command messages per second.
5. A single connection can subscribe to at most 1024 streams. A single subscribe command can contain at most 100 streams.

### Commands

There are currently three available `op` commands. Their formats are shown below:

1. subscribe
2. unsubscribe
3. ping

**Subscribe command:**

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "marketTicker@BTCUSDC"
  ]
}
```

**Unsubscribe command:**

```json
{
  "id": 1545910660739,
  "op": "unsubscribe",
  "args": [
    "marketTicker@BTCUSDC"
  ]
}
```

`args` uses the `stream[@queue]` format. `stream` is the channel name, and `queue` is an optional subscription parameter such as a symbol, Kline interval, or depth precision. Multiple subscription items can be placed in one `args` array. One array can contain at most 100 subscription items.**Success response:**

```json
{
  "id": "1545910660739",
  "event": "success"
}
```

**Error response:**

```json
{
  "id": "1545910660739",
  "event": "error",
  "code": 4000,
  "msg": "stream marketL2@@BTCUSDC is invalid"
}
```

**Heartbeat:** the client must send a ping within 3 minutes to keep the connection alive:

```json
{
  "id": "1545910590801",
  "op": "ping"
}
```

**Heartbeat response:**

```json
{
  "id": "1545910590801",
  "event": "pong",
  "timestamp": 1780755553813750
}
```

### Ticker

**Stream**: `marketTicker@BTCUSDC`**Subscribe:**

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "marketTicker@BTCUSDC"
  ]
}
```

**Push data:**

```json
{
  "event": "marketTicker",
  "eventType": "ticker",
  "data": {
    "symbol": "BTCUSDC",
    "sequence": 1713516609293,
    "side": "buy",
    "price": "86454.6",
    "size": "0.001",
    "tradeId": "1713516609293",
    "bestBidSize": "0.123",
    "bestBidPrice": "86454.5",
    "bestAskPrice": "86454.6",
    "bestAskSize": "0.045",
    "ts": 1740641976241000000
  }
}
```

Field notes: `sequence` matches the latest `tradeId`; `side` is the taker side of this trade; `price` / `size` / `tradeId` describe the trade that triggered this ticker update; `bestBidPrice` / `bestBidSize` / `bestAskPrice` / `bestAskSize` are the current best bid and ask; `ts` is the push time in nanoseconds.

### Order Book - Level 2 Incremental

**Stream**: `marketL2@BTCUSDC`. Pushes Level 2 incremental updates. The client is responsible for maintaining its local order book. After connecting, it is recommended to first pull a full snapshot via Order Book Depth, then apply the incremental updates from this stream. Each change is pushed as its own message. For the full merge/rebuild procedure, see Maintaining a Local Order Book.**Subscribe:**

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "marketL2@BTCUSDC"
  ]
}
```

**Push data:**

```json
{
  "event": "marketL2",
  "eventType": "l2",
  "data": {
    "symbol": "BTCUSDC",
    "sequence": 1709294490100,
    "change": "89778.6,buy,1534",
    "timestamp": 1731680249701
  }
}
```

The `change` field has the format `price,side,size`, where `side` is `buy` or `sell`. A `size` of `0` indicates that the price level has been removed. The client should discard any message whose `sequence` is less than or equal to the `sequence` of the initial snapshot.

### Order Book - 5 Levels

**Stream**: `marketL2d5@BTCUSDC`. Pushes the best 5 levels of bids and asks as a snapshot.**Subscribe:**

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "marketL2d5@BTCUSDC"
  ]
}
```

**Push data:**

```json
{
  "event": "marketL2d5",
  "eventType": "l2",
  "data": {
    "symbol": "BTCUSDC",
    "sequence": 1709294490099,
    "bids": [
      [
        "89778.6",
        1534
      ],
      [
        "89778.2",
        54
      ]
    ],
    "asks": [
      [
        "89778.7",
        854
      ],
      [
        "89779.2",
        4
      ]
    ],
    "timestamp": 1731680249700,
    "ts": 1731680249700
  }
}
```

### Order Book - 50 Levels

**Stream**: `marketL2d50@BTCUSDC_{multi}`, where `{multi}` is a multiplier. Allowed values: `1` (smallest precision), `10`, `100`, `1000`.**Subscribe:**

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "marketL2d50@BTCUSDC_1"
  ]
}
```

**Push data:**

```json
{
  "event": "marketL2d50",
  "eventType": "l2",
  "data": {
    "symbol": "BTCUSDC",
    "sequence": 1709294490099,
    "bids": [
      [
        "89778.6",
        1534
      ],
      [
        "89778.2",
        54
      ]
    ],
    "asks": [
      [
        "89778.7",
        854
      ],
      [
        "89779.2",
        4
      ]
    ],
    "timestamp": 1731680249700,
    "ts": 1731680249700
  }
}
```

### Klines / Candles

**Stream**: `marketCandles@BTCUSDC_{granularity}`. Allowed granularities: `1min`, `3min`, `5min`, `15min`, `30min`, `1hour`, `2hour`, `4hour`, `8hour`, `12hour`, `1day`, `1week`, `1month`. No message is pushed when there is no update.**Subscribe:**

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "marketCandles@BTCUSDC_1min"
  ]
}
```

**Push data:**

```json
{
  "event": "marketCandles",
  "eventType": "candle",
  "data": {
    "symbol": "BTCUSDC",
    "candles": [
      "1731898200",
      "90638.6",
      "90638.6",
      "90638.6",
      "90638.6",
      "1903413.6",
      "21"
    ],
    "time": 1731898208357
  }
}
```

Array field order: `[start time (seconds), open, close, high, low, turnover, volume]`.

### Latest Trades

**Stream**: `marketTrade@BTCUSDC`**Subscribe:**

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "marketTrade@BTCUSDC"
  ]
}
```

**Push data:**

```json
{
  "event": "marketTrade",
  "eventType": "trade",
  "data": {
    "symbol": "BTCUSDC",
    "sequence": 1794100537695,
    "side": "buy",
    "size": "0.001",
    "price": "90503.9",
    "takerOrderId": "247822202957807616",
    "makerOrderId": "247822167163555840",
    "tradeId": "1794100537695",
    "ts": 1731898619520000000
  }
}
```

### Mark Price / Index Price

**Stream**: `marketInstrument`**Subscribe:**

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "marketInstrument"
  ]
}
```

**Push data (mark price / index price):**

```json
{
  "event": "marketInstrument",
  "eventType": "fairPrice",
  "data": {
    "symbol": "BTCUSDC",
    "markPrice": 90445.02,
    "indexPrice": 90445.02,
    "granularity": 1000,
    "timestamp": 1731899129000
  }
}
```

**Push data (funding rate):**

```json
{
  "event": "marketInstrument",
  "eventType": "fundingRate",
  "data": {
    "symbol": "BTCUSDC",
    "granularity": 60000,
    "fundingRate": -0.002966,
    "timestamp": 1551770400000
  }
}
```

### 24-Hour Snapshot

**Stream**: `marketSnapshot@BTCUSDC`. Periodically pushes the rolling 24-hour trading statistics.**Subscribe:**

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "marketSnapshot@BTCUSDC"
  ]
}
```

**Push data:**

```json
{
  "event": "marketSnapshot",
  "eventType": "trade",
  "data": {
    "symbol": "BTCUSDC",
    "highPrice": "89299.9",
    "lowPrice": "82205.2",
    "lastPrice": "86262.6",
    "price24HoursBefore": "88762.5",
    "priceChg": "-2499.9",
    "priceChgPct": "-0.0281",
    "volume": "12062.039",
    "turnover": "1033552780.2532",
    "ts": "1740643185017"
  }
}
```

## Maintaining a Local Order Book

To build and keep an **accurate** order book locally, merge the full REST snapshot from Order Book Depth with the incremental updates from the Order Book - Level 2 Incremental stream (`marketL2@SYMBOL`). The two are stitched together by the same `sequence` number.

> If you only need shallow depth and do not mind full-page replacement, subscribe to Order Book - 5 Levels / Order Book - 50 Levels instead: those streams push complete snapshots, so you can simply replace your local data on each message. The merge procedure below is **not** needed. The procedure below is only for maintaining a full, arbitrary-depth book via the `l2` incremental stream.

### Build Procedure

1. **Subscribe to the incremental stream first**: after connecting to WebSocket, subscribe to `marketL2@SYMBOL` and **buffer** every incoming incremental message (together with its `sequence`). Do not discard anything yet.
2. **Then fetch the full snapshot**: call `GET /api/v1/market/order-book/depth-100` and record the baseline sequence `S0 = data.sequence`.
3. **Initialize the local book from the snapshot**: keep two tables keyed **by price** (bids and asks), with the quantity as the value. Maintain bids in **descending** price order and asks in **ascending** price order.
4. **Drop stale updates**: discard every buffered message with `sequence <= S0`. Starting from the first message with `sequence > S0`, apply messages to the book in **ascending** `sequence` order.
5. **Apply each update**: the `change` field has the format `price,side,quantity`.
   1. `side = buy` modifies the bids, `side = sell` modifies the asks;
   2. `quantity > 0`: overwrite (insert or update) the quantity at that price level;
   3. `quantity = 0`: remove that price level.
6. **Switch to live mode**: once the buffer is drained, apply rule 5 to each newly arriving update in real time.
7. **Truncate on display**: when presenting the book, slice to the desired number of levels and always keep bids descending, asks ascending.

### Correctness Checks and Rebuild

* **Order by `sequence`, not `timestamp`**: the sequence number is the authoritative ordering of the book state.
* **Use the price string / fixed-point as the key**: the price in `change` is a string. Casting it to `float` for use as a key causes level mismatches due to floating-point error. Keep the original string or use fixed-point, such as scaled integers.
* **Continuity check**: the `sequence` of incremental messages should increase monotonically and connect to the snapshot. If you ever see `sequence` go backwards, observe an obvious gap (suspected packet loss / reordering), or notice the local book diverging from the market, the local book may be corrupted. **Rebuild from step 1 by pulling a fresh snapshot** rather than patching on top of a bad state.
* During a rebuild, again buffer updates first, then fetch the snapshot, then align by `S0`, to avoid introducing a new gap during the rebuild.

## WebSocket Account Information Push

### Connection

1. endpoint wss\://stream.kryptox.finance/ws/private
2. Each connection is valid for no more than 24 hours. Please handle disconnects and reconnects properly.
3. Send a ping command within every 3 minutes to keep the connection alive. Otherwise, the server will close the connection.
4. The WebSocket server accepts at most 10 client command messages per second.
5. A single connection can subscribe to at most 1024 streams. A single subscribe command can contain at most 100 streams.

Before connecting, call REST `https://api.kryptox.finance/api/v1/ws/private` to obtain a `listenKey`. This endpoint requires `USER_DATA` authentication.

```plaintext
POST api/v1/ws/private
```

> **Response:**

```json
{
  "code": "0",
  "data": {
    "listenKey": "GoocvU8BRPeWiAzxLFOfAk6dzCLrdXS-OJIJ6s=.GMc5CA7UhxwUNbEI4ehQhQ=="
  }
}
```

Connect using the returned `listenKey`:

```plaintext
wss://stream.kryptox.finance/ws/private?listenKey=GoocvU8BRPeWiAzxLFOfAk6dzCLrdXS-OJIJ6s=.GMc5CA7UhxwUNbEI4ehQhQ==
```

1. A newly obtained `listenKey` is valid for 120 minutes. A valid, unexpired `listenKey` is required when establishing the connection.
2. Account information subscriptions use `op` and `args`, same as market data subscriptions.

### Account Balance

**Stream**: `userAssets`**Subscribe:**

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "userAssets"
  ]
}
```

**Push data:**

```json
{
  "event": "userAssets",
  "eventType": "walletBalance",
  "data": {
    "currency": "USDT",
    "walletBalance": "371.394298816",
    "availableBalance": "285.652001096",
    "holdBalance": "0",
    "equity": "387.224858816",
    "crossOrderMargin": "10.06002012",
    "crossPosMargin": "17.551016",
    "crossUnPnl": "2.95996",
    "totalCrossMargin": "310.370835226",
    "maxWithdrawAmount": "285.645841096",
    "version": "2118",
    "timestamp": "1741164936624"
  }
}
```

### Order Updates

**Subscribe:**

* `userTrades` — subscribe to order events for **all** contracts of the current user.
* `userTrades@BTCUSDC` — subscribe to order events for one specific contract.

Both streams push order-lifecycle events for the current user: placement, match, cancel, and update.

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "userTrades@BTCUSDC"
  ]
}
```

**Push data:**

* `open`: maker order has entered the book
* `match`: a match occurred, pushed to both the taker and maker side
* `filled`: order has been fully filled, pushed in addition to `match`
* `update`: adjustment to a maker order's matchable size
* `canceled`: the order has been cancelled

**Example (match):**

```json
{
  "event": "userTrades",
  "eventType": "symbolOrderChange",
  "data": {
    "orderId": "284486580251463680",
    "symbol": "BTCUSDC",
    "type": "match",
    "status": "match",
    "price": "86275.1",
    "matchPrice": "86275.1",
    "matchSize": "0.001",
    "orderType": "market",
    "side": "buy",
    "size": "0.001",
    "filledSize": "0.001",
    "remainSize": "0",
    "canceledSize": "0",
    "tradeId": "1828954878212",
    "liquidity": "taker",
    "orderTime": 1740640088244000000,
    "clientOid": "5a80bd847f1811ef8a7faa665a37b3d7",
    "ts": 1740640088427000000,
    "feeType": "takerFee",
    "tradeType": "trade"
  }
}
```

### Position Updates

**Stream**: `userPosition`**Subscribe:**

```json
{
  "id": 1545910660739,
  "op": "subscribe",
  "args": [
    "userPosition"
  ]
}
```

**Push data:**`eventType` is always `positionChange`. Each message corresponds to a single position change on a single contract.

```json
{
  "event": "userPosition",
  "eventType": "positionChange",
  "data": {
    "id": "284486580251463680",
    "symbol": "BTCUSDC",
    "openingTimestamp": 1717639498983,
    "currentTimestamp": 1717724686618,
    "currentQty": "-0.002",
    "isOpen": true,
    "currentCost": "-136.002",
    "posCost": "-136.002",
    "currentComm": "0.06739824",
    "markPrice": "70778.04",
    "markValue": "-141.55608",
    "realisedPnl": "-0.09580416",
    "unrealisedPnl": "-5.55408",
    "unrealisedPnlPcnt": "-0.0408",
    "unrealisedRoePcnt": "-1.0189",
    "avgEntryPrice": "68001",
    "settleCurrency": "USDC",
    "maintainMargin": "0.708",
    "mmr": "0.0050",
    "posInit": "5.4509819612",
    "posMargin": "5.6735903779",
    "liquidationPrice": "80700.49720065",
    "changeReason": "positionChange"
  }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.kryptox.finance/api/websocket-stream.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
