> ## 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.

# Mirage

> WebSocket API for the Mirage execution simulator

Mirage is a single-instrument session with a PM-style broker prompt, bots, and a countdown. Connect as a UI client, then start with `mirageStartSession` (same effect as clicking **Start session** in the broker panel).

Product overview: [Mirage](/mirage). 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": "mirage" }`
3. Wait for `orderBook` (auth is async; broker greeting/confirm may appear; `brokerMessages` stay empty until start) and often `countdown` with `"pending"`
4. `{ "action": "mirageStartSession", "sessionDurationSeconds": 60 }` to start bots, countdown, and reveal the PM order
5. Receive `mirageSession` with `brokerMessages`, then an `orderBook` that includes the same order
6. Trade with `placeOrder` / `cancelOrder` / `cancelAllOrders` on instrument `0`
7. `resetExchange` or disconnect ends/logs the run as configured by the server

## 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"

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

  ready = False
  while True:
      msg = json.loads(ws.recv())
      if msg.get("type") == "orderBook" and not ready:
          ready = True
          ws.send(json.dumps({
              "action": "mirageStartSession",
              "sessionDurationSeconds": 60,
          }))
      elif msg.get("type") == "mirageSession":
          for order in msg.get("brokerMessages") or []:
              print(order["type"], order["orderQty"], "@", order["orderPrice"])
          print("countdown", msg.get("countdownSecondsLeft"))
      elif msg.get("type") == "countdown":
          print("countdown", msg.get("value"))
  ```

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

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

  ws.onmessage = (event) => {
    const msg = JSON.parse(event.data);
    if (msg.type === "orderBook" && !ready) {
      ready = true;
      ws.send(JSON.stringify({
        action: "mirageStartSession",
        sessionDurationSeconds: 60,
      }));
    }
    if (msg.type === "mirageSession") {
      for (const order of msg.brokerMessages || []) {
        console.log(order.type, order.orderQty, "@", order.orderPrice);
      }
      console.log("countdown", msg.countdownSecondsLeft);
    }
    if (msg.type === "countdown") {
      console.log("countdown", msg.value);
    }
  };
  ```
</CodeGroup>

## Client actions

| Action                                           | Body                                               | Effect                                                                                 |
| ------------------------------------------------ | -------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `userConnected`                                  | `token`, `applicationType: "mirage"`, `sessionId?` | Bind UI socket                                                                         |
| `mirageStartSession`                             | `sessionDurationSeconds?` (1–600, default 60)      | Start session: bots on, countdown, reveal broker order (idempotent; never toggles off) |
| `placeOrder` / `cancelOrder` / `cancelAllOrders` | See [overview](/api-reference/introduction)        | Instrument `0`                                                                         |
| `resetExchange`                                  | `sessionId?`                                       | Log/reset book; countdown returns to pending                                           |
| `recordSession`                                  | optional session fields                            | Snapshot PnL, position, broker messages                                                |
| `setBotsActive`                                  | `active: false`                                    | Bots off                                                                               |
| `toggleBots`                                     | `sessionDurationSeconds?`                          | Shared pause/resume toggle; Mirage UI uses `mirageStartSession` instead                |
| `brokerMessage`                                  | `messageData: { action, quantity, price }`         | Broker channel (UI mainly displays bot-driven messages)                                |
| `resetExperiment`                                | —                                                  | Reset mid and countdown pending                                                        |

## Server messages

### `mirageSession`

Sent to the requesting socket after `mirageStartSession`:

```json theme={null}
{
  "type": "mirageSession",
  "started": true,
  "botsRunning": true,
  "sessionDurationSeconds": 60,
  "countdownSecondsLeft": 60,
  "brokerMessages": [
    {
      "type": "buy",
      "orderQty": 25,
      "orderPrice": 10,
      "timestamp": "2026-08-08T12:00:00.000Z"
    }
  ]
}
```

| Field                         | Notes                                        |
| ----------------------------- | -------------------------------------------- |
| `brokerMessages[].type`       | `"buy"` or `"sell"`                          |
| `brokerMessages[].orderQty`   | Positive for buy, negative for sell          |
| `brokerMessages[].orderPrice` | Limit on the Mirage ladder (1–20)            |
| `countdownSecondsLeft`        | Seconds remaining (or duration just started) |

Calling `mirageStartSession` again while already running returns the same broker order and does not restart the clock.

### `countdown`

```json theme={null}
{ "type": "countdown", "value": 47 }
```

`value` is seconds left, or `"pending"` before/after a session.

### `orderBook` (Mirage extras)

In addition to the common book fields, Mirage may include:

| Field                  | Notes                                                      |
| ---------------------- | ---------------------------------------------------------- |
| `brokerMessages`       | PM / broker order lines (empty until `mirageStartSession`) |
| `brokerGreeting`       | Opening broker line                                        |
| `brokerConfirm`        | Confirmation payload when present                          |
| `countdownSecondsLeft` | Mirror of the live countdown                               |

### Scoring

Past sessions can store a Mirage Score (0–1). Formula and examples: [Mirage](/mirage#mirage-score).

## Related

* Guide: [Mirage](/mirage)
* Shared auth and orders: [API overview](/api-reference/introduction)
