# Introduction

### 1. Introduction
While there is a strict access frequency control for REST API, we highly recommend that API users utilize Websocket to get the real-time data.
::: tip
The recommended way is to just create a Websocket connection and subscribe to multiple channels.
:::

### 2. Apply Connect Token
Before creating a Websocket connection, you need to get the websocket base URL and apply for a Token。

:::tip[Note]
The token is valid for only 24 hours, and a single connection is expected to be disconnected after 24 hours.
:::

It should be noted that:

- if you subscribe to spot/margin data, you need to obtain tokens through the spot base URL:
[Get Public Token - Spot/Margin](https://www.kucoin.com/docs-new/websocket-api/base-info/get-public-token-spot-margin.md)
[Get Private Token - Spot/Margin](https://www.kucoin.com/docs-new/websocket-api/base-info/get-private-token-spot-margin.md)

- if you subscribe to futures data, you need to obtain tokens through the futures base URL, which cannot be mixed:
[Get Public Token - Futures](https://www.kucoin.com/docs-new/websocket-api/base-info/get-public-token-futures.md)
[Get Private Token - Futures](https://www.kucoin.com/docs-new/websocket-api/base-info/get-private-token-futures.md)

### 3. Create connection

```javascript
var socket = new WebSocket(
  'wss://ws-api-xxx.kucoin.xxx?token=xxx&connectId=xxxxx',
);
```

Once the connection has been successfully established, the system will send a welcome message.

::: tip
The connection will only be available once the welcome message has been received
:::

```json
{
  "id": "hQvf8jkno",
  "type": "welcome"
}
```

**connectId**: The connection ID is a unique value taken from the client side. The welcome message ID and the error message ID are both connectId.

If you only want to receive private messages of the specified topic, please set privateChannel to true when subscribing.

### 4. Heartbeat

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

**WebSocket Heartbeat Mechanism**

The WebSocket heartbeat mechanism is determined by two parameters returned from the following RESTful token-generation endpoints:

- Get Public Token – Classic Spot/Margin
- Get Private Token – Classic Spot/Margin
- Get Public Token – Classic Futures
- Get Private Token – Classic Futures

These endpoints return the following heartbeat parameters:

- **pingInterval** — Heartbeat sending interval  
- **pingTimeout** — Heartbeat timeout threshold 

**1. Parameter Definitions**

**pingInterval**
- Indicates how often the client should send a `ping` frame.
- The recommended behavior is to send one ping every **pingInterval** seconds.  
- Current server value: **18 seconds**.

**pingTimeout**
- Indicates the maximum time the client should wait for a `pong` after sending a `ping`.
- If no `pong` is received within this timeout, the connection should be treated as disconnected.
- Current server value: **10 seconds**.

**2. Behavior Notes**

**2.1 Session Close Logic**
The WebSocket cluster’s session-closure logic is **not** simply `pingInterval + pingTimeout`.  
Clients only need to ensure they send a `ping` **at least once every `pingInterval` seconds**.

No additional internal timing rules need to be considered.

**2.2 Timeout Timer Reset Rules**
The timeout countdown is based on the **most recent outgoing message**, which includes:

- `ping` frames  
- Business messages (e.g., place order, cancel order, etc.)  

Any outgoing message refreshes the timeout timer.

Network delay should also be considered; some users implement a heartbeat cycle of **9 seconds** for higher reliability.

**2.3 Per-Session Heartbeat Requirement**
Each WebSocket session must maintain its own independent heartbeat logic.  
All sessions must implement keepalive handling to prevent disconnection.

**2.4 Handling Timeout Conditions**
If the client's configured `pingInterval`:

- **> 10 seconds and < 18 seconds**
- After sending a `ping`, if no `pong` is received within **10 seconds** (`pingTimeout`),  
  the client should **immediately send another `ping`**, without waiting for the next scheduled interval.

- **< 10 seconds**
- Additional pong-response detection logic is **not required**, because the next ping will be sent before the timeout occurs.

**3. Summary**

`pingInterval` determines **how often** the client should send heartbeats.  
`pingTimeout` determines **how long to wait** for the server’s response.

A correct implementation should:

- Send heartbeats at or before `pingInterval`
- Detect server silence using `pingTimeout`
- Reset timeout on any outgoing traffic  
- Implement heartbeat independently for each WebSocket session  

This ensures stable, long-lived WebSocket connections under the Classic Spot/Margin and Classic Futures APIs.

```json
{
  "id": "1545910590801",
  "type": "pong",
  "timestamp": 1764215232226553
}
```

### 5. Subscribe

To subscribe to channel messages from a specific server, the client side should send a subscription message to the server.

#### Parameters

- **ID**: ID is a unique string to mark the request which is same as ID property of ack.
- **Topic**: The topic you want to subscribe to.
- **PrivateChannel**: You can subscribe to some private topics through the privateChannel parameter. This parameter is set to "false" by default. When set to "true", you can only receive content pushes related to the topics you subscribe to.
- **Response** If the response is set to true, the system will return ack messages after the subscription has succeeded.

```json
//Spot Demo
{
  "id": 1545910660739, //The ID should be a unique value
  "type": "subscribe",
  "topic": "/market/ticker:BTC-USDT,ETH-USDT", //Topic needs to be subscribed. Some topics support subscribing to information on multiple trading pairs by separating them with a comma (“,”).
  "privateChannel": false, //Adopted the private channel or not. Set as false by default.
  "response": true //Whether the server needs to return the receipt information of this subscription or not. Set as false by default.
}
```

```json
//Future Demo
{
  "id": 1545910660739, //The ID should be a unique value
  "type": "subscribe",
  "topic": "/market/ticker:XBTUSDM", //Subscribed topic. Some topics support subscribing to information on multiple trading pairs by separating them with a comma (“,”).
  "privateChannel": false, //Adopted the private channel or not. Set as false by default.
  "response": true //Whether the server needs to return the receipt information of this subscription or not. Set as false by default.
}
```

If the subscription succeeds, the system will send ack messages to you, when the response is set as true.

```json
{
  "id": "1545910660739",
  "type": "ack"
}
```

Whenever topic messages are generated, the system will send the corresponding messages to the client side. For details about the message format, please check the definitions of topics.



### 6. UnSubscribe

Unsubscribe from topics you have subscribed to.

#### Parameters
- **ID**: ID unique string to mark the request.
- **Topic**: The topic you want to unsubscribe from.
- **PrivateChannel**: You can unsubscribe from some private topics through the privateChannel parameter. Set to "true", you can unsubscribe from related private channel pushes.
- **Response**: If the response is set as true, the system will return the ack messages after the unsubscription succeeds.

```json
//Spot Unsubscribe Topic
{
  "id": "1545910840805", //The ID should be a unique value
  "type": "unsubscribe",
  "topic": "/market/ticker:BTC-USDT,ETH-USDT", //Topic needs to be unsubscribed. Some topics support unsubscribing from information on multiple trading pairs by separating them with a comma (“,”).
  "privateChannel": false,
  "response": true //Whether the server needs to return the receipt information of this subscription or not. Set as false by default.
}
```

```json
//Futures Unsubscribe Topic
{
  "id": "1545910840805", //The id should be an unique value
  "type": "unsubscribe",
  "topic": "/market/ticker:XBTUSDM", //Topic needs to be unsubscribed. Some topics support unsubscribing from information on multiple trading pairs by separating them with a comma (“,”).
  "privateChannel": false,
  "response": true //Whether the server needs to return the receipt information of this subscription or not. Set as false by default.
}
```

If the unsubscription succeeds, the system will send ack messages to you, when the response is set as true.

```json
{
  "id": "1545910840805",
  "type": "ack"
}
```

