> For the complete documentation index, see [llms.txt](https://zumo.fusion.ac/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://zumo.fusion.ac/documentation/guides/connecting.md).

# Connecting

Connect to Zed’s default consumer namespace (`/`) with your Zumo key.

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

const socket = io('https://zed.fusion.ac', {
  auth: { key: process.env.ZUMO_CONSUMER_KEY },
  query: { mode: 'duels' }, // optional; omit for all modes
});

socket.on('connect', () => console.log('connected', socket.id));
socket.on('connect_error', (err) => console.error(err.message));
```

{% hint style="info" %}
Protocol is Socket.IO v5 / Engine.IO v4. The **event name** is the message type (for example `playerJoined`). There are no numeric opcodes.
{% endhint %}

## Requirements

* Key status `approved` and `enabled`
* Non-empty **consume** ACL for events you subscribe to
* For `replayRequest`, the event must appear in **provide** ACL

## Errors

| Symptom                                   | Likely cause                                   |
| ----------------------------------------- | ---------------------------------------------- |
| `connect_error` / `Unauthorized consumer` | Bad key, pending/denied, or disabled           |
| Connected but no events                   | Missing consume ACL, or mode filter too narrow |
| `replayRejected` with `unauthorized`      | Missing `replayRequest` on provide ACL         |

## Minimal lobby subscriber

```js
const LOBBY_EVENTS = [
  'playerJoined', 'playerLeft', 'chat', 'rawMessage',
  'locrawResponse', 'gameJoin', 'disconnected', 'error',
];

for (const name of LOBBY_EVENTS) {
  socket.on(name, (data) => {
    const { botId, mode, lobbyId, timestamp, ...fields } = data;
    // route by mode / lobbyId / event type
  });
}
```

See [API: WebSocket overview](https://app.gitbook.com/s/M9ty6FYa3j98VSBHF9LN/ws).
