> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paysight.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Events reference

> Full EVENT_TYPES catalog

Events are delivered via `onMessage` or `widget.subscribe`. Each message has `type` and optional `payload`.

```javascript theme={null}
PaySightSDK.createWidget({
  config: { /* ... */ },
  onMessage: (message) => {
    console.log(message.type, message.payload);
  },
});
```

## Lifecycle

| Event                | Payload                      | Description                                         |
| -------------------- | ---------------------------- | --------------------------------------------------- |
| `READY`              | —                            | Widget iframe initialized and interactive           |
| `DESTROY`            | —                            | Widget destroyed                                    |
| `HEIGHT_CHANGE`      | `{ height: number }`         | Iframe content height changed (auto-resize)         |
| `WALLET_FORM_LAYOUT` | `{ showOrDivider: boolean }` | Whether host "OR" divider and card form are visible |

## Configuration

| Event                   | Payload | Description                  |
| ----------------------- | ------- | ---------------------------- |
| `CONFIG_UPDATE_SUCCESS` | —       | `update()` applied in iframe |

## Form

| Event          | Payload                             | Description                                   |
| -------------- | ----------------------------------- | --------------------------------------------- |
| `FIELD_CHANGE` | `{ field: string; value: unknown }` | User edited a field                           |
| `FIELD_BLUR`   | `{ field: string; value: unknown }` | Field lost focus                              |
| `FORM_SUBMIT`  | —                                   | In-iframe form submitted (before payment API) |

## Payment

| Event             | Payload                                   | Description                                       |
| ----------------- | ----------------------------------------- | ------------------------------------------------- |
| `PAYMENT_START`   | —                                         | Payment attempt started (checkout **and** upsell) |
| `PAYMENT_SUCCESS` | See below                                 | Charge succeeded                                  |
| `PAYMENT_ERROR`   | `{ message?: string; details?: unknown }` | Charge failed                                     |

<Callout type="info">
  **Upsell uses the same payment events.** There are no separate `UPSELL_START`, `UPSELL_SUCCESS`, or `UPSELL_ERROR` events on the host. On page 2, listen for `PAYMENT_SUCCESS` / `PAYMENT_ERROR` and check `payload.mode === 'upsell'` (and `payload.upsellId`).
</Callout>

### `PAYMENT_SUCCESS` payload

```typescript theme={null}
{
  paysightSession?: string;   // use for upsell.initialPaymentSession
  transactionId?: string;
  amount?: number;
  orderId?: number;
  mode?: 'checkout' | 'upsell';
  upsellId?: string;
  [key: string]: unknown;     // full API response fields
}
```

## 3D Secure

| Event                 | Payload                                       | Description                |
| --------------------- | --------------------------------------------- | -------------------------- |
| `PAYMENT_3DS_START`   | —                                             | 3DS challenge started      |
| `PAYMENT_3DS_SUCCESS` | —                                             | 3DS completed successfully |
| `PAYMENT_3DS_ERROR`   | `{ code: string; message: string; details? }` | 3DS error                  |
| `PAYMENT_3DS_FAILURE` | `{ code: string; message: string; details? }` | 3DS failed or abandoned    |

## Shopify cart

| Event         | Payload                                              | Description         |
| ------------- | ---------------------------------------------------- | ------------------- |
| `CART_READY`  | `{ subtotal, shipping, total, currency, itemCount }` | Cart UI mounted     |
| `CART_UPDATE` | Same as `CART_READY`                                 | Cart config changed |

## Upsell guard

| Event                   | Payload                                         | Description                               |
| ----------------------- | ----------------------------------------------- | ----------------------------------------- |
| `DUPLICATE_TRANSACTION` | `{ upsellId, message, initialPaymentSession? }` | Upsell already completed for this session |

## Errors (structured)

| Event   | Payload                                                                 | Description                                      |
| ------- | ----------------------------------------------------------------------- | ------------------------------------------------ |
| `ERROR` | `{ code: PaymentErrorCode; message: string; missingFields?: string[] }` | Validation or guard failure before/during submit |

See [Error codes](/widget-sdk/reference/error-codes) for `code` values.

## Internal (integrators rarely need these)

| Event            | Direction     | Notes                          |
| ---------------- | ------------- | ------------------------------ |
| `ACK`            | iframe → host | Handshake                      |
| `INIT`           | host → iframe | Initial config                 |
| `CONFIG_UPDATE`  | host → iframe | Runtime config patch           |
| `SUBMIT_PAYMENT` | host → iframe | Triggered by `submitPayment()` |
| `SUBMIT_UPSELL`  | host → iframe | Triggered by `submitUpsell()`  |
| `PROXY_READY`    | iframe → host | Messaging proxy ready          |

`PS_WALLET_READINESS` is a separate `postMessage` (not in `EVENT_TYPES`) used for wallet-only layout.

## Example handler

```javascript theme={null}
function handleMessage(message) {
  switch (message.type) {
    case 'READY':
      break;
    case 'PAYMENT_SUCCESS':
      if (message.payload?.mode === 'upsell') {
        redirectToThankYou();
      } else {
        const session = message.payload?.paysightSession;
        if (session) sessionStorage.setItem('paysightSession', session);
      }
      break;
    case 'PAYMENT_ERROR':
      if (message.payload?.mode === 'upsell') showUpsellError(message.payload);
      break;
    case 'DUPLICATE_TRANSACTION':
      redirectToThankYou();
      break;
    case 'ERROR':
      showError(message.payload.code, message.payload.message);
      break;
  }
}
```

## Related

* [Events guide](/widget-sdk/guides/events)
* [Saved payment & upsell](/widget-sdk/guides/saved-payment-and-upsell)
* [Error handling example](/widget-sdk/examples/error-handling)
