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

# Stream em tempo real

> Assine eventos ao vivo da aplicação por meio de um stream Server-Sent Events (SSE).

`app.realtime()` abre um stream [Server-Sent Events](https://developer.mozilla.org/docs/Web/API/Server-sent_events) e retorna a `Response` bruta. O SDK **não** faz parsing dos frames SSE — ele entrega o stream para que você integre no seu próprio loop de eventos.

## Limites de conexão

* Cada conexão dura até **10 minutos** (seu TTL). O servidor executa **uma reconexão interna transparente** quando o TTL é atingido, mas o cliente ainda precisa reconectar quando o stream termina.
* Uma única conta mantém no máximo **5 conexões simultâneas**, com um limite adicional por aplicação. Exceder qualquer um dos limites falha com `code: "REALTIME_MAX_CONNECTIONS"`.
* `app.realtime()` retorna a `Response` bruta; seu `body` é o stream SSE.

## Formato dos eventos

O stream emite dois tipos de frames:

* `event: system` — mensagens de ciclo de vida da conexão, como `REALTIME_CONNECTING`, `REALTIME_TIMEOUT`, etc.
* `event: message` — payload JSON da aplicação

## Consumindo o stream

```typescript theme={null}
import { SquareCloudAPI } from "@squarecloud/api";

const api = new SquareCloudAPI(process.env.SQUARE_API_KEY!);
const app = await api.applications.fetch("abc123def456abc123def456");

const response = await app.realtime();

if (!response.body) {
    throw new Error("Stream sem body");
}

const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
let buffer = "";

while (true) {
    const { value, done } = await reader.read();
    if (done) break;

    buffer += value;

    // Frames SSE são separados por \n\n
    let separator = buffer.indexOf("\n\n");
    while (separator !== -1) {
        const rawFrame = buffer.slice(0, separator);
        buffer = buffer.slice(separator + 2);
        separator = buffer.indexOf("\n\n");

        const event = parseSSE(rawFrame);
        if (!event) continue;

        if (event.name === "system") {
            console.log(`[system] ${event.data}`);
            continue;
        }

        try {
            const payload = JSON.parse(event.data);
            console.log("[message]", payload);
        } catch {
            console.log("[message]", event.data);
        }
    }
}

function parseSSE(frame: string): { name: string; data: string } | null {
    let name = "message";
    let data = "";

    for (const line of frame.split("\n")) {
        if (line.startsWith("event:")) name = line.slice(6).trim();
        else if (line.startsWith("data:")) data += line.slice(5).trim();
    }

    return data ? { name, data } : null;
}
```

<Tip>
  Cada chamada a `app.realtime()` retorna uma `Response` nova. Para se manter conectado além do timeout de 10 minutos do servidor, reconecte quando o stream encerrar.
</Tip>
