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

# Opera

> WebSocket API for Opera missions and external bots

Opera is the API-first simulator. External clients authenticate with `operaConnect`, place and cancel with request/response (`operaResult`), and receive `operaState` plus `orderBook`.

Product overview: [Opera](/opera). Full message schemas: OpenAPI group **Opera** in the sidebar.

## Get a token

1. Sign in at [getavenir.co](https://www.getavenir.co)
2. Open **Opera** (or go to `/opera`)
3. Click **Copy token**
4. Send it in `operaConnect` as `token`

Tokens expire quickly. On `operaResult` with `status: 401`, copy a fresh token and reconnect.

## Protocol

1. Connect to `wss://www.getavenir.co/ws`
2. `{ "action": "operaConnect", "token": "...", "requestId": "c1" }`
3. Expect `operaResult` (`op: "connect"`, `status: 200`), then `orderBook` and `operaState`
4. `{ "action": "operaPlace", ... }` / `operaCancel` / `operaCancelAll` / `operaGetState`
5. Correlate replies with optional `requestId` on `operaResult`

The in-app UI may instead use `userConnected` with `applicationType: "opera"` (UI client). Bot-mode and session record/reset are **UI-only**; API sockets get those rejected.

## Starter code

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

  ws = create_connection("wss://www.getavenir.co/ws")
  token = "paste_token_here"

  ws.send(json.dumps({"action": "operaConnect", "token": token, "requestId": "c1"}))
  print(ws.recv())

  ws.send(json.dumps({
      "action": "operaPlace",
      "requestId": "p1",
      "orders": [
          {"type": "bid", "price": 9, "quantity": 1, "instrumentId": 0},
          {"type": "bid", "price": 10, "quantity": 1, "instrumentId": 0},
      ],
  }))
  print(ws.recv())
  ws.close()
  ```

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

  ws.onopen = () => {
    ws.send(JSON.stringify({ action: "operaConnect", token, requestId: "c1" }));
  };

  ws.onmessage = (event) => {
    const msg = JSON.parse(event.data);
    console.log(msg);
    if (msg.type === "operaResult" && msg.op === "connect" && msg.status === 200) {
      ws.send(JSON.stringify({
        action: "operaPlace",
        requestId: "p1",
        orders: [
          { type: "bid", price: 9, quantity: 1, instrumentId: 0 },
          { type: "bid", price: 10, quantity: 1, instrumentId: 0 },
        ],
      }));
    }
  };
  ```
</CodeGroup>

## Client actions

| Action               | Body                                                                                                          | Who      |
| -------------------- | ------------------------------------------------------------------------------------------------------------- | -------- |
| `operaConnect`       | `token`, `requestId?`, `sessionId?`                                                                           | API      |
| `operaPlace`         | single `{ type, price, quantity, instrumentId?, orderId? }` **or** `{ orders: [...] }` (max 40), `requestId?` | API + UI |
| `operaCancel`        | `orderId`, `requestId?`                                                                                       | API + UI |
| `operaCancelAll`     | `requestId?`                                                                                                  | API + UI |
| `operaGetState`      | `requestId?`                                                                                                  | API + UI |
| `operaSetBotMode`    | `mode`: `off` \| `static` \| `walker` \| `taker`                                                              | UI only  |
| `operaSetWalker`     | `active: true\|false`                                                                                         | UI only  |
| `operaSessionRecord` | `sessionId?`, `missionsPassed?`                                                                               | UI only  |
| `operaSessionReset`  | same                                                                                                          | UI only  |

Default instrument is `0`. `orderId` is optional on place (server can assign a UUID). Status codes on `operaResult` are HTTP-like (`200` / `201` / `400` / `403` / `404` / `429`). Cancel of another participant's order returns **403**; place/cancel rate limits return **429** (same 120 / 240 per 60s bands as UI trading). `operaCancelAll` is not cancel-rate-limited.

UI `placeOrder` / `toggleBots` are **not** available on API sockets (`forbidden` / `ui_only`).

## Server messages

| Type          | Role                                                                           |
| ------------- | ------------------------------------------------------------------------------ |
| `operaResult` | Reply to a client action (`op`, `requestId`, `status`, plus body)              |
| `operaState`  | Snapshot: open orders, position, pnl, fills, ladder, `actions[]`, taker fields |
| `orderBook`   | Live book / participants (Opera participants may include `fills`)              |

## Related

* Guide: [Opera](/opera)
* Shared overview: [API overview](/api-reference/introduction)
* Schemas: OpenAPI **Opera** group
