---
title: WebSocket API Reference
description: Complete WebSocket API reference for NoLag real-time communication. Covers connection, authentication, message types, presence, lobbies, and reconnection.
---

# WebSocket API Reference

Low-level WebSocket protocol reference for NoLag real-time communication. All messages use MessagePack binary encoding.

## Connection

| Property | Value |
| --- | --- |
| Endpoint | `wss://broker.nolag.app/ws` |
| Encoding | MessagePack binary frames |
| Heartbeat | Empty binary packet (0 bytes) every 30 seconds, both directions |

## Authentication

The first message sent after connecting must be an authentication request. The server enforces a **10-second timeout** for the auth response. If no valid auth message is received within that window, the connection is closed.

```json [Request]
{
  "type": "auth",
  "token": "at_live_<key_id>.<secret>",
  "reconnect": false,
  "projectId": "..."
}
```
```json [Response (success)]
{
  "type": "auth",
  "success": true,
  "actorTokenId": "...",
  "restoredSubscriptions": [...]
}
```
```json [Response (failure)]
{
  "type": "auth",
  "success": false,
  "error": "invalid_token"
}
```

| Field | Type | Description |
| --- | --- | --- |
| `type` | string | Always `"auth"` |
| `token` | string | Access token in the format `at_live_<key_id>.<secret>` |
| `reconnect` | boolean | Set to `true` to trigger subscription restoration after a reconnect |
| `projectId` | string | The project identifier |

## Client to Server Messages

### 1. subscribe

Subscribe to a topic to begin receiving messages.

```json [JSON]
{
  "type": "subscribe",
  "topic": "app/room/topic",
  "qos": 1,
  "filters": ["f1"],
  "loadBalance": false,
  "loadBalanceGroup": "group-1"
}
```

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `type` | string | Yes | Always `"subscribe"` |
| `topic` | string | Yes | Human-readable slug format: `app/room/topic` |
| `qos` | number | No | Quality of Service level: `0`, `1` (default), or `2` |
| `filters` | string[] | No | Filter array. Max 100 entries. Characters `/`, `#`, `+` are not allowed. |
| `loadBalance` | boolean | No | Enable load balancing to distribute messages across clients |
| `loadBalanceGroup` | string | No | Group name for load balancing |

### 2. unsubscribe

Stop receiving messages from a topic.

```json [JSON]
{
  "type": "unsubscribe",
  "topic": "app/room/topic"
}
```

### 3. publish

Publish a message to a topic.

```json [JSON]
{
  "type": "publish",
  "topic": "app/room/topic",
  "data": { "your": "payload" },
  "qos": 1,
  "echo": true,
  "filter": "f1"
}
```

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `type` | string | Yes | Always `"publish"` |
| `topic` | string | Yes | Target topic in slug format |
| `data` | object | Yes | The message payload |
| `qos` | number | No | Quality of Service level: `0`, `1` (default), or `2` |
| `echo` | boolean | No | Set to `false` to prevent the message from being delivered back to the sender |
| `filter` | string | No | Route the message only to subscribers whose filter set includes this value |

### 4. setFilters

Replace the entire filter set for a subscription. Sending an empty array acts as a wildcard, meaning all messages will be received.

```json [JSON]
{
  "type": "setFilters",
  "topic": "app/room/topic",
  "filters": ["f1"]
}
```

### 5. presence

Announce or update presence data for a room.

```json [JSON]
{
  "type": "presence",
  "roomId": "room-slug",
  "data": { "status": "online" }
}
```

### 6. getPresence

Request the current presence list for a room.

```json [JSON]
{
  "type": "getPresence",
  "roomId": "room-slug"
}
```

### 7. ack

Acknowledge receipt of a single message. Required when the server sends a message with `requiresAck: true`.

```json [JSON]
{
  "type": "ack",
  "msgId": "uuid"
}
```

### 8. batchAck

Acknowledge receipt of multiple messages at once. Required when the server sends messages with `requiresAck: true`.

```json [JSON]
{
  "type": "batchAck",
  "msgIds": ["id1", "id2"]
}
```

### 9. lobbySubscribe

Subscribe to a lobby to receive aggregated presence events across multiple rooms.

```json [JSON]
{
  "type": "lobbySubscribe",
  "lobbyId": "lobby-slug"
}
```

### 10. lobbyUnsubscribe

Unsubscribe from a lobby.

```json [JSON]
{
  "type": "lobbyUnsubscribe",
  "lobbyId": "lobby-slug"
}
```

### 11. getLobbyPresence

Request the current presence data for an entire lobby.

```json [JSON]
{
  "type": "getLobbyPresence",
  "lobbyId": "lobby-slug"
}
```

## Server to Client Messages

### 1. message

Delivers a published message to the client.

```json [JSON]
{
  "type": "message",
  "topic": "...",
  "data": { "your": "payload" },
  "msgId": "uuid",
  "requiresAck": true,
  "isReplay": false,
  "filter": "f1"
}
```

