K-line WS push
Connection URL:
wss://stream.valuescan.ai/stream/ws/openapi/kline
1. Overview
K-line WS push delivers real-time second-level K-line data for subscribed tokens. After the client establishes a WebSocket connection and completes subscription, it receives K-line messages for subscribed tokens.
Key features:
- Real-time push: Pushes current K-line changes, not only closed candles.
- Second-level data: Currently pushes only
bucketType=1ssecond-level K-lines. - Per-connection subscription: Each WS connection maintains its own subscription list.
- Reconnect on disconnect: Clients must reconnect and resubscribe after disconnection.
Note: Push content reflects live market changes; not every token receives a message every second. For 1m, 5m, 1h, and other periods, aggregate from the received second-level data on the client.
2. Connection URL
GET wss://stream.valuescan.ai/stream/ws/openapi/kline3. Authentication
K-line WS authenticates at connection time. Parameters are passed in the Query String.
| Parameter | Type | Required | Description |
|---|---|---|---|
apiKey | string | Yes | ValueScan Access Key |
sign | string | Yes | HMAC-SHA256 signature |
timestamp | long | Yes | Millisecond Unix timestamp |
nonce | string | Yes | Random string (replay protection) |
Signature algorithm:
sign = HMAC-SHA256(SK, timestampMs + nonce)Example:
import hashlib
import hmac
import time
import uuid
AK = "your-access-key"
SK = "your-secret-key"
timestamp = str(int(time.time() * 1000))
nonce = uuid.uuid4().hex
sign = hmac.new(
SK.encode(),
(timestamp + nonce).encode(),
hashlib.sha256,
).hexdigest()4. Credits consumption
- Billing: Per user; 100 credits every 30 minutes while the WS connection is active.
- Insufficient credits: The connection receives a standard error message and disconnects.
Within a successfully billed 30-minute period, the connection remains usable; if credits are insufficient at the next billing cycle, the connection closes.
5. Connection and message format
1. Connection success
After the connection is established and authenticated:
{
"type": "connected",
"payload": {
"requestId": "7b8a0b7f9f4a4f2c91f9e1e48c36d5b2"
}
}2. Subscribe
Client sends:
{
"type": "subscribe",
"payload": {
"items": [
{
"vsTokenId": 1
}
]
}
}Subscription confirmation:
{
"type": "subscribed",
"payload": {
"items": [
{
"vsTokenId": 1
}
]
}
}3. Unsubscribe
Unsubscribe specific tokens:
{
"type": "unsubscribe",
"payload": {
"items": [
{
"vsTokenId": 1
}
]
}
}Unsubscribe all on the current connection:
{
"type": "unsubscribe",
"payload": {}
}Unsubscribe confirmation:
{
"type": "unsubscribed",
"payload": {
"items": []
}
}4. K-line push
K-line message:
{
"type": "data",
"payload": {
"vsTokenId": 1,
"bucketType": "1s",
"tradePair": "BTCUSDT",
"klineType": "01",
"time": 1781686187000,
"open": 64873.11,
"close": 64877.29,
"high": 64877.3,
"low": 64873.11,
"volume": 0.27783,
"value": 18023.8032114,
"uniqueId": "01:BTCUSDT:1781686187000:1s"
}
}Payload fields:
| Field | Type | Description |
|---|---|---|
vsTokenId | long | Token ID |
bucketType | string | K-line time window; fixed to 1s |
tradePair | string | Default USDT trading pair |
klineType | string | K-line source type; see KlineType enum |
time | long | K-line time (millisecond timestamp) |
open | number | Open price |
close | number | Close price |
high | number | High price |
low | number | Low price |
volume | number | Volume |
value | number | Turnover |
uniqueId | string | Unique push ID for client deduplication |
6. Subscription limits
| Limit | Max | Description |
|---|---|---|
| K-line WS connections per user | 50 | Exceeding returns rate-limit error |
| Tokens per WS connection | 200 vsTokenId | Duplicate vsTokenId counted once |
Split subscriptions across connections when approaching 200 tokens per connection.
7. Error messages
Business errors after WS connection use unified JSON:
{
"type": "error",
"payload": {
"code": 40001,
"message": "Required parameter is missing",
"requestId": "a7d7ce3053e140dca91d93df173648f8"
}
}Common error codes:
| code | Description |
|---|---|
20001 | API Key missing |
20012 | Timestamp expired |
20021 | Signature verification failed |
40001 | Required parameter missing, e.g. subscription item missing vsTokenId |
40002 | Invalid parameter format or value |
60001 | Rate limited, e.g. connection or subscription count exceeded |
70001 | Insufficient OpenApi credits |
Authentication errors at connection time return HTTP 200 with business JSON; code in the body indicates the actual error.
8. Integration example
Python
Dependencies:
pip install websocket-clientExample:
import hashlib
import hmac
import json
import time
import uuid
import urllib.parse
import websocket
AK = "your-access-key"
SK = "your-secret-key"
VS_TOKEN_ID = 1
timestamp = str(int(time.time() * 1000))
nonce = uuid.uuid4().hex
sign = hmac.new(
SK.encode(),
(timestamp + nonce).encode(),
hashlib.sha256,
).hexdigest()
params = urllib.parse.urlencode({
"apiKey": AK,
"sign": sign,
"timestamp": timestamp,
"nonce": nonce,
})
url = f"wss://stream.valuescan.ai/stream/ws/openapi/kline?{params}"
ws = websocket.create_connection(url, timeout=10)
try:
connected = json.loads(ws.recv())
print("connected:", connected)
ws.send(json.dumps({
"type": "subscribe",
"payload": {
"items": [
{"vsTokenId": VS_TOKEN_ID}
]
}
}))
while True:
message = json.loads(ws.recv())
msg_type = message.get("type")
if msg_type == "subscribed":
print("subscribed:", message)
elif msg_type == "data":
kline = message["payload"]
print(
f"[{kline['tradePair']}] "
f"time={kline['time']} close={kline['close']} volume={kline['volume']}"
)
elif msg_type == "error":
print("error:", message)
break
finally:
ws.close()9. Reconnection recommendations
K-line WS connections may drop due to network issues, maintenance, or insufficient credits. Recommended client behavior:
- Listen for connection close events.
- Reconnect with exponential backoff; avoid high-frequency retries.
- Regenerate
timestamp,nonce, andsignon reconnect. - Resend subscription messages to restore the subscription list.
- Use
uniqueIdfor idempotent deduplication of processed K-line messages.
Example backoff intervals: 1s, 2s, 4s, 8s, max 60s.