# Live events
Use FlowHandle events and DOM events to observe checkout starts, purchases, completions, and cancellations.
Source: /docs/sdk/events
Last modified: 2026-06-18
`plandalf.present()` and `plandalf.mount()` return a `FlowHandle`: an awaitable Promise with an `.events` async iterable and `.close()` method.

## Observe a checkout

```js
const handle = plandalf.present("pro-plan");

(async () => {
  for await (const event of handle.events) {
    if (event.type === "start") console.log("Checkout opened");
    if (event.type === "purchase") console.log("Paid invoice", event.invoice_total);
    if (event.type === "complete") console.log("Flow complete", event.session?.uuid);
    if (event.type === "cancel") console.log("Dismissed", event.reason);
  }
})();

const result = await handle;
```


### Event listener explained

- `const handle = plandalf.present("pro-plan")` - Starts checkout and returns a FlowHandle immediately. You can listen to events before the customer finishes.
- `for await (const event of handle.events)` - Reads live checkout events in order. This is useful for analytics, frontend unlocks, and handoffs to your own backend.
- `event.type === "purchase"` - Runs when a paid invoice is created. This can happen before the whole flow is complete if the checkout includes upsells.
- `const result = await handle` - Waits for the final state: completed checkout or customer dismissal.

## Event types

| Event | When it fires |
| --- | --- |
| `start` | The checkout frame opens or an inline checkout mounts. |
| `purchase` | A paid invoice is created, including main purchase or upsell. |
| `complete` | The checkout flow reaches its final completion state. |
| `cancel` | The customer dismisses the frame before completing. |

## Close a flow

```js
const handle = plandalf.present("pro-plan");

document.querySelector("#cancel").addEventListener("click", () => {
  handle.close();
});
```

## Get a handle from an element

Declarative elements are tracked by the SDK. Use `from()` to retrieve the current handle.

```html
<button id="buy" data-plandalf-present="pro-plan">
  Buy
</button>
```

```js
const button = document.getElementById("buy");
const handle = plandalf.from(button);
```

`from()` returns the most recent open handle for that element or `null`.

## Related docs

- [Configure the SDK](/docs/sdk/configure)
- [SDK checkout API](/docs/api/sdk-checkout)
- [Webhooks](/docs/api/webhooks)