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

# Realtime protocol

> Connect to Tayho WebSockets, subscribe to allowlisted channels, and recover with snapshots and replay.

# Realtime protocol

Tayho realtime delivers snapshots and at-least-once events. Use it to refresh interfaces quickly,
while REST reads and receipt status remain the durable lifecycle authority.

## Connect

1. Send `POST /v1/realtime/tickets` with an API key granting `realtime`.
2. Open `wss://<api-host>/v1/ws?ticket=<ticket>` before `expiresAt`.
3. Use each ticket once. Obtain a new one for every connection or reconnect.
4. Wait for `hello`, then send `subscribe`.

Never put the API key in the WebSocket URL. A consumed, expired, or invalid ticket is rejected.

```json theme={null}
{
  "type": "subscribe",
  "requestId": "subscribe-portfolio-1",
  "channels": [
    "market.price:7",
    "trader.positions:0x1111111111111111111111111111111111111111"
  ]
}
```

The server returns an authoritative `snapshot` for a new channel, then a `subscribed`
acknowledgement. Events can overlap state already represented by the snapshot.

## Channel catalog

| Family    | Allowed values                                                                                                                           |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Protocol  | `protocol.config`, `vault.state`, `staking.state`, `system.status`                                                                       |
| Market    | `market.{state\|price\|trades\|funding\|liquidity\|oracle}:<marketId>`                                                                   |
| Trader    | `trader.{positions\|portfolio\|balances\|activity\|orders\|trades\|funding\|settlements\|sessions\|vault\|rewards\|transfers}:<address>` |
| Lifecycle | `intent:<orderHash>`, `action:<actionHash>`, `transaction:<txHash>`                                                                      |

Addresses and hashes are canonicalized to lowercase. Market IDs are canonical unsigned decimal
values. Protected `intent:` and `action:` snapshots require the matching receipt in the
`capabilities` object:

```json theme={null}
{
  "type": "subscribe",
  "requestId": "subscribe-action-1",
  "channels": [
    "action:0x1111111111111111111111111111111111111111111111111111111111111111"
  ],
  "capabilities": {
    "action:0x1111111111111111111111111111111111111111111111111111111111111111": "receipt-capability"
  }
}
```

## Delivery rules

An `event` includes a stable `eventId`, one or more channels, a stream `sequence`, source,
timestamp, optional checkpoint, and domain data. Delivery is at least once:

* deduplicate by `eventId`;
* apply domain versions or sequences monotonically;
* persist only the latest sequence per subscribed channel; and
* reconcile from REST after any uncertain period.

The server sends `heartbeat`; clients can send `ping` and receive `pong`. Client message types are
`subscribe`, `unsubscribe`, and `ping`. Server message types are `hello`, `snapshot`, `event`,
`subscribed`, `unsubscribed`, `heartbeat`, `pong`, `resync_required`, and `error`.

## Reconnect and resume

On reconnect, obtain a new ticket and include each saved channel cursor:

```json theme={null}
{
  "type": "subscribe",
  "requestId": "resume-portfolio-2",
  "channels": ["market.price:7"],
  "resumeFrom": {
    "market.price:7": "1784203200000-0"
  }
}
```

The server replays later matching events when they remain available. If the replay has a gap or is
too large, it sends `resync_required` and follows with a fresh snapshot. Replace local channel
state from that snapshot and continue with its sequence.

Use exponential backoff with jitter for repeated connection failures. The Tayho SDK automatically
obtains fresh tickets, reconnects, resumes channel cursors, and keeps a rolling event-ID
deduplication window.

## Errors and closure

Protocol errors include a stable code and can identify the affected request or channel.
`INVALID_CHANNEL`, `SUBSCRIPTION_LIMIT`, `CAPABILITY_REQUIRED`, `CAPABILITY_INVALID`, and
`REALTIME_UNAVAILABLE` require the caller to correct input or reconcile. Connection or message
admission failures can close the socket; respect the HTTP or close reason and avoid reconnect
storms.

The complete message schemas are available in the generated realtime reference.
