# Subscribe or unsubscribe to API events

Nutrient Web SDK comes with an API to subscribe and unsubscribe to framework-level events that are dispatched every time actions occur. This API is available on every [`Instance`](https://www.nutrient.io/api/web/NutrientViewer.Instance.html) and consists of two methods:

- [`Instance#addEventListener`](https://www.nutrient.io/api/web/NutrientViewer.Instance.html#addEventListener)

- [`Instance#removeEventListener`](https://www.nutrient.io/api/web/NutrientViewer.Instance.html#removeEventListener)

A comprehensive list of and detailed documentation for every event is available in the [`addEventListener` docs](https://www.nutrient.io/api/web/NutrientViewer.Instance.html#addEventListener).

Once Nutrient Web SDK is initialized, registering an event listener is straightforward:

```js

function listener(createdAnnotations) {
  console.log(createdAnnotations);
}

instance.addEventListener("annotations.create", listener);

```

It's important to define the `listener` function separately so that it can be used later on to remove the event listener:

```js

instance.removeEventListener("annotations.create", listener);

```

Note that adding an unknown event will raise a [`NutrientViewer.Error`](https://www.nutrient.io/api/web/NutrientViewer.Error.html):

```js

try {
  instance.addEventListener("doesnotexist", () => {});
} catch (error) {
  error instanceof NutrientViewer.Error; // => true
}

```

### Listener arguments

With the exception of exact single-value arguments like numbers and strings, Nutrient Web SDK invokes event listeners with immutable data structures. When this occurs, you can use the `toJS` method to convert them to plain JavaScript objects:

```js

function listener(createdAnnotations) {
  console.log(createdAnnotations.toJS()); // => Array of annotation objects
}

instance.addEventListener("annotations.create", listener);

```

Here’s an example of native JavaScript argument types:

```js

function listener(zoom) {
  console.log(zoom); // => 1.5 for example
}

instance.addEventListener("viewState.zoom.change", listener);

```

### Registering events on the internal viewer document and window

Nutrient Web SDK is rendered inside of an iframe, and because of this, we expose its `document` and `window` objects on each instance as `contentDocument` and `contentWindow`.

By using a reference to these objects, it is possible to register regular DOM events on elements inside of the viewer frame:

```js

instance.contentDocument.addEventListener("mouseup", handleMouseUp);

```

As a general rule, we advise against registering events on the objects, since this might easily interfere with internal application logic. When possible, use [Nutrient Web SDK events](https://www.nutrient.io/api/web/NutrientViewer.Instance.html#addEventListener).

### Event examples and documentation

All of the available events are documented, with examples, on the [documentation page for NutrientViewer.Instance](https://www.nutrient.io/api/web/NutrientViewer.Instance.html#addEventListener). Don’t hesitate to contact us if specific use cases are not covered in the API docs.
---

## Related pages

- [Manage annotations effectively with our API](/guides/web/events/annotation.md)
- [Forms](/guides/web/events/forms.md)
- [Manage bookmarks efficiently with event-driven updates](/guides/web/events/bookmarks.md)
- [Text Selection](/guides/web/events/text-selection.md)

