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

> How to receive real-time events with the Go SDK over WebSocket

Use `client.Events` to receive instance events in real time without exposing a public URL.

For HTTP callbacks, see [Webhooks](/en/sdk/go/webhooks).

## Common events

| Event                     | Description                            |
| ------------------------- | -------------------------------------- |
| `Message`                 | New incoming message or message event. |
| `ReadReceipt`             | Read/delivery update.                  |
| `Presence`                | User presence.                         |
| `ChatPresence`            | Chat presence.                         |
| `HistorySync`             | History synchronization.               |
| `Connected`               | Instance connected to WhatsApp.        |
| `Disconnected`            | Instance disconnected.                 |
| `GroupParticipantsAdd`    | Participants added to group.           |
| `GroupParticipantsRemove` | Participants removed from group.       |
| `All`                     | All subscribed events.                 |

Use the exported constants: `vzaps.EventMessage`, `vzaps.EventConnected`, etc.

## Subscribe to realtime

```go theme={null}
sub, err := client.Events.Subscribe(ctx, vzaps.EventSubscribeRequest{
	InstanceID:    "VZ...",
	InstanceToken: "instance-token",
	Events:        []vzaps.EventType{vzaps.EventMessage, vzaps.EventReadReceipt, vzaps.EventConnected, vzaps.EventDisconnected},
	Reconnect:     true,
	MaxRetries:    10,
	RetryDelay:    time.Second,
})
```

**Return:** `EventSubscription` — object with `on()`, `close()`, and automatic reconnect when configured.

Options:

| Field           | Type            | Required | Description                                                     |
| --------------- | --------------- | -------- | --------------------------------------------------------------- |
| `InstanceID`    | `string`        | Yes      | Instance to watch.                                              |
| `InstanceToken` | `string`        | Yes      | Instance token.                                                 |
| `Events`        | `[]EventType`   | No       | Event list. If omitted, uses events subscribed on the instance. |
| `Reconnect`     | `bool`          | No       | Reconnect automatically. Default: `true`.                       |
| `MaxRetries`    | `int`           | No       | Maximum retry attempts.                                         |
| `RetryDelay`    | `time.Duration` | No       | Delay between retries.                                          |
| `LastEventID`   | `string`        | No       | Resume cursor.                                                  |

Pass the same `context.Context` used for the subscribe call; cancellation stops reconnection attempts.

## Register handlers

```go theme={null}
sub.OnOpen(func() {
	fmt.Println("Realtime connected")
})

sub.On(vzaps.EventMessage, func(event vzaps.Event) {
	fmt.Println(event.ID)
	fmt.Println(event.InstanceID)
	fmt.Printf("%#v\n", event.Data)
})

sub.On(vzaps.EventAll, func(event vzaps.Event) {
	fmt.Println("Received event:", event.Type)
})

sub.OnError(func(err error) {
	fmt.Println("Realtime error:", err)
})
```

## Close subscription

```go theme={null}
sub.Close()
```

**Return:** `Promise<void>` after the WebSocket closes.

In long-running processes:

```go theme={null}
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt)
<-sigCh
sub.Close()
```

## Event envelope

Every event received by the SDK has this shape:

```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"
  }
}
```

Fields:

| Field            | Description                                                                          |
| ---------------- | ------------------------------------------------------------------------------------ |
| `id`             | Event identifier. Use for deduplication.                                             |
| `type`           | Event type.                                                                          |
| `instance_id`    | Source instance.                                                                     |
| `created_at`     | Event creation date.                                                                 |
| `data`           | Event payload.                                                                       |
| `data.media_url` | Media URL when the incoming event contains media and the platform provides the file. |

In Go, access fields via `event.ID`, `event.Type`, `event.InstanceID`, `event.CreatedAt`, and `event.Data`.

## Delivery and ack

Delivery is **at-least-once**. Your app should process events idempotently.

After the handler finishes, the SDK automatically sends an ack.

Recommendations:

* store `event.ID` if your automation performs external effects;
* ignore events that were already processed;
* use `LastEventID` when reconnecting if you want to reduce gaps;
* keep handlers fast and move long-running work to your own queue.

## Realtime or webhook?

| Scenario                                          | Recommendation |
| ------------------------------------------------- | -------------- |
| Bot, dashboard, or app with immediate consumption | Realtime       |
| Backend with public URL and HTTP pipeline         | Webhook        |
| Do not want to expose a public URL                | Realtime       |
| Need to reprocess deliveries via logs             | Webhook        |
