You can push events from native code to the page whenever native state changes, such as when a save finishes or a download progresses. That prevents the page from having to poll native code for updates.

Events travel in one direction— native code emits the event, and the page listens on the API's namespace object.

## Emitting an Event

Call `api.Emit()` with an event name and any payload values:

```cpp
api.Emit("saved", std::string("slot1.dat"));
```

You can call `api.Emit()` from any thread. Arguments are copied during the call, so values you pass don't need to outlive it.

Payload types convert to JavaScript types the same way as exposed-function parameters (see [Passing Data Across the Bridge](/docs/2.0/passing-data-across-the-bridge)). You can pass up to 16 payload arguments.

Events are delivered on the Renderer's thread during a later call to `Renderer::Update()`. The event reaches every attached page that held the bindings when `api.Emit()` was called.

> 📘 Native Values Only
>
> You can't pass a `js::Value` to `api.Emit()` (doing so causes a build error). An emitted event reaches every attached page, while a `js::Value` belongs to a single page. Pass native types like numbers, strings, containers, or structs instead.

## Listening on the Page

Subscribe to events on the API's namespace object using `on()` or `once()`:

```js
myApp.on('saved', (path) => refreshList(path));    // every save
myApp.once('saved', () => showToast("Saved"));    // the next save only
```

The listener receives the payload values that native code emitted. If a listener throws an error, the other listeners still run.

For nested event names like `fs.changed`, the page can subscribe to the full path on the root namespace object (`myApp.on('fs.changed', fn)`). If bindings exist under `fs`, the page can also subscribe on the child namespace (`myApp.fs.on('changed', fn)`).

> 🚧 Reserved Method Names
>
> The names `on`, `once`, and `off` are reserved on every namespace object. A native binding or child namespace with one of these names is still registered, but it replaces the event method on that object. The renderer logs a warning if diagnostics are set to `Warn` or `Strict` (at `Off`, the method is replaced silently).

### Removing Listeners

Call `off()` to remove a specific listener or all listeners for an event:

```js
function onSaved(path) { refreshList(path); }

myApp.on('saved', onSaved);

// Later:
myApp.off('saved', onSaved);  // remove this listener
myApp.off('saved');           // remove every listener for 'saved'
```

Removing a single listener requires passing the same function object that was registered, so you'll need to use a named function rather than an inline arrow function.

### Missed Events

Events are not queued or replayed— if a page isn't listening when an event is delivered, it misses that event. A page that subscribes later receives only subsequent events.

### Restoring from the Back-Forward Cache

Re-subscribe to events in a `pageshow` handler when a page is restored from the back-forward cache:

```js
window.addEventListener('pageshow', (event) => {
  if (event.persisted)
    myApp.on('saved', onSaved);
});
```

A page restored from the back-forward cache keeps its API bindings, but it loses its event subscriptions.

Check `event.persisted` before re-subscribing— regular page loads also fire `pageshow`, but with `persisted` set to `false`.

## Declaring Events

Declare an event and its payload types using `DefineEvent()`:

```cpp
api.DefineEvent<std::string>("saved", js::Param("path"),
                             js::Doc("A save finished."));
```

Declaring events is optional— events work without declaration. Pass payload types as template arguments, with optional parameter names in `js::Param` and documentation in `js::Doc`.

Declaring an event includes it in the API's schema. Generated TypeScript declarations gain typed `on()`, `once()`, and `off()` overloads (see [API Schemas and TypeScript](/docs/2.0/api-schemas-and-typescript)), and diagnostics check event names (see [JavaScript Errors and Diagnostics](/docs/2.0/javascript-errors-and-diagnostics)).

A declaration only describes the event. Calling `api.Emit()` doesn't check its arguments against declared types, and declarations cannot be removed with `api.Unbind()`.

> 🚧 Declare All Events or None
>
> Declaring an event enables name checks in diagnostics at `Warn` and `Strict` levels. The renderer then logs a warning for every `api.Emit()` call or page subscription for an undeclared event. You should declare every event the API uses, or none of them.

## Requesting Data from the Page

Events only travel from native code to the page.

To get an answer back, emit a request event carrying an ID and have the page reply through an exposed function:

```cpp
api["answerInventory"] = [](double request_id,
                            std::vector<std::string> items) {
  OnInventoryAnswer(request_id, items);
};
api.Emit("queryInventory", next_request_id++);
```

On the page, listen for the request event and return the data with that ID:

```js
myApp.on('queryInventory', (id) => myApp.answerInventory(id, collectItems()));
```

Native code then matches the reply to the original request using the ID.
