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

# Realtime

> Como receber eventos em tempo real com o SDK PHP via WebSocket

Use `$vzaps->events()` para receber eventos da instância em tempo real, sem expor URL pública.

Para callbacks HTTP, veja [Webhooks](/pt-BR/sdk/php/webhooks).

<Note>
  Em PHP, realtime deve rodar em CLI, worker, daemon, Laravel Command, Symfony Console ou consumidor de fila. Não mantenha um WebSocket aberto dentro do ciclo de vida normal de uma request HTTP.
</Note>

## Eventos comuns

| Evento                    | Descrição                                     |
| ------------------------- | --------------------------------------------- |
| `Message`                 | Nova mensagem recebida ou evento de mensagem. |
| `ReadReceipt`             | Atualização de leitura/entrega.               |
| `Presence`                | Presença do usuário.                          |
| `ChatPresence`            | Presença em chat.                             |
| `HistorySync`             | Sincronização de histórico.                   |
| `Connected`               | Instância conectada ao WhatsApp.              |
| `Disconnected`            | Instância desconectada.                       |
| `GroupParticipantsAdd`    | Participantes adicionados em grupo.           |
| `GroupParticipantsRemove` | Participantes removidos de grupo.             |
| `All`                     | Todos os eventos assinados.                   |

## Instalar transporte WebSocket

```bash theme={null}
composer require textalk/websocket
```

Também é possível passar `webSocketFactory` no `VZapsClient` para testes ou transporte próprio.

## Assinar realtime

```php theme={null}
use VZaps\Sdk\Models\Realtime\EventSubscribeRequest;
use VZaps\Sdk\Models\Realtime\VZapsEventType;

$subscription = $vzaps->events()->subscribe(new EventSubscribeRequest(
    instanceId: 'VZ...',
    instanceToken: 'instance-token',
    events: [
        VZapsEventType::Message,
        VZapsEventType::ReadReceipt,
        VZapsEventType::Connected,
        VZapsEventType::Disconnected,
    ],
    reconnect: true,
    maxRetries: 10,
    retryDelayMs: 1000,
));
```

**Retorno:** `EventSubscription` — objeto com `on()`, `close()` e reconexao automatica quando configurada.

Opções:

| Campo           | Tipo                             | Obrigatório | Descrição                                                         |
| --------------- | -------------------------------- | ----------- | ----------------------------------------------------------------- |
| `instanceId`    | `string`                         | Sim         | Instância que será acompanhada.                                   |
| `instanceToken` | `string`                         | Sim         | Token da instância.                                               |
| `events`        | `VZapsEventType[]` ou `string[]` | Não         | Lista de eventos. Se omitido, usa eventos assinados na instância. |
| `reconnect`     | `boolean`                        | Não         | Reconectar automaticamente. Padrão: `true`.                       |
| `maxRetries`    | `int`                            | Não         | Máximo de tentativas.                                             |
| `retryDelayMs`  | `int`                            | Não         | Delay entre tentativas.                                           |
| `lastEventId`   | `string`                         | Não         | Cursor para retomada.                                             |

## Registrar handlers

```php theme={null}
$subscription->on(VZapsEventType::Message, function ($event): void {
    echo $event->id . PHP_EOL;
    echo $event->instanceId . PHP_EOL;
    print_r($event->data);
});

$subscription->on(VZapsEventType::All, function ($event): void {
    echo 'Evento recebido: ' . $event->type . PHP_EOL;
});

$subscription->onError(function ($error): void {
    error_log('Erro realtime: ' . $error->getMessage());
});
```

## Fechar assinatura

```php theme={null}
$subscription->close();
```

**Retorno:** `Promise<void>` apos fechar o WebSocket.

Em processos CLI:

```php theme={null}
if (function_exists('pcntl_signal')) {
    pcntl_signal(SIGINT, function () use ($subscription): void {
        $subscription->close();
        exit(0);
    });
}

$subscription->awaitClose();
```

## Envelope do evento

Cada evento recebido pelo SDK tem este formato:

```json theme={null}
{
  "id": "evt_01J...",
  "type": "Message",
  "instance_id": "VZ...",
  "created_at": "2026-06-23T22:57:17.000Z",
  "data": {
    "type": "Message",
    "media_url": "https://cdn.example.com/media/image.jpg"
  }
}
```

Campos:

| Campo            | Descrição                                                                                  |
| ---------------- | ------------------------------------------------------------------------------------------ |
| `id`             | Identificador do evento. Use para deduplicação.                                            |
| `type`           | Tipo do evento.                                                                            |
| `instance_id`    | Instância origem no payload original.                                                      |
| `created_at`     | Data de criação do evento no payload original.                                             |
| `data`           | Payload do evento.                                                                         |
| `data.media_url` | URL de mídia quando o evento recebido contém mídia e a plataforma disponibiliza o arquivo. |

No objeto PHP `VZapsEvent`, os atalhos principais ficam como `$event->id`, `$event->type`, `$event->instanceId`, `$event->createdAt`, `$event->data` e `$event->raw`.

## Entrega e ack

A entrega é **at-least-once**. Seu app deve tratar eventos de forma idempotente.

Depois que o handler termina, o SDK envia ack automaticamente.

Recomendações:

* salve `event.id` se sua automação executa efeitos externos;
* ignore eventos já processados;
* use `lastEventId` ao reconectar se quiser reduzir lacunas;
* mantenha handlers rápidos e mova trabalhos longos para sua própria fila.

## Realtime ou webhook?

| Cenário                                    | Recomendação |
| ------------------------------------------ | ------------ |
| Bot, dashboard ou app com consumo imediato | Realtime     |
| Backend com URL pública e pipeline HTTP    | Webhook      |
| Não quer expor URL pública                 | Realtime     |
| Quer reprocessar entregas via logs         | Webhook      |
