# WebSocket Protocol

Vask speaks the Pusher Channels WebSocket protocol over native WebSockets.

```text
wss://wss.vask.dev/app/{app_key}?protocol=7&client=js&version=8.4.0
```

Fallback transports such as SockJS, HTTP streaming, and long polling are intentionally not part of Vask's WebSocket parity scope.

## Connection established

After the WebSocket handshake, Vask sends:

```json
{
    "event": "pusher:connection_established",
    "data": "{\"socket_id\":\"1234.5678\",\"activity_timeout\":120}"
}
```

Use `socket_id` when signing private, presence, encrypted, and user authentication requests.

## Heartbeats

Clients may send:

```json
{
    "event": "pusher:ping",
    "data": {}
}
```

Vask replies:

```json
{
    "event": "pusher:pong",
    "data": {}
}
```

SDKs usually handle this automatically.

## Subscribe

Public channel:

```json
{
    "event": "pusher:subscribe",
    "data": {
        "channel": "public-feed"
    }
}
```

Private channel:

```json
{
    "event": "pusher:subscribe",
    "data": {
        "channel": "private-dashboard.42",
        "auth": "app_key:hmac_signature"
    }
}
```

Presence channel:

```json
{
    "event": "pusher:subscribe",
    "data": {
        "channel": "presence-room.42",
        "auth": "app_key:hmac_signature",
        "channel_data": "{\"user_id\":\"user-123\",\"user_info\":{\"name\":\"Ada\"}}"
    }
}
```

Successful subscriptions emit `pusher_internal:subscription_succeeded`.

## Unsubscribe

```json
{
    "event": "pusher:unsubscribe",
    "data": {
        "channel": "presence-room.42"
    }
}
```

Presence channels emit member removal events when the last connection for a `user_id` leaves.

## User sign-in

```json
{
    "event": "pusher:signin",
    "data": {
        "auth": "app_key:hmac_signature",
        "user_data": "{\"id\":\"user-123\",\"name\":\"Ada\"}"
    }
}
```

Vask replies with `pusher:signin_success` or `pusher:error`.

## Client events

Client events must start with `client-` and include a subscribed private or presence channel.

```json
{
    "event": "client-typing",
    "channel": "private-room.42",
    "data": "{\"is_typing\":true}"
}
```

## Close codes

| Code   | Meaning                                      |
| ------ | -------------------------------------------- |
| `4001` | Unknown app.                                 |
| `4003` | App disabled.                                |
| `4004` | Connection quota exceeded.                   |
| `4005` | Unknown WebSocket path.                      |
| `4009` | Unauthorized connection or command.          |
| `4200` | Signed-in user connection terminated by API. |
| `4201` | Heartbeat timeout.                           |

## Unsupported transport scope

Vask is a WebSocket service. Configure browser SDKs to use `ws` and `wss` transports.

```js
const pusher = new Pusher('app_key', {
    wsHost: 'wss.vask.dev',
    wsPort: 443,
    forceTLS: true,
    enabledTransports: ['ws', 'wss'],
});
```

## Related docs

- [Channels](/docs/channels)
- [Authentication and signatures](/docs/authentication)
- [User authentication](/docs/user-authentication)
