---
title: "client.liveEvents()"
description: "Every method in this namespace: its signature, its parameters, what it returns and an example."
url: "https://nextmail.sh/docs/java/reference/live-events"
area: "Java"
category: "Reference"
---

# client.liveEvents()

Every method in this namespace: its signature, its parameters, what it returns and an example.

## Methods

Follow the mailbox as it changes, without polling: one event each time a message arrives or is sent and each time a conversation changes or is deleted, resumed where it left off after a dropped connection.

### `liveEvents().stream`

Follow the mailbox as it changes

```java
LiveEventStream stream(RequestOptions options)
```

Opens the live event stream, `GET /live-events` as server-sent events, and returns a `LiveEventStream` that yields one event at a time for as long as you read it: `message.received` when a message is filed for an address, `message.sent` when a message sent from an address is filed in its Sent folder, `thread.changed` when a conversation gains or loses labels (read, starred, archived, moved, snoozed or labelled), `thread.deleted` when one is deleted for good, and `message.status_changed` when the delivery of an email sent from an address moves on, with its `status`: `delivered`, `delivery_delayed`, `bounced`, `complained`, `failed`, `suppressed` or `cancelled`. The types are in `sh.nextmail.constants.LiveEventTypes` and the statuses in `sh.nextmail.constants.LiveSendStatuses`. Each event is a map with `id`, `type`, `occurredAt` and `data`, where `data.addresses` names the addresses it concerns and `threadId` and `messageId` the conversation and the message, where there is one. No content travels in an event, so read the conversation with `threads().get` or the message with `threads().getMessage` when you need it.

The stream never ends by itself. The server closes it after 30 minutes, when the credential stops being valid, or when the connection drops, and the stream opens it again and resumes where it left off through `Last-Event-ID`: at once after the server closes it, and with backoff after a failure. When the server can no longer replay from that point, which happens once the event is more than 10 minutes or 1,000 events back, the stream yields a `reset` event, whose `type` is `LiveEventStream.RESET` and whose `data.reason` is `expired` or `unknown`, before the next events: anything may have changed in between, so list again what you keep in sync.

A `LiveEventStream` is an `Iterator` and an `Iterable` of maps, so a `for` loop walks it, and it is `AutoCloseable`, so open it in a try-with-resources block. Break out of the loop or call `close()` to close the connection. `close()` works from any thread, and interrupting the thread that reads the stream closes it too. `stream()` returns it as a `java.util.stream.Stream` that closes it when closed, and `lastEventId()` returns the id it would resume after, to pass as `lastEventId` to a later stream.

A key or an app limited to particular addresses gets only the events of the addresses it reaches, enforced on the server for every event.

Scopes: `threads:read`.

**Parameters**

- `options.types` (`String or List<String>`): Only these kinds of event: `message.received`, `message.sent`, `thread.changed`, `thread.deleted` and `message.status_changed`, as in `sh.nextmail.constants.LiveEventTypes`. A list is sent comma separated. Left out, all of them. A `reset` is always delivered.
- `options.address` (`String`): Only the events of this address. One the key does not reach delivers nothing rather than failing.
- `options.lastEventId` (`String`): Resume after this event id, one an earlier stream yielded or returned from `lastEventId()`. It is sent as the `Last-Event-ID` header. Left out, the stream starts with what happens from now on.
- `options.apiKey` (`String`): Overrides the client's API key for this stream only, on every reconnection.

**Returns**

A `LiveEventStream` that yields each event as a map with `id`, `type`, `occurredAt` and `data`. `data` has `addresses`, `threadId` and `messageId`, and by type `labelIds` (received), `emailId` (sent), `addedLabelIds` and `removedLabelIds` (changed), or `emailId`, `status` and `recipients` (status changed, where `threadId` may be null). A reset yields a map with `id`, `type` set to `reset`, `occurredAt` and `data` holding `reason`.

**Example**

```java
try (LiveEventStream events = client.liveEvents().stream(RequestOptions.of("types", List.of(LiveEventTypes.MESSAGE_RECEIVED)))) {
    for (Map<String, Object> event : events) {
        if (LiveEventStream.RESET.equals(event.get("type"))) {
            System.out.println("Resync: the stream could not resume");

            continue;
        }

        Map<?, ?> data = (Map<?, ?>) event.get("data");
        Map<String, Object> thread = client.threads().get((String) data.get("threadId"));

        System.out.println(data.get("addresses") + " " + thread.get("id"));

        break;
    }
}
```

**Notes**

- One key, app or session holds at most 5 open streams, and a workspace at most 50. Past that the stream is refused with 429 `too_many_streams`, which it retries.
- The server sends a keepalive every 25 seconds and a `retry` hint of 3 seconds. Events are kept for resuming for 10 minutes and at most 1,000 per workspace.
- A network failure, a 408, a 429 and a 5xx answer are retried for as long as you read, waiting about a second at first and doubling up to 30 seconds, or longer when `Retry-After` asks, and the client's `maxRetries` does not limit it. When no byte arrives for 60 seconds, the stream drops the connection and opens it again.
- A 400, 401, 403, 404 or 422 throws the `ApiException` from `hasNext()` instead of retrying, so an expired or revoked credential ends the stream on the next attempt to open it. A 200 that is not an event stream throws one too, with the code `unrecognised_response`.
- The connection opens on the first call to `hasNext()`, and the client's `timeout` bounds only the wait for the server to answer, never how long the stream stays open.

Also available in: API [`GET /live-events`](https://nextmail.sh/docs/api/reference/live-events#get-live-events); TypeScript [`liveEvents.stream()`](https://nextmail.sh/docs/sdk/reference/live-events#stream); Python [`live_events.stream()`](https://nextmail.sh/docs/python/reference/live-events#stream); Ruby [`live_events.stream`](https://nextmail.sh/docs/ruby/reference/live-events#stream); PHP [`liveEvents->stream`](https://nextmail.sh/docs/php/reference/live-events#stream); Go [`LiveEvents.Stream`](https://nextmail.sh/docs/go/reference/live-events#stream); C# [`LiveEvents.StreamAsync`](https://nextmail.sh/docs/csharp/reference/live-events#stream); CLI [`nextmail live-events stream`](https://nextmail.sh/docs/cli/reference/live-events#live-events-stream).
