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

# WebSocket Setup

## Quick Start

For quick integration, follow these steps:

1. **Connect** to `wss://ws.noodles.fi/ws/coin-update`
2. **Send periodic pings** every 30 seconds to keep connection alive
3. **Subscribe** using the room-based format (recommended)
4. **Handle messages** by checking the `type` field
5. **Implement reconnection**: On disconnect, automatically reconnect and resubscribe to your channels

## Endpoints

```
wss://ws.noodles.fi/ws/coin-update
```

## CORS Validation

* Web browser connections must pass CORS validation based on the `Origin` header.
* Contact [@hiephho](https://t.me/hiephho) on Telegram for whitelisting your domain.
* If CORS validation fails, the server will send 403 Forbidden status code and close the connection.

## Available Rooms

The WebSocket service supports four main data rooms:

1. [**TRADES**](/docs.noodles.fi/websocket/room-trades.md) - Real-time trading transaction data
2. [**COIN\_UPDATES**](/docs.noodles.fi/websocket/room-coin-updates.md) - Real-time coin updates for coins (price, price change, volume, maker, etc.)
3. [**OHLC**](/docs.noodles.fi/websocket/room-ohlc.md) - Candlestick/OHLC data for various time intervals

## Coin ID Format

All coin identifiers follow the format: `{package}::{module}::{type}`

**Examples**:

* SUI: `0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI`
* USDC: `0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC`

## Message Protocol

### Message Types

| Type          | Direction       | Purpose                           |
| ------------- | --------------- | --------------------------------- |
| `ping`        | Client → Server | Keep connection alive             |
| `pong`        | Server → Client | Ping response                     |
| `subscribe`   | Client → Server | Subscribe to a channel            |
| `unsubscribe` | Client → Server | Unsubscribe from a channel        |
| `data`        | Server → Client | Real-time data or acknowledgments |
| `error`       | Server → Client | Error messages                    |

### Client Message Format

```json
{
  "type": "subscribe|unsubscribe|ping",
  "room": "ROOM_NAME",
  "data": {
    // Room-specific data
  }
}
```

**Examples**:

Subscribe to trades for a single coin:

```json
{
  "type": "subscribe",
  "room": "TRADES",
  "data": {
    "coin": "0x2::sui::SUI"
  }
}
```

Subscribe to coin statistic updates for multiple coins:

```json
{
  "type": "subscribe",
  "room": "COIN_UPDATES",
  "data": {
    "coins": [
      "0x2::sui::SUI",
      "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC"
    ]
  }
}
```

Subscribe to OHLC data:

```json
{
  "type": "subscribe",
  "room": "OHLC",
  "data": {
    "coin": "0x2::sui::SUI",
    "bucket": 5
  }
}
```

### Server Message Format

```json
{
  "type": "data|error|pong|subscribe|unsubscribe",
  "channel": "CHANNEL_NAME",
  "room": "ROOM_NAME",
  "data": { ... },
  "error": "error_message"
}
```

#### Subscription Confirmation

When you subscribe or unsubscribe, the server sends a confirmation message:

```json
{
  "type": "subscribe",
  "data": {
    "action": "subscribe",
    "channels": ["TRADES-0x2::sui::SUI"],
    "room": "TRADES"
  }
}
```

## Error Handling

### Common Error Messages

| Error                        | Description                                 | Resolution                                                               |
| ---------------------------- | ------------------------------------------- | ------------------------------------------------------------------------ |
| `"Invalid channel format"`   | Channel name doesn't follow expected format | Check channel naming convention                                          |
| `"Invalid coin"`             | Coin ID is not valid                        | Verify coin ID format                                                    |
| `"Invalid room"`             | Unsupported room type                       | Use TRADES, COIN\_UPDATES, OHLC, or ALERTS                               |
| `"Invalid bucket"`           | Unsupported time bucket for OHLC            | Use supported time intervals (1, 5, 15, 30, 60, 240, 1440, 10080, 43200) |
| `"Invalid coins format"`     | Coins array format is incorrect             | Ensure coins is an array of valid coin IDs                               |
| `"Invalid wallet"`           | Wallet address is not valid                 | Verify wallet address format                                             |
| `"Invalid message format"`   | Message JSON is malformed                   | Check JSON syntax                                                        |
| `"Unsupported message type"` | Unknown message type                        | Use ping, subscribe, or unsubscribe                                      |

### Connection Errors

* **Rate Limit Exceeded**: Temporary IP blocking due to too many connection attempts (http status 429)
* **Origin Not Allowed**: CORS validation failure (http status 403)
* **Connection Timeout**: Network connectivity issues

## Rate Limits

* **Maximum Connections per IP**: 20
* **Maximum Connection Attempts per Minute**: 30
* **Blocking Duration**: 10 minutes for IPs exceeding limits

## Integration Examples

### JavaScript/Web Browser

```javascript
// Connect to WebSocket
const ws = new WebSocket('wss://ws.noodles.fi/ws/coin-update');

// Connection opened
ws.onopen = function() {
    console.log('Connected to Noodles WebSocket');
    
    // Send ping to keep connection alive
    ws.send(JSON.stringify({
        type: 'ping'
    }));
    
    // Subscribe to USDC trading data (new format - recommended)
    ws.send(JSON.stringify({
        type: 'subscribe',
        room: 'TRADES',
        data: {
            coin: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC'
        }
    }));
};

// Handle incoming messages
ws.onmessage = function(event) {
    const message = JSON.parse(event.data);
    
    switch(message.type) {
        case 'data':
            handleDataMessage(message);
            break;
        case 'error':
            console.error('WebSocket error:', message.error);
            break;
        case 'pong':
            console.log('Received pong from server');
            break;
    }
};

function handleDataMessage(message) {
    const { channel, room, data } = message;
    
    // Check if it's a subscription confirmation
    if (data && data.action && (data.action === 'subscribe' || data.action === 'unsubscribe')) {
        console.log(`${data.action} confirmed for room ${data.room}:`, data.channels);
        return;
    }
    
    // Handle data based on room type
    if (room === 'TRADES' || channel?.startsWith('TRADES-')) {
        console.log('Trading data:', data);
    } else if (room === 'COIN_UPDATES' || channel?.startsWith('COIN_UPDATES-')) {
        console.log('Price update:', data);
    } else if (room === 'OHLC' || channel?.startsWith('OHLC.')) {
        console.log('OHLC data:', data);
    } else if (room === 'ALERTS' || channel?.startsWith('ALERTS.')) {
        console.log('Wallet alert:', data);
    }
}

// Connection error
ws.onerror = function(error) {
    console.error('WebSocket error:', error);
};

// Connection closed
ws.onclose = function(event) {
    console.log('WebSocket connection closed:', event.code, event.reason);
};

// Unsubscribe from a channel 
function unsubscribe(room, coin, bucket) {
    const message = {
        type: 'unsubscribe',
        room: room,
        data: {}
    };
    
    if (room === 'TRADES' || room === 'OHLC') {
        message.data.coin = coin;
        if (room === 'OHLC' && bucket) {
            message.data.bucket = bucket;
        }
    } else if (room === 'COIN_UPDATES') {
        message.data.coins = Array.isArray(coin) ? coin : [coin];
    }
    
    ws.send(JSON.stringify(message));
}

// Example usage:
// unsubscribe('TRADES', '0x2::sui::SUI');
// unsubscribe('OHLC', '0x2::sui::SUI', 5);
// unsubscribe('COIN_UPDATES', ['0x2::sui::SUI', '0xdba...::usdc::USDC']);
```

For more detailed examples including TypeScript integrations, see the individual room documentation pages.


---

# 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://noodles-finance.gitbook.io/docs.noodles.fi/websocket/websocket-setup.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.
