> ## Documentation Index
> Fetch the complete documentation index at: https://docs.solanatracker.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 连接 Solana Tracker Datastream WebSocket

> 使用 API 密钥连接 Datastream，订阅房间，并处理 JSON 心跳和认证错误。

建立连接后，加入应用需要的房间。所有订阅使用相同的认证、加入和离开消息，以及 JSON 心跳协议。

<Info>
  **URL:** `wss://datastream.solanatracker.io/{apiKey}`\
  Use your Data API key in the path. Available on Premium, Business, and Enterprise plans.
</Info>

## Connection URL

Always connect to the canonical Datastream host:

```text theme={null}
wss://datastream.solanatracker.io/{apiKey}
```

Datastream authentication uses the API key in the WebSocket path. REST base URLs are separate from the Datastream host.

## Authentication failures

An invalid or missing API key may still complete the WebSocket handshake, then close almost immediately with:

* no JSON error payload
* no `joined` acknowledgment

If the connection closes immediately without a room acknowledgment, check the API key and URL before retrying.

## Join and leave

```javascript theme={null}
const ws = new WebSocket("wss://datastream.solanatracker.io/YOUR_API_KEY");

ws.onopen = () => {
  ws.send(JSON.stringify({ type: "join", room: "price-by-token:TOKEN_MINT" }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  if (msg.type === "joined") {
    console.log("Subscribed", msg.room);
  }

  if (msg.type === "message") {
    // Room payload in msg.data
  }

  // Application heartbeat (not WebSocket protocol ping/pong)
  if (msg.type === "ping") {
    ws.send(JSON.stringify({ type: "pong" }));
  }
};

// Call after joining when the app no longer needs this subscription.
// There is no separate `left` acknowledgment.
function unsubscribe() {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ type: "leave", room: "price-by-token:TOKEN_MINT" }));
  }
}
```

| Envelope | Direction | Meaning |
| - | - | - |
| `{ "type": "join", "room" }` | Client → server | Subscribe |
| `{ "type": "joined", "room" }` | Server → client | Subscribe confirmed |
| `{ "type": "leave", "room" }` | Client → server | Unsubscribe (no `left` ack) |
| `{ "type": "message", "room", "data" }` | Server → client | Room data |
| `{ "type": "ping" }` | Server → client | App heartbeat |
| `{ "type": "pong" }` | Client → server | Heartbeat reply |

## Heartbeat (JSON ping/pong)

The server may emit a JSON control frame:

```json theme={null}
{ "type": "ping" }
```

Reply with:

```json theme={null}
{ "type": "pong" }
```

Reply to JSON heartbeats in your message handler. They are application messages, separate from WebSocket protocol ping/pong frames.

## Wallet balance amounts

On `wallet:{wallet}:balance` and `wallet:{wallet}:{token}:balance`:

* `amount` is a **UI decimal** (human units), not raw integer base units / lamports
* native SOL uses mint `So11111111111111111111111111111111111111112`

```json theme={null}
{
  "type": "message",
  "room": "wallet:WALLET:balance",
  "data": {
    "wallet": "WALLET",
    "token": "So11111111111111111111111111111111111111112",
    "amount": 1.2345
  }
}
```

## Limits and quotas

Premium+ Datastream includes **unlimited messages** (no per-message fees). There is **no limit** on concurrent WebSocket connections or rooms per connection.

REST monthly request quotas do **not** disconnect an established Datastream session when exhausted.

## Next

<CardGroup cols={2}>
  <Card title="实时价格" href="/cn/guides/datastream-prices">
    Price and candle rooms.
  </Card>

  <Card title="代币发行" href="/cn/guides/datastream-tokens">
    Launches, graduations, and market events.
  </Card>

  <Card title="实时风险信号" href="/cn/guides/datastream-safety">
    Snipers, bundlers, and holder signals.
  </Card>

  <Card title="实时盈亏" href="/cn/guides/datastream-pnl">
    Live wallet and position PnL.
  </Card>
</CardGroup>
