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

# WebSocket

> Supported Phoenix WebSocket subscription requests and response message types.

## Connection

Connect to the Phoenix WebSocket endpoint:

```text theme={null}
wss://perp-api.phoenix.trade/v1/ws
```

The Rust SDK uses `PHOENIX_WS_URL` when it is set. Otherwise, it derives the WebSocket URL from `PHOENIX_API_URL` by switching `http` to `ws` and using `/v1/ws`.

Messages are UTF-8 JSON objects.

## Client messages

Subscribe with a `type` and `subscription` envelope:

```json theme={null}
{
  "type": "subscribe",
  "subscription": {
    "channel": "orderbook",
    "symbol": "SOL"
  }
}
```

Unsubscribe with the same subscription object:

```json theme={null}
{
  "type": "unsubscribe",
  "subscription": {
    "channel": "orderbook",
    "symbol": "SOL"
  }
}
```

## Supported channels

| Channel       | Subscription fields                      | Response type              |
| ------------- | ---------------------------------------- | -------------------------- |
| `allMids`     | none                                     | `AllMidsData`              |
| `exchange`    | optional `encoding`                      | `ExchangeMessage`          |
| `fundingRate` | `symbol`                                 | `FundingRateMessage`       |
| `orderbook`   | `symbol`, optional `bypassExecutionBand` | `L2BookUpdate`             |
| `traderState` | `authority`, `traderPdaIndex`            | `TraderStateServerMessage` |
| `market`      | `symbol`                                 | `MarketStatsUpdate`        |
| `trades`      | `symbol`                                 | `TradesMessage`            |
| `candles`     | `symbol`, `timeframe`                    | `CandleData`               |

## Control responses

The server confirms successful subscriptions with a `subscriptionConfirmed` message:

```json theme={null}
{
  "type": "subscriptionConfirmed",
  "subscription": {
    "channel": "orderbook",
    "symbol": "SOL"
  }
}
```

Subscription-level errors use `subscriptionError`:

```json theme={null}
{
  "type": "subscriptionError",
  "subscription": {
    "channel": "orderbook",
    "symbol": "SOL"
  },
  "code": "invalid_subscription",
  "message": "invalid subscription"
}
```

Server errors use the `error` channel:

```json theme={null}
{
  "channel": "error",
  "code": 400,
  "error": "unknown channel"
}
```

## Market subscriptions

### Exchange

Use the `exchange` channel to keep local exchange and market-parameter metadata in sync. The server sends an initial snapshot followed by ordered deltas when exchange keys, exchange status, markets, or market parameters change.

```json theme={null}
{
  "type": "subscribe",
  "subscription": {
    "channel": "exchange",
    "encoding": "json"
  }
}
```

The `encoding` field is optional. Omit it to use the default compressed snapshot response:

```json theme={null}
{
  "channel": "exchange",
  "messageType": "encodedSnapshot",
  "version": 1,
  "sequenceNumber": "123",
  "slot": 123456789,
  "slotIndex": 0,
  "reason": "snapshot",
  "encoding": "base64+zstd",
  "payload": "..."
}
```

Set `encoding` to `json` to receive the initial snapshot as JSON. The examples below are abbreviated to show the fields relevant to cache synchronization:

```json theme={null}
{
  "channel": "exchange",
  "messageType": "snapshot",
  "version": 1,
  "sequenceNumber": "123",
  "slot": 123456789,
  "slotIndex": 0,
  "reason": "snapshot",
  "exchange": {
    "programId": "program-pubkey",
    "globalConfig": "global-config-pubkey",
    "active": true,
    "gated": false
  },
  "markets": [
    {
      "symbol": "SOL",
      "assetId": 1,
      "marketStatus": "active",
      "marketPubkey": "market-pubkey",
      "splinePubkey": "spline-pubkey"
    }
  ]
}
```

After the snapshot, apply each `delta` with the next `sequenceNumber` to your local cache. If a sequence number is skipped, resubscribe and rebuild from a fresh snapshot.

```json theme={null}
{
  "channel": "exchange",
  "messageType": "delta",
  "version": 1,
  "sequenceNumber": "124",
  "slot": 123456790,
  "slotIndex": 0,
  "ops": [
    {
      "kind": "marketAdded",
      "market": {
        "symbol": "ETH",
        "assetId": 2,
        "marketStatus": "active",
        "marketPubkey": "market-pubkey",
        "splinePubkey": "spline-pubkey"
      }
    },
    {
      "kind": "marketClosed",
      "symbol": "SOL",
      "previous_market_status": "active",
      "finalized_mark_price": "150000000"
    }
  ]
}
```

Handle exchange deltas as cache mutations:

| Delta kind               | Sync behavior                                                                                            |
| ------------------------ | -------------------------------------------------------------------------------------------------------- |
| `marketAdded`            | Add or replace the market config in the local market map.                                                |
| `marketStatusChanged`    | Update the market's `marketStatus`.                                                                      |
| `marketClosed`           | Mark the market as `closed` and retain the finalized mark price if your client needs settlement context. |
| `marketTombstoned`       | Mark the market as `tombstoned` and stop treating it as tradeable.                                       |
| `marketDeleted`          | Remove the market from the local market map.                                                             |
| `marketParameterUpdated` | Patch the market's risk, funding, fee, cap, or commodity metadata fields from the update payload.        |
| `exchangeStatusChanged`  | Update exchange-level `active`, `gated`, and status feature flags.                                       |
| `exchangeKeysUpdated`    | Replace exchange-level account and authority keys.                                                       |

### All mids

```json theme={null}
{
  "type": "subscribe",
  "subscription": {
    "channel": "allMids"
  }
}
```

```json theme={null}
{
  "channel": "allMids",
  "mids": {
    "SOL": 150.25,
    "BTC": 65000.5
  },
  "slot": 123456789,
  "slotIndex": 0
}
```

### Funding rate

```json theme={null}
{
  "type": "subscribe",
  "subscription": {
    "channel": "fundingRate",
    "symbol": "SOL"
  }
}
```

```json theme={null}
{
  "channel": "fundingRate",
  "symbol": "SOL",
  "funding": 0.0000125
}
```

### Orderbook

Set `bypassExecutionBand` to `true` to receive the full orderbook during commodities after-hours, including price levels outside the tradeable execution band.

```json theme={null}
{
  "type": "subscribe",
  "subscription": {
    "channel": "orderbook",
    "symbol": "SOL",
    "bypassExecutionBand": false
  }
}
```

```json theme={null}
{
  "channel": "orderbook",
  "symbol": "SOL",
  "orderbook": {
    "bids": [[150.25, 100.0], [150.2, 200.0]],
    "asks": [[150.3, 150.0], [150.35, 250.0]],
    "mid": 150.275
  },
  "bypassExecutionBand": false
}
```

### Market stats

```json theme={null}
{
  "type": "subscribe",
  "subscription": {
    "channel": "market",
    "symbol": "SOL"
  }
}
```

```json theme={null}
{
  "channel": "market",
  "symbol": "SOL",
  "openInterest": 1000.0,
  "markPx": 150.1,
  "midPx": 150.12,
  "oraclePx": 150.0,
  "prevDayPx": 148.7,
  "dayNtlVlm": 2500000.0,
  "funding": 0.0000125
}
```

### Trades

```json theme={null}
{
  "type": "subscribe",
  "subscription": {
    "channel": "trades",
    "symbol": "SOL"
  }
}
```

```json theme={null}
{
  "channel": "trades",
  "symbol": "SOL",
  "trades": [
    {
      "slot": "123456789",
      "slotIndex": 5,
      "timestamp": "1775578550",
      "symbol": "SOL",
      "taker": "taker-pubkey",
      "tradeSequenceNumber": "100",
      "side": "bid",
      "baseLotsFilled": "1000",
      "quoteLotsFilled": "150000",
      "feeInQuoteLots": "30",
      "baseAmount": 10.0,
      "quoteAmount": 1500.0,
      "numFills": 2
    }
  ]
}
```

### Candles

Supported timeframes are `1s`, `5s`, `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, and `1d`.

```json theme={null}
{
  "type": "subscribe",
  "subscription": {
    "channel": "candles",
    "symbol": "SOL",
    "timeframe": "1m"
  }
}
```

The server sends candle updates with `channel` set to `candle`:

```json theme={null}
{
  "channel": "candle",
  "symbol": "SOL",
  "timeframe": "1m",
  "candle": {
    "time": 1727181985,
    "low": 149.8,
    "high": 151.5,
    "open": 150.25,
    "close": 150.9,
    "volume": 1234.56,
    "tradeCount": 89
  }
}
```

## Trader subscriptions

### Trader state

```json theme={null}
{
  "type": "subscribe",
  "subscription": {
    "channel": "traderState",
    "authority": "wallet-pubkey",
    "traderPdaIndex": 0
  }
}
```

Trader state messages are either `snapshot` or `delta` payloads.

```json theme={null}
{
  "channel": "traderState",
  "authority": "wallet-pubkey",
  "traderPdaIndex": 0,
  "slot": 123456789,
  "messageType": "snapshot",
  "version": 1,
  "capabilities": {
    "flags": 63,
    "state": "active",
    "capabilities": {
      "placeLimitOrder": { "immediate": true },
      "placeMarketOrder": { "immediate": true },
      "riskIncreasingTrade": { "immediate": true },
      "riskReducingTrade": { "immediate": true },
      "depositCollateral": { "immediate": true },
      "withdrawCollateral": { "immediate": true }
    }
  },
  "makerFeeOverrideMultiplier": 1.0,
  "takerFeeOverrideMultiplier": 1.0,
  "subaccounts": []
}
```

```json theme={null}
{
  "channel": "traderState",
  "authority": "wallet-pubkey",
  "traderPdaIndex": 0,
  "slot": 123456790,
  "messageType": "delta",
  "deltas": [
    {
      "subaccountIndex": 0,
      "sequence": 42,
      "collateral": "1000000",
      "positions": [],
      "orders": [],
      "splines": [],
      "tradeHistory": [],
      "orderHistory": []
    }
  ]
}
```
