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

# WebSocket API

Real-time updates for prices, order books, and your account, over a Socket.IO connection.

## Connecting

```
wss://predict.pretoke.xyz/ws
```

{% hint style="info" %}
The WebSocket runs on the **same host and port** as the REST API — the path is `/ws`. Transports: `websocket` (preferred) and `polling` (fallback). CORS is open at the transport level; private data authorization happens at the subscription level (see User channel below).
{% endhint %}

{% hint style="warning" %}
The server disconnects idle clients that don't send a `ping` within **10 seconds**. Send `ping` events periodically (every 5 seconds is recommended).
{% endhint %}

***

## Client → Server events

### `ping`

Keep-alive. Send periodically to stay connected.

```json
// emit "ping" with no payload
```

Server replies: `{ "type": "pong" }`

***

### `subscribe`

Subscribe to one of three channels:

{% tabs %}
{% tab title="Market channel" %}
General price/volume updates for one or more markets:

```json
{ "channel": "market", "marketIds": ["mkt_1", "mkt_2"] }
```

Server confirms:

```json
{ "type": "subscribed", "channel": "market", "marketIds": ["mkt_1", "mkt_2"] }
```

{% endtab %}

{% tab title="Book channel" %}
Detailed order book updates for a single market. You immediately receive a full snapshot before incremental updates start:

```json
{ "channel": "book", "marketId": "mkt_1" }
```

Server sends snapshot first:

```json
{ "type": "snapshot", "channel": "book", "data": { "bids": [...], "asks": [...] } }
```

Then confirms:

```json
{ "type": "subscribed", "channel": "book", "marketId": "mkt_1" }
```

{% endtab %}

{% tab title="User channel" %}
Private balance/position updates for your account. **Requires your JWT access token:**

```json
{ "channel": "user", "token": "eyJhbGciOi..." }
```

Server confirms (or sends error if token is invalid):

```json
{ "type": "subscribed", "channel": "user", "userId": "usr_01hz..." }
```

{% endtab %}
{% endtabs %}

***

### `unsubscribe`

Same shape as `subscribe`, to leave a channel:

```json
{ "channel": "market", "marketIds": ["mkt_1"] }
{ "channel": "book", "marketId": "mkt_1" }
{ "channel": "user" }
```

***

## Server → Client events

All server pushes arrive as a single `message` event with a `type` discriminator.

### Market update

```json
{ "type": "update", "channel": "market", "data": { "marketId": "mkt_1", "buyYesPrice": "0.64", "buyNoPrice": "0.38" } }
```

### Book snapshot + updates

```json
{ "type": "snapshot", "channel": "book", "data": { "bids": [...], "asks": [...] } }
{ "type": "update", "channel": "book", "data": { "marketId": "mkt_1", "bids": [...], "asks": [...] } }
```

A `snapshot` is sent once immediately after subscribing. Subsequent messages are incremental `update`s.

### User update

```json
{ "type": "update", "channel": "user", "data": { "balance": { "available": "1300000000" } } }
```

Payload shape varies depending on what changed (balance, positions, order status).

### Pong

```json
{ "type": "pong" }
```

### Error

```json
{ "type": "error", "message": "Authentication required" }
```

***

## Full connection example

{% tabs %}
{% tab title="JavaScript (socket.io-client)" %}

```javascript
import { io } from 'socket.io-client';

const socket = io('https://predict.pretoke.xyz', {
  path: '/ws',
  transports: ['websocket']
});

socket.on('connect', () => {
  console.log('Connected');

  // Subscribe to market prices
  socket.emit('subscribe', { channel: 'market', marketIds: ['mkt_1', 'mkt_2'] });

  // Subscribe to order book
  socket.emit('subscribe', { channel: 'book', marketId: 'mkt_1' });

  // Subscribe to private user channel (requires auth token)
  socket.emit('subscribe', { channel: 'user', token: accessToken });

  // Keep-alive ping every 5 seconds
  setInterval(() => socket.emit('ping'), 5000);
});

socket.on('message', (msg) => {
  switch (msg.type) {
    case 'update':
      if (msg.channel === 'market') {
        console.log('Price update:', msg.data);
      } else if (msg.channel === 'book') {
        console.log('Book update:', msg.data);
      } else if (msg.channel === 'user') {
        console.log('Account update:', msg.data);
      }
      break;
    case 'snapshot':
      console.log('Order book snapshot:', msg.data);
      break;
    case 'pong':
      // Keep-alive acknowledged
      break;
    case 'error':
      console.error('WS error:', msg.message);
      break;
  }
});

socket.on('disconnect', () => {
  console.log('Disconnected — will auto-reconnect');
});
```

{% endtab %}

{% tab title="Python (python-socketio)" %}

```python
import socketio

sio = socketio.Client()

@sio.on('connect')
def on_connect():
    print('Connected')
    sio.emit('subscribe', {'channel': 'market', 'marketIds': ['mkt_1']})
    sio.emit('subscribe', {'channel': 'user', 'token': access_token})

@sio.on('message')
def on_message(msg):
    if msg.get('type') == 'update':
        print(f"[{msg['channel']}] {msg['data']}")
    elif msg.get('type') == 'snapshot':
        print(f"Snapshot: {msg['data']}")

sio.connect('https://predict.pretoke.xyz', socketio_path='/ws', transports=['websocket'])

# Keep-alive loop
import time
while True:
    sio.emit('ping')
    time.sleep(5)
```

{% endtab %}

{% tab title="Node.js (socket.io-client)" %}

```javascript
const { io } = require('socket.io-client');

const socket = io('https://predict.pretoke.xyz', {
  path: '/ws',
  transports: ['websocket']
});

socket.on('connect', () => {
  socket.emit('subscribe', { channel: 'market', marketIds: ['mkt_1'] });
  socket.emit('subscribe', { channel: 'user', token: accessToken });

  setInterval(() => socket.emit('ping'), 5000);
});

socket.on('message', (msg) => {
  if (msg.type === 'update') {
    console.log(`[${msg.channel}]`, msg.data);
  }
});
```

{% endtab %}
{% endtabs %}


---

# 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, and the optional `goal` query parameter:

```
GET https://docs.pretoke.xyz/api-reference/websocket.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
