> ## 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.

# Fluxo WebSocket (subscrições)

> Subscreva os desportos, ligas, eventos ou mercados que realmente segue, e receba apenas esses.

<Note>
  Os fluxos em tempo real exigem o plano **Sharp**.
</Note>

`wss://api.apinn.io/ws` envia os movimentos de odds tal como o [fluxo SSE](/pt/concepts/streaming), com uma diferença que conta: a ligação é **bidirecional**, pelo que pode dizer ao servidor o que pretende. Sem subscrição recebe todo o book — exatamente o que o fluxo SSE envia.

Passe a sua chave no cabeçalho `X-API-Key`, ou como `?key=A_SUA_CHAVE` no URL (um navegador não pode definir cabeçalhos numa ligação WebSocket).

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

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

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") {
    // estado completo e atual da sua subscrição
    console.log(m.count, "linhas");
  } else if (m.t === "delta") {
    // apenas as linhas que mudaram, dentro do seu âmbito
    for (const row of m.rows) console.log(row.event_id, row.market, row.odds1, row.odds2);
  }
});
```

## Subscrever

Envie `{"op": "subscribe", ...}` com qualquer combinação dos filtros abaixo. São cumulativos: uma linha tem de satisfazer todos os filtros que definir.

| Filtro    | Tipo               | Exemplo                                        |
| --------- | ------------------ | ---------------------------------------------- |
| `sports`  | ids de desporto    | `{"sports": [29, 33]}`                         |
| `leagues` | ids de liga        | `{"leagues": [2436]}`                          |
| `events`  | ids de evento      | `{"events": [1632682788]}`                     |
| `markets` | nomes de mercado   | `{"markets": ["moneyline", "totals"]}`         |
| `periods` | números de período | `{"periods": [0]}` — apenas tempo regulamentar |

Uma nova subscrição substitui a anterior e devolve um snapshot atualizado. `{"op": "unsubscribe"}` devolve-lhe o book completo, e `{"op": "ping"}` responde `{"t": "pong"}`.

## Mensagens do servidor

| `t`        | Conteúdo                                        | Significado                                                                       |
| ---------- | ----------------------------------------------- | --------------------------------------------------------------------------------- |
| `hello`    | `{ subscription }`                              | Enviado na ligação e após cada alteração de subscrição; reflete o que está ativo. |
| `snapshot` | `{ count, rows }`                               | Estado completo **da sua subscrição**, enviado logo após subscrever.              |
| `delta`    | `{ rows, specials, removed, removed_specials }` | O que mudou desde a mensagem anterior — e o que desapareceu.                      |
| `pong`     | `{ ts }`                                        | Resposta a `ping`.                                                                |

Cada delta traz também um `seq`, incrementado a cada difusão. Um cliente sem subscrição recebe todos os números seguidos: uma falha indica uma mensagem perdida. Um cliente subscrito a um âmbito verá falhas normalmente — as difusões que não lhe diziam respeito.

## Remoções

`removed` e `removed_specials` listam as séries que já não existem: um jogo terminado, um mercado fechado. **Apague-as do seu book.** Um cliente que as ignora continua a servir odds de mercados desaparecidos: medido ao longo de nove horas, isso representa cerca de 2,5 % do book, e não para de crescer.

Uma entrada removida traz apenas o que identifica a série, sem preços: `event_id`, `period`, `market`, `line` para as odds; `event_id`, `special_id`, `period`, `contestant_name`, `handicap` para os specials. São filtradas pela sua subscrição como tudo o resto.

As linhas têm a mesma forma que em `/api/odds`: `event_id`, `period`, `market`, `line`, as odds (`odds1`/`odds0`/`odds2`), as odds justas (`todds*`), `status` e `timestamp` — a hora da **última alteração de preço**, não a do envio.

## Porquê subscrever

Filtrar não é apenas conveniência. Medido no book em direto, só o futebol representa cerca de 40 % dos movimentos, o moneyline em tempo regulamentar cerca de 49 %, e um jogo isolado é insignificante. Um cliente que segue meia dúzia de jogos passa de dezenas de milhares de linhas por hora para algumas dezenas.

<Tip>
  Tal como o fluxo SSE, a ligação conta como **1 pedido**, no momento em que se liga. Aquilo que subscreve muda o volume recebido, não o preço.
</Tip>

<Note>
  As linhas de odds trazem `event_id`, `period` e `market`, mas não o desporto nem a liga — estes são resolvidos através dos fixtures. Um evento ausente do índice de fixtures não satisfaz um filtro `sports` ou `leagues`; filtre por `events` se precisar dele de imediato.
</Note>
