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

# WebSocket Direct Integration

> Connect to VIZOCHOK via WebSocket without the SDK, for backend clients, custom frontends, and mobile apps.

Use the WebSocket API directly when you cannot use the JS SDK, for example in backend services, mobile apps, or custom chat UIs.

## When to Use Direct WebSocket

<CardGroup cols={2}>
  <Card title="Use the SDK" icon="code">
    * Web storefronts (any framework)
    * Standard floating or inline widget
    * Want built-in UI, reconnection, session management
  </Card>

  <Card title="Use Direct WebSocket" icon="plug">
    * Backend-to-backend chat (e.g. Telegram bot)
    * Mobile apps (React Native, Flutter, native)
    * Custom chat UI with full control
    * Testing and automation
  </Card>
</CardGroup>

## Quick Start

<Steps>
  <Step title="Connect to WebSocket">
    ```
    wss://api.vizochok.com/api/v1/ws/chat
    ```
  </Step>

  <Step title="Authenticate (first message)">
    ```json theme={null}
    {
      "type": "auth",
      "token": "pk_your_public_key",
      "store_id": "your-store",
      "user_id": "user-123"
    }
    ```

    Wait for `{"type": "auth_ok"}` before sending messages.
  </Step>

  <Step title="Send a message">
    ```json theme={null}
    {
      "type": "message",
      "text": "Show me milk",
      "conversation_id": "conv_abc123"
    }
    ```

    Omit `conversation_id` to start a new conversation.
  </Step>

  <Step title="Handle streaming response">
    You will receive multiple messages:

    1. `{"type": "status", "code": "searching", ...}` (progress indicator)
    2. `{"type": "text_delta", "delta": "Here "}` (repeated, concatenate)
    3. `{"type": "text_end"}` (text block complete)
    4. `{"type": "product_cards", "items": [...]}` (product results)
    5. `{"type": "response_complete", ...}` (ready for next message)
  </Step>
</Steps>

## Python Example

```python theme={null}
import asyncio
import json
import websockets

async def chat():
    async with websockets.connect("wss://api.vizochok.com/api/v1/ws/chat") as ws:
        # Authenticate
        await ws.send(json.dumps({
            "type": "auth",
            "token": "pk_your_key",
            "store_id": "your-store",
            "user_id": "user-123",
        }))

        auth_response = json.loads(await ws.recv())
        assert auth_response["type"] == "auth_ok"

        # Wait for conversation_started
        init = json.loads(await ws.recv())
        conversation_id = init.get("conversation_id")

        # Send a message
        await ws.send(json.dumps({
            "type": "message",
            "text": "What milk do you have?",
            "conversation_id": conversation_id,
        }))

        # Collect streaming response
        full_text = ""
        while True:
            msg = json.loads(await ws.recv())
            if msg["type"] == "text_delta":
                full_text += msg["delta"]
            elif msg["type"] == "response_complete":
                break

        print(full_text)

asyncio.run(chat())
```

## Node.js Example

```javascript theme={null}
const WebSocket = require('ws');

const ws = new WebSocket('wss://api.vizochok.com/api/v1/ws/chat');

ws.on('open', () => {
  ws.send(JSON.stringify({
    type: 'auth',
    token: 'pk_your_key',
    store_id: 'your-store',
    user_id: 'user-123',
  }));
});

let conversationId = null;
let fullText = '';

ws.on('message', (data) => {
  const msg = JSON.parse(data);

  switch (msg.type) {
    case 'auth_ok':
      break;
    case 'conversation_started':
      conversationId = msg.conversation_id;
      ws.send(JSON.stringify({
        type: 'message',
        text: 'What milk do you have?',
        conversation_id: conversationId,
      }));
      break;
    case 'text_delta':
      fullText += msg.delta;
      break;
    case 'response_complete':
      console.log(fullText);
      ws.close();
      break;
  }
});
```

## Session Management

* Save the `conversation_id` from `conversation_started` or `session_restored`
* Pass it in subsequent `message` calls to continue the same conversation
* Sessions expire after 1 hour of inactivity in Redis
* On reconnect with a valid `conversation_id`, the server sends `session_restored` with cart state

## Heartbeat

Send `{"type": "ping"}` every 30 seconds to keep the connection alive. The server also sends pings and expects a `{"type": "pong"}` response within 60 seconds.

## Full Protocol Reference

For the complete list of message types, fields, close codes, and error handling, see [WebSocket Protocol](/concepts/websocket-protocol).
