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

# WebSocket em tempo real

> Assine atualizações de estado ao vivo via WebSocket

# WebSocket em tempo real

Para receber **atualizações ao vivo** (sem polling) das mudanças de estado das entidades, conecte-se ao endpoint WebSocket do Portal.

## Endpoint

```
wss://portal.unicontrol.me/v1/websocket
```

## Autenticação

O WebSocket usa um fluxo de **autenticação em duas etapas**: primeiro você conecta, depois envia uma mensagem `auth` com o token.

<Warning>
  O WebSocket atual aceita **OAuth access token** (JWT do Logto). PAT (`pat_...`) **não** funciona neste endpoint. Para integrações via WebSocket use o fluxo OAuth oficial — entre em contato com o suporte para receber as credenciais OAuth client.
</Warning>

## Fluxo básico (JavaScript)

```javascript theme={null}
const ws = new WebSocket("wss://portal.unicontrol.me/v1/websocket");

ws.onopen = () => {
  ws.send(JSON.stringify({
    type: "auth",
    access_token: SEU_ACCESS_TOKEN_OAUTH
  }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  console.log("recebido:", msg);
};

// Heartbeat — envie um ping a cada 30s para manter a conexao viva
setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ type: "ping" }));
  }
}, 30_000);
```

## Tipos de mensagem

### Enviadas pelo cliente

| Tipo   | Quando                    | Payload                    |
| ------ | ------------------------- | -------------------------- |
| `auth` | Logo após a conexão abrir | `{ access_token: string }` |
| `ping` | A cada 30s (heartbeat)    | —                          |

### Recebidas do servidor

| Tipo            | Quando                                       | Payload                               |
| --------------- | -------------------------------------------- | ------------------------------------- |
| `pong`          | Resposta ao ping                             | —                                     |
| `state_changed` | Estado de qualquer entidade do usuário mudou | `{ entity_id, old_state, new_state }` |

## Quando NÃO usar WebSocket

* Você so precisa do **estado atual** uma vez — use `/v1/states/{entity_id}`.
* Você quer histórico — use `/v1/history`.
* Você roda em ambiente sem WebSocket persistente (lambda, edge function) — prefira polling ou webhooks de saida.

## Reconexao e robustez

WebSockets caem. Sua integração deve:

1. **Reconectar com backoff exponencial** ao perder conexão.
2. **Re-autenticar** após a reconexao.
3. **Re-sincronizar estado**: depois de reconectar, busque `/v1/entities/states` para não perder mudanças que ocorreram durante o gap.

```javascript theme={null}
function connect(retry = 0) {
  const ws = new WebSocket("wss://portal.unicontrol.me/v1/websocket");

  ws.onopen = () => {
    ws.send(JSON.stringify({ type: "auth", access_token: TOKEN }));
    syncStates(); // GET /v1/entities/states
    retry = 0;
  };

  ws.onclose = () => {
    const delay = Math.min(30_000, 1000 * 2 ** retry);
    setTimeout(() => connect(retry + 1), delay);
  };
}
```

<Info>
  Para uso massivo (sistemas multi-tenant, dashboards de muitos clientes), considere uma camada própria de cache que assina o WebSocket uma vez por conta e revende as atualizações aos seus clientes — em vez de cada cliente abrir sua própria conexão.
</Info>
