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

# WebSocket Session

> Maintain continuity across brief WebSocket disconnections, with automatic backfill of missed order events.

Transient network instability, brief client-side hiccups, and other short-lived connectivity disruptions can interrupt a WebSocket connection for a few seconds at a time. A WebSocket session lets a reconnecting client be recognized as the same client picking up where it left off — enabling backfill, which automatically recovers any order events missed during the gap instead of requiring a full reconciliation from scratch.

## Scope

A session is available on the Order Creation Stream only — no other stream is session-aware yet.

| Product    | Subscription    | Stream                                                                       |
| ---------- | --------------- | ---------------------------------------------------------------------------- |
| Perpetuals | `orders`        | [Order Creation Stream](/latest/perps/websocket-api/order-creation-stream)   |
| Options    | `optionsOrders` | [Order Creation Stream](/latest/options/websocket-api/order-creation-stream) |

## Starting a Session

Add an optional `sessionId` (UUID) query parameter to the connection URL. Generate one value and reuse it across reconnects to keep the same session:

```
wss://ws.sandbox.rails.xyz?product=perpetuals&market=BTC-USDT&subscriptions=orders&sessionId=d785d51c-054e-4e33-9738-92d04ede9fab
```

Omit `sessionId` to skip starting a session — the connection behaves as a one-off, with no missed messages backfilled and no [Summary Message](#summary-message) sent.

## Resumed vs. Fresh Sessions

Whether a session continued or started over is reported as a `resumed` field on the [Summary Message](#summary-message).

A session can be resumed for up to **1 minute** after a disconnect. Reconnecting with the same `sessionId` within that window continues the session: `resumed` is `true`, and the backfill covers whatever was missed since the last message delivered on the prior connection.

`resumed` is `false` when either:

* The connection uses a `sessionId` that hasn't been seen before, or
* The connection reuses a `sessionId` from a prior session, but reconnects after the 1-minute window has elapsed

In both cases there is no prior position to resume from, so nothing is backfilled. Reconcile local order state from scratch using the REST API or `emit` requests on the relevant streams.

## Backfill

When `sessionId` is supplied and the connection is subscribed to the Order Creation Stream, backfill runs automatically on connect: any missed messages are delivered first, followed by a `sessionBackfill` message summarizing the session.

### Summary Message

See [Order Creation Stream](/latest/perps/websocket-api/order-creation-stream) (or the [Options equivalent](/latest/options/websocket-api/order-creation-stream)) for the exact message shape.

| Field               | Description                                                                                                                                       |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sessionId`         | Echoes the `sessionId` supplied on the connection                                                                                                 |
| `resumed`           | Whether this session continued a live position (`true`) or started fresh (`false`) — see [Resumed vs. Fresh Sessions](#resumed-vs-fresh-sessions) |
| `from`              | Start of the backfill window, as a Unix timestamp (ms). `0` when `resumed` is `false`                                                             |
| `to`                | End of the backfill window, as a Unix timestamp (ms)                                                                                              |
| `events`            | Total number of missed messages backfilled across all markets (or contracts, for Options)                                                         |
| `backfilledMarkets` | Markets (or contracts) whose missed messages were fully backfilled                                                                                |
| `expiredMarkets`    | Markets (or contracts) that exceeded the [Limits](#limits) — nothing was backfilled for them                                                      |

### Limits

Backfill is capped at **500 missed events** per market (or per contract, for Options). For each market or contract with at least one missed event:

* If 500 or fewer events accumulated while disconnected, all of them are backfilled and the market (or contract) is listed in `backfilledMarkets`
* If more than 500 accumulated, none are backfilled and the market (or contract) is listed in `expiredMarkets` instead — reconcile that market's order state from scratch via the REST API or `emit` requests on the relevant streams

No silent gaps: every market or contract with missed activity appears in exactly one of the two arrays.
