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

# Flusso WebSocket (sottoscrizioni)

> Sottoscrivi gli sport, i campionati, gli eventi o i mercati che segui davvero, e ricevi solo quelli.

<Note>
  I flussi in tempo reale richiedono il piano **Sharp**.
</Note>

`wss://api.apinn.io/ws` invia i movimenti delle quote come il [flusso SSE](/it/concepts/streaming), con una differenza che conta: la connessione è **bidirezionale**, quindi puoi dire al server che cosa vuoi. Senza sottoscrizione ricevi tutto il book — esattamente ciò che invia il flusso SSE.

Passa la tua chiave nell'header `X-API-Key`, oppure come `?key=LA_TUA_CHIAVE` nell'URL (un browser non può impostare header su una connessione WebSocket).

```javascript Node.js theme={null}
import WebSocket from "ws";

const sock = new WebSocket("wss://api.apinn.io/ws?key=LA_TUA_CHIAVE");

sock.on("open", () => {
  sock.send(JSON.stringify({ op: "subscribe", sports: [29], markets: ["moneyline"] }));
});

sock.on("message", (buf) => {
  const m = JSON.parse(buf);
  if (m.t === "snapshot") {
    // stato completo e attuale della tua sottoscrizione
    console.log(m.count, "righe");
  } else if (m.t === "delta") {
    // solo le righe cambiate, nel tuo perimetro
    for (const row of m.rows) console.log(row.event_id, row.market, row.odds1, row.odds2);
  }
});
```

## Sottoscrivere

Invia `{"op": "subscribe", ...}` con qualsiasi combinazione dei filtri seguenti. Sono cumulativi: una riga deve soddisfare tutti i filtri impostati.

| Filtro    | Tipo              | Esempio                                       |
| --------- | ----------------- | --------------------------------------------- |
| `sports`  | id sport          | `{"sports": [29, 33]}`                        |
| `leagues` | id campionato     | `{"leagues": [2436]}`                         |
| `events`  | id evento         | `{"events": [1632682788]}`                    |
| `markets` | nomi di mercato   | `{"markets": ["moneyline", "totals"]}`        |
| `periods` | numeri di periodo | `{"periods": [0]}` — solo tempi regolamentari |

Una nuova sottoscrizione sostituisce la precedente e restituisce uno snapshot aggiornato. `{"op": "unsubscribe"}` ti riporta al book completo, e `{"op": "ping"}` risponde `{"t": "pong"}`.

## Messaggi del server

| `t`        | Contenuto                                       | Significato                                                                               |
| ---------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `hello`    | `{ subscription }`                              | Inviato alla connessione e dopo ogni cambio di sottoscrizione; riflette ciò che è attivo. |
| `snapshot` | `{ count, rows }`                               | Stato completo **della tua sottoscrizione**, inviato subito dopo la sottoscrizione.       |
| `delta`    | `{ rows, specials, removed, removed_specials }` | Ciò che è cambiato dal messaggio precedente — e ciò che è sparito.                        |
| `pong`     | `{ ts }`                                        | Risposta a `ping`.                                                                        |

Ogni delta porta anche un `seq`, incrementato a ogni diffusione. Un client senza sottoscrizione riceve tutti i numeri di seguito: un buco segnala un messaggio perso. Un client sottoscritto a un perimetro vedrà normalmente dei buchi — le diffusioni che non lo riguardavano.

## Rimozioni

`removed` e `removed_specials` elencano le serie che non esistono più: una partita finita, un mercato chiuso. **Cancellale dal tuo book.** Un client che le ignora continua a servire quote su mercati spariti: misurato su nove ore, si tratta di circa il 2,5 % del book, e continua a crescere.

Una voce rimossa porta solo ciò che identifica la serie, non i prezzi: `event_id`, `period`, `market`, `line` per le quote; `event_id`, `special_id`, `period`, `contestant_name`, `handicap` per gli specials. Sono filtrate dalla tua sottoscrizione come tutto il resto.

Le righe hanno la stessa forma di `/api/odds`: `event_id`, `period`, `market`, `line`, le quote (`odds1`/`odds0`/`odds2`), le quote eque (`todds*`), `status` e `timestamp` — l'ora dell'**ultima variazione di prezzo**, non quella dell'invio.

## Perché sottoscrivere

Filtrare non è solo comodità. Misurato sul book in diretta, il solo calcio rappresenta circa il 40 % dei movimenti, il moneyline sui tempi regolamentari circa il 49 %, e una singola partita è trascurabile. Un client che segue una manciata di partite passa da decine di migliaia di righe all'ora a poche decine.

<Tip>
  Come il flusso SSE, la connessione conta come **1 richiesta**, nel momento in cui ti connetti. Ciò che sottoscrivi cambia il volume ricevuto, non il prezzo.
</Tip>

<Note>
  Le righe delle quote portano `event_id`, `period` e `market`, ma non lo sport né il campionato — questi si risolvono tramite i fixtures. Un evento assente dall'indice dei fixtures non soddisfa un filtro `sports` o `leagues`; filtra su `events` se ti serve subito.
</Note>