| Field | Type | Description |
| --- | --- | --- |
| `msgId` | string | Present when message logging is enabled on the topic |
| `requiresAck` | boolean | When `true`, the client must respond with an `ack` or `batchAck` |
| `isReplay` | boolean | Set to `true` when the message is being replayed after a reconnect |
| `filter` | string | The filter value the message was published with |

### 2. subscribed

Confirms a successful subscription.

```json [JSON]
{
  "type": "subscribed",
  "topic": "...",
  "loadBalance": false
}
```

### 3. unsubscribed

Confirms a successful unsubscription.

```json [JSON]
{
  "type": "unsubscribed",
  "topic": "..."
}
```

### 4. filtersUpdated

Confirms that the filter set for a subscription has been updated.

```json [JSON]
{
  "type": "filtersUpdated",
  "topic": "...",
  "filters": ["f1"]
}
```

### 5. presence

Notifies the client of a presence change in a room (join, leave, or update).

```json [JSON]
{
  "type": "presence",
  "event": "join",
  "data": {
    "actorTokenId": "...",
    "presence": { "status": "online" },
    "joinedAt": 1716000000
  }
}
```

The `event` field is one of: `"join"`, `"leave"`, or `"update"`.

### 6. presenceList

Returns the full list of present actors in a room. Sent in response to a `getPresence` request.

```json [JSON]
{
  "type": "presenceList",
  "roomId": "...",
  "data": [
    { "actorTokenId": "...", "presence": { "status": "online" }, "joinedAt": 1716000000 }
  ]
}
```

### 7. lobbySubscribed

Confirms a lobby subscription and includes the current presence snapshot.

```json [JSON]
{
  "type": "lobbySubscribed",
  "lobbyId": "...",
  "presence": {
    "room1": {
      "actor1": { "status": "online" }
    }
  }
}
```

### 8. lobbyUnsubscribed

Confirms a lobby unsubscription.

```json [JSON]
{
  "type": "lobbyUnsubscribed",
  "lobbyId": "..."
}
```

### 9. lobbyPresence

Notifies the client of a presence event within a lobby.

```json [JSON]
{
  "type": "lobbyPresence",
  "event": "join",
  "lobbyId": "...",
  "roomId": "...",
  "actorId": "...",
  "data": { "status": "online" }
}
```

### 10. lobbyPresenceList

Returns the full presence data for a lobby. Sent in response to a `getLobbyPresence` request.

```json [JSON]
{
  "type": "lobbyPresenceList",
  "lobbyId": "...",
  "presence": { "room1": { "actor1": { "status": "online" } } }
}
```

### 11. replayStart

Indicates the beginning of a message replay sequence after reconnection.

```json [JSON]
{
  "type": "replayStart",
  "count": 247,
  "oldestTimestamp": "...",
  "newestTimestamp": "..."
}
```

### 12. replayEnd

Indicates the end of a message replay sequence.

```json [JSON]
{
  "type": "replayEnd",
  "replayed": 247
}
```

### 13. hydration

Sent automatically on subscribe when a webhook is configured for that topic (via `topicConfigs.webhooks.onSubscribe` or the legacy app-level hydration webhook). Contains initial state data.

```json [JSON]
{
  "type": "hydration",
  "topic": "...",
  "data": { "initialState": "..." }
}
```

### 14. error

Reports an error to the client.

```json [JSON]
{
  "type": "error",
  "error": "rate_limit_exceeded",
  "code": 42910,
  "topic": "..."
}
```

### 15. disconnect

Informs the client that the server is closing the connection, along with the reason.

```json [JSON]
{
  "type": "disconnect",
  "reason": "token_invalid"
}
```

## QoS Levels

| Level | Name | Description |
| --- | --- | --- |
| `0` | At most once | Fire and forget. No delivery guarantee. |
| `1` | At least once | Acknowledged delivery. Messages may be delivered more than once. |
| `2` | Exactly once | Guaranteed single delivery. |

## Reconnection

When a client reconnects after a disconnect, it should send the `auth` message with `reconnect: true`. The server will restore previous subscriptions and replay any messages that were missed during the disconnect.

### Reconnection flow

1. Client reconnects and sends `auth` with `reconnect: true`.
2. Server responds with `restoredSubscriptions`, an array of objects containing: `pattern`, `loadBalance`, `loadBalanceGroup`, and `filters`.
3. Server sends a `replayStart` message with the total count and timestamp range.
4. Server delivers all missed messages (with `isReplay: true`).
5. Server sends a `replayEnd` message confirming how many messages were replayed.

### Backoff strategy

| Parameter | Value |
| --- | --- |
| Base delay | 5 seconds |
| Max delay | 30 seconds |
| Multiplier | 1.5x |

Each failed reconnection attempt increases the delay by the multiplier, up to the maximum. For example: 5s, 7.5s, 11.25s, 16.875s, 25.3s, 30s, 30s, ...

## Next Steps

- [Error Codes](/docs/api-reference/errors)
- [JavaScript SDK](/docs/sdks/javascript)
