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

# Events and error codes

> Every event an Elements checkout sends to your page, and every error code it can report.

The block tells your page what happens inside it. Listen with `on` on the block from [`Shoppex.mount`](/developers/elements/reference#mount-with-javascript), or with DOM events on the HTML block.

```js theme={"system"}
checkout.on('step', ({ step, previous }) => console.log(previous, '→', step));
checkout.on('error', ({ code, recoverable }) => {
  if (code === 'origin_not_allowed') showBuyOnOurSiteLink();
});
```

> [!WARNING]
>
> `success` tells your page that the buyer finished. It is not proof of payment: any script on the page can send a browser event. Deliver orders from [webhooks](/developers/webhook-events) or the [Developer API](/developers/invoices).

## Events

| Event | Payload | When |
| - | - | - |
| `ready` | `{ height, mode }` | Once, when the block has drawn and measured itself. `mode` is `'live'` or `'test'`. |
| `resize` | `{ height }` | When the block's height changes. The script sets the height for you. |
| `step` | `{ step, previous, reason? }` | When the buyer moves to another step. `previous` is `null` for the first step. |
| `invoice-created` | `{ invoiceId, test? }` | Once per invoice, when the buyer starts paying. |
| `redirect` | `{ url, reason, target }` | Before the block hands the buyer to a payment provider's window or tab. The script opens it. |
| `success` | `{ invoiceId, completionAccessGrant?, test? }` | Once per invoice, after Shoppex confirmed the payment. |
| `error` | `{ type, code, message, recoverable, invoiceId? }` | See [Error codes](#error-codes). |
| `warning` | `{ code, detail }` | The block did not use something your page sent. See [Warnings](#warnings). |

**Steps** are `details` (email and fields), `payment`, `processing`, `redirect` and `success`. Before 3-D Secure, the block sends `step: 'processing'` with `reason: 'authentication'` and the script scrolls the block into view, so the bank's check is not off screen.

**Redirects.** `reason` is `'gateway'` or `'authentication'`. `target` is `'popup'`, `'new_tab'` or `'top'`. If the browser blocks the popup or new tab, the script opens the address in the current tab.

**Test mode** adds `test: true` to `invoice-created` and `success`, and the invoice ID starts with `test_`. No invoice exists.

## DOM events

The HTML block sends every event as a DOM event named `shoppex:element:<event>` on its `<div>`. The payload is in `event.detail`. The events bubble, so you can listen on `document`:

```js theme={"system"}
document.addEventListener('shoppex:element:success', (event) => {
  console.log('Order placed', event.detail.invoiceId);
});
```

A block from `Shoppex.mount` sends the same DOM events on its container.

## Error codes

Match on `code`. A code never changes its meaning, and new errors get new codes. `message` is text for the buyer in their language and can change at any time.

`recoverable: true` means the buyer can still finish in the same block, for example by fixing a field, picking another payment method or clicking **Try again**.

| `code` | `type` | `recoverable` | When |
| - | - | - | - |
| `origin_not_allowed` | `load` | no | The page's site is not on your [allowed sites](/developers/elements/sites). In test mode: not on the list and not `http://localhost` or `http://127.0.0.1`. |
| `frame_load_timeout` | `load` | yes | The block did not report `ready` within 15 seconds. |
| `checkout_unavailable` | `load` | yes | Shoppex did not answer, or the checkout cannot load right now. |
| `already_mounted` | `config` | no | The page already has an Elements block. See [One block per page](/developers/elements/reference#one-block-per-page). |
| `invalid_options` | `config` | no | The options are wrong, the target element does not exist, the shop does not exist, or the shop hid the `groupId` group. The console names the reason. |
| `product_not_found` | `config` | no | The shop hid or deleted the product. The block says so at once and offers no retry. An id that never existed gets `frame_load_timeout`: no shop's site list lets its frame load. |
| `invoice_not_found` | `config` | no | The invoice does not exist. |
| `cart_rejected` | `checkout` | yes | The checkout refused the item, for example its quantity or variant. |
| `out_of_stock` | `checkout` | no | Not enough stock. |
| `coupon_invalid` | `checkout` | yes | The coupon is not valid for this order. |
| `email_rejected` | `checkout` | yes | The email address was refused. |
| `checkout_blocked` | `checkout` | no | Your shop's rules do not allow this buyer to purchase. |
| `checkout_failed` | `checkout` | no | An error without a more specific code. Shoppex is alerted. |
| `payment_declined` | `payment` | yes | The bank or provider declined the payment. |
| `payment_failed` | `payment` | yes | The payment did not go through. |
| `authentication_failed` | `payment` | yes | 3-D Secure or another check by the bank failed. |
| `gateway_handoff_failed` | `payment` | yes | The payment provider could not be opened. |
| `amount_below_minimum` | `payment` | no | The total is below the payment method's minimum. Another method may still accept it. |

For the load and config errors, the block shows its own message in place of the checkout. The other errors show inside the checkout, where the buyer can act on them.

## Warnings

| `code` | `detail` | When |
| - | - | - |
| `appearance_value_rejected` | `{ key, value, reason }` | An [appearance](/developers/elements/appearance#values-the-block-does-not-use) value failed its check. The block keeps the Style Center value for that key. |
| `command_rejected` | `{ type, reason }` | The block refused a message from your page that it does not understand. |

Warnings come after `ready`, once per key and appearance.

## What your page cannot do

Your page can restyle the block with `update({ appearance })`. It cannot start, confirm or cancel a payment, and it cannot change the product, the quantity or the amount. Only the buyer can, inside the block. The block accepts messages only from the page that loaded it, and your script accepts events only from its own block on `checkout.shoppex.io`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.