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

# Atlas

> WebSocket API for Atlas headlines and trading

Atlas binds a UI WebSocket to a two-stock book and a server-driven headline feed. Signal headlines schedule delayed mid-shifts on Gamma bots; noise does not.

Product overview: [Atlas](/atlas). Shared connect and order fields: [API overview](/api-reference/introduction).

## Protocol

1. Connect to `wss://www.getavenir.co/ws`
2. `{ "action": "userConnected", "token": "<Clerk JWT>", "applicationType": "atlas", "atlasFeed": { } }`
3. Wait for `orderBook` and `atlasFeedState` (auth is async; bots are turned on for Atlas)
4. `{ "action": "atlasStartFeed" }` — immediate headline, then on the interval
5. Trade with `placeOrder` / `cancelOrder` on instruments `1` and `2`
6. `{ "action": "atlasStopFeed" }` when done

Identity comes from `token`. Optional `atlasFeed` on connect seeds session settings.

## Starter code

<CodeGroup>
  ```python Python theme={null}
  import json
  from websocket import create_connection

  ws = create_connection("wss://www.getavenir.co/ws")
  token = "paste_clerk_jwt_here"
  companies = []

  ws.send(json.dumps({
      "action": "userConnected",
      "token": token,
      "applicationType": "atlas",
  }))

  ready = False
  while True:
      msg = json.loads(ws.recv())
      if msg.get("type") == "atlasFeedState":
          companies = msg.get("companies") or []
          print("companies", companies, "playing", msg.get("isPlaying"))
          if not ready:
              ready = True
              ws.send(json.dumps({"action": "atlasStartFeed"}))
      elif msg.get("type") == "headline":
          text = msg.get("text") or ""
          subject = next((c for c in sorted(companies, key=len, reverse=True) if c and text.startswith(c)), None)
          print(msg.get("id"), subject or "noise", text)
  ```

  ```javascript JavaScript theme={null}
  const token = "paste_clerk_jwt_here";
  const ws = new WebSocket("wss://www.getavenir.co/ws");
  let companies = [];
  let ready = false;

  ws.onopen = () => {
    ws.send(JSON.stringify({
      action: "userConnected",
      token,
      applicationType: "atlas",
    }));
  };

  ws.onmessage = (event) => {
    const msg = JSON.parse(event.data);
    if (msg.type === "atlasFeedState") {
      companies = msg.companies || [];
      console.log("companies", companies, "playing", msg.isPlaying);
      if (!ready) {
        ready = true;
        ws.send(JSON.stringify({ action: "atlasStartFeed" }));
      }
    }
    if (msg.type === "headline") {
      const text = msg.text || "";
      const subject = [...companies]
        .filter((c) => c && text.startsWith(c))
        .sort((a, b) => b.length - a.length)[0] || null;
      console.log(msg.id, subject || "noise", text);
    }
  };
  ```
</CodeGroup>

## Client actions

| Action                                           | Body                                                            | Effect                                                |
| ------------------------------------------------ | --------------------------------------------------------------- | ----------------------------------------------------- |
| `userConnected`                                  | `token`, `applicationType: "atlas"`, `sessionId?`, `atlasFeed?` | Bind UI socket; ensure feed session                   |
| `atlasStartFeed`                                 | optional settings                                               | Start feed; emit headline then interval               |
| `atlasStopFeed`                                  | —                                                               | Stop feed                                             |
| `atlasConfigureFeed`                             | settings fields                                                 | Update stored settings (restarts interval if playing) |
| `atlasGetFeedState`                              | —                                                               | Push a fresh `atlasFeedState`                         |
| `atlasSessionMeta`                               | `avgReactionMs`                                                 | Client reaction timing for session scoring            |
| `placeOrder` / `cancelOrder` / `cancelAllOrders` | See [overview](/api-reference/introduction)                     | `instrumentId` `1` or `2`                             |
| `resetExchange`                                  | `sessionId?`                                                    | Log atlas session; reset feed counts; bots stay on    |
| `recordSession`                                  | uses server headline counts + `avgReactionMs`                   | Persist session                                       |
| `setBotsActive`                                  | `active: false`                                                 | Bots off                                              |

Optional settings on connect / `atlasStartFeed` / `atlasConfigureFeed`:

```json theme={null}
{
  "frequencySeconds": 3,
  "reactionMinPoints": 3,
  "reactionMaxPoints": 6,
  "delayMinSeconds": 2,
  "delayMaxSeconds": 4,
  "tickerMappingEnabled": true
}
```

Values are clamped server-side. The sample above matches server defaults; Easy / Medium / Hard presets use other bands (Medium is reaction 4–8). Mid-shift magnitude and delay always come from the stored session band.

## Server messages

### `headline`

Wire payload is text-only. Kind, direction, subject, instrument, and counters are **not** included.

```json theme={null}
{
  "type": "headline",
  "id": "…",
  "text": "Harbor Vertex Inc. raises full-year revenue guidance above consensus.",
  "timestamp": 1710000000000
}
```

| Field       | Notes                |
| ----------- | -------------------- |
| `id`        | Headline id          |
| `text`      | Full headline string |
| `timestamp` | Emit time (ms)       |

Infer signal vs noise by matching `text` against `atlasFeedState.companies` (longest prefix wins). `companies[0]` → instrument `1`, `companies[1]` → instrument `2`. No company prefix ⇒ noise.

Bullish/bearish direction is in the wording, not a separate field. The server still schedules delayed mid-shifts for signals; watch `orderBook.atlasMidShiftStatus` when a shift fires (`instrumentId`, `direction`, `delta`, `timestamp`).

Live counters (`headlinesSeen`, `tradableHeadlinesSeen`) live on `atlasFeedState` (connect, start/stop/configure, `atlasGetFeedState`), not on each `headline`.

### `atlasFeedState`

```json theme={null}
{
  "type": "atlasFeedState",
  "companies": ["Harbor Vertex Inc.", "Sterling Capital Ltd."],
  "isPlaying": true,
  "frequencySeconds": 3,
  "reactionMinPoints": 3,
  "reactionMaxPoints": 6,
  "delayMinSeconds": 2,
  "delayMaxSeconds": 4,
  "tickerMappingEnabled": true,
  "headlinesSeen": 12,
  "tradableHeadlinesSeen": 3,
  "atlasDifficultyMode": "custom"
}
```

`companies[0]` → instrument `1`, `companies[1]` → instrument `2`.

### `orderBook`

Includes `gammaBotMidsByInstrument` and `atlasMidShiftStatus` while the session is live.

## Related

* Guide: [Atlas](/atlas)
* Shared auth and orders: [API overview](/api-reference/introduction)
* Opera bots: [Opera](/api-reference/opera)
