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

# Chat & notifications (/chat)

> Receive group messages, proposal updates, and per-user notifications in real time.

The `/chat` namespace is the per-user real-time channel. On connect it auto-joins you to every group
you belong to plus a private `user:{userId}` room, so you receive messages and notifications without
subscribing per group.

```javascript theme={null}
import { io } from "socket.io-client";

const socket = io("wss://api.alpha-labs.trade/chat", {
  transports: ["websocket"],
  auth: { token: process.env.MURMO_API_KEY },
});

socket.on("connected", ({ userId, groups, reactionKeys }) => {
  console.log(`connected as ${userId}, in ${groups.length} groups`);
});

socket.on("new_message", (msg) => {
  console.log(`[${msg.groupId}] ${msg.content}`);
});

socket.on("proposal_updated", (p) => {
  console.log("proposal changed:", p.type, p.metadata);
});
```

## Server → client events

| Event                                          | Room         | Payload                                                                                                                            |
| ---------------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| `connected`                                    | socket       | `{ userId, groups, reactionKeys }`                                                                                                 |
| `new_message`                                  | `group:{id}` | The created message.                                                                                                               |
| `message_updated`                              | `group:{id}` | The edited message.                                                                                                                |
| `message_deleted`                              | `group:{id}` | The deleted message id.                                                                                                            |
| `message_pinned` / `message_unpinned`          | `group:{id}` | The (un)pinned message.                                                                                                            |
| `unread_updated`                               | `user:{id}`  | `{ groupId, unreadCount }`                                                                                                         |
| `proposal_updated`                             | `group:{id}` | A trade-idea change; `metadata` carries the details.                                                                               |
| `membership_changed` / `join_request_approved` | `user:{id}`  | Membership changes for you.                                                                                                        |
| `achievement_earned`                           | `user:{id}`  | A new achievement.                                                                                                                 |
| `notification.*`                               | `user:{id}`  | Push-style notifications (`notification.message`, `notification.proposal`, `notification.membership`, `notification.achievement`). |
| `error`                                        | socket       | `{ message }`                                                                                                                      |

<Note>
  `proposal_updated.metadata` is where trade economics live (e.g. `initialPrice` on create,
  `exitPnlUsd` / `exitPnlPct` on close, `didWin` / `result` on resolve). These money fields follow
  the API's decimal-**string** contract.
</Note>

## Client → server events

You can drive chat over the socket, though for bots the [REST chat endpoints](/api-reference) are
often simpler. Available messages:

`send_message`, `share_asset`, `add_reaction`, `remove_reaction`, `delete_message`, `pin_message`,
`unpin_message`, `get_pinned_messages`, `join_group`, `leave_group`, `focus_chat`, `blur_chat`.

## Sending: socket vs REST

<CardGroup cols={2}>
  <Card title="Over the socket" icon="bolt">
    `socket.emit("send_message", { groupId, type: "TEXT", content: "gm" })` — lowest latency if
    you're already connected.
  </Card>

  <Card title="Over REST" icon="paper-plane">
    `POST /api/v1/chat/{groupId}/messages` with `{ "type": "TEXT", "content": "gm" }` — stateless,
    same persistence and broadcast. Good for fire-and-forget bots.
  </Card>
</CardGroup>

Both run the identical send path (permission check, moderation, persistence, broadcast), so a message
sent via REST still arrives as a `new_message` to everyone on the socket. Membership is enforced — you
can only read and post in groups you belong to.

## REST chat endpoints

If your bot prefers plain HTTP over the socket, the full chat surface is four endpoints, all
members-only:

| Endpoint                               | Does                                                           |
| -------------------------------------- | -------------------------------------------------------------- |
| `GET /api/v1/chat/{groupId}/messages`  | Page history (newest first; cursor with `before` / `after`).   |
| `POST /api/v1/chat/{groupId}/messages` | Send a message (`type`: `TEXT`, `STICKER`, `IMAGE`, `SYSTEM`). |
| `GET /api/v1/chat/{groupId}/pinned`    | List pinned messages (newest pin first).                       |
| `POST /api/v1/chat/{groupId}/read`     | Mark the group read (resets your unread count to 0).           |

<Tip>
  A common bot pattern: connect to `/chat` to **receive** `new_message` and `proposal_updated`, and
  use the REST endpoints to **send** and to page history (`GET /api/v1/chat/{groupId}/messages`).
</Tip>
