# Resumable WebSocket streams The `/orders`, `/accounting`, and `/events` streams use the same resume protocol. - Data-frame `seq` values are strictly increasing in delivery order but are **not guaranteed to be contiguous**. Filters and retention can produce valid gaps. A gap alone is not evidence of data loss and must not trigger a reconnect. - Drop a data frame when `seq <= last_applied`; otherwise apply it atomically with persisting the new `last_applied`. - `heartbeat` and `backlog_end` do not advance the data sequence; they repeat the latest relevant `seq`. - Reconnect with `since=last_applied`. The server may replay that sequence inclusively, then sends `backlog_end` and continues live delivery. The duplicate check makes this safe. - Replay is limited to messages from the preceding **one hour**. Reconnect promptly and do not rely on older history being available. - `resume_too_old` followed by close code `4009` means the requested position is outside the supported replay window or is otherwise unavailable. - Close code `4008` means the client is reading too slowly. Keep socket reads independent from slower business processing and enforce bounded local queues. - Use heartbeat `interval_sec` for liveness detection; reconnect if no frame arrives within the client-defined timeout. Available URL filters differ by stream: - `/orders`: repeatable `market`, `event_id`, and `account_id`. - `/accounting`: repeatable `market` and `account_id`. - `/events`: repeatable `event_id`, `market_id`, and `lang`. Changing filters changes which sequence numbers are delivered and invalidates assumptions tied to the previous subscription. Persist a resume position together with its filter set.