# Realtime — Socket.IO

Endpoint: `wss://api.crm.emerald-system.id` (atau `ws://localhost:3010` lokal) path `/socket.io`

## Auth (wajib)

Kirim salah satu saat connect:

- Query: `?token=JWT` atau `?api_key=wg_xxx`
- Header: `Authorization: Bearer <JWT>` atau `x-api-key: wg_xxx`

JWT = login `POST /api/auth/login`. `x-api-key` = dari `api_keys`. Gagal = error `UNAUTHORIZED`.

## Connect

```js
import { io } from "socket.io-client";
const socket = io("https://api.crm.emerald-system.id", {
  path: "/socket.io",
  transports: ["websocket","polling"],
  query: { api_key: "wg_xxx" } // atau token: "eyJ..."
});
socket.on("connected", console.log);
socket.on("connect_error", e => console.error(e.message));
```

## Join room per session (wajib untuk dapat event)

```js
socket.emit("join", { session_id: "cs-01" }, res => console.log(res));
// atau
socket.emit("subscribe", { sessions: ["cs-01","marketing"] }, console.log);
socket.emit("leave", { session_id: "cs-01" });
```

Hanya event dari session yang di-join yang akan masuk.

## Event yang dikirim server

Semua event bentuk: `{ event, session_id, timestamp, data }`

Event: `connection.update`, `message.upsert`, `message.status`, `message.waiting`, `message.scheduled_sent` + semua event webhook yang sama. Client akan menerima event di **3 channel** (pilih salah satu):

- `socket.on(eventName, cb)` — misal `socket.on("message.upsert", cb)`
- `socket.on("message", cb)` — semua event
- `socket.on("event", cb)` — alias

```js
socket.on("message.upsert", (msg) => {
  console.log(msg.session_id, msg.data.text, msg.data.from);
});
socket.on("connection.update", (msg) => console.log(msg.data.status));
socket.on("message.status", (msg) => console.log(msg.data.status)); // delivered/read
```

## Contoh Node.js consumer

```js
import { io } from "socket.io-client";
const s = io("https://api.crm.emerald-system.id", { query: { api_key: process.env.API_KEY } });
s.on("connect", () => s.emit("join", { session_id: "cs-01" }));
s.on("message.upsert", m => console.log("baru:", m.data));
s.on("message.status", m => console.log("status:", m.data));
```

## Catatan

- Realtime **tidak menggantikan webhook** — keduanya dikirim bersamaan. Webhook tetap untuk server-to-server, socket untuk browser/consumer realtime.
- Jika tidak join room, tidak ada event masuk.
- Ping: `socket.emit("ping", cb)`
