> ## 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.

# Security and CSP

> What your Content Security Policy needs for Elements, and how the checkout block protects your buyers and your shop.

## Content Security Policy

If your site sends a `Content-Security-Policy` header, add these sources next to the ones you already have. Each one is needed by something the script does on your page.

| Directive | Source | Why |
| - | - | - |
| `script-src` | `https://checkout.shoppex.io` | Loads `embed.iife.js`. |
| `frame-src` | `https://checkout.shoppex.io` | The checkout block is an iframe from this origin. |
| `connect-src` | `https://api.shoppex.io` | Before it loads the block, the script asks Shoppex whether your site is allowed. |
| `style-src` | `'nonce-YOUR_NONCE'` or `'unsafe-inline'` | The script adds its loading and error styles to the page. With a nonce, pass it to `Shoppex.init({ nonce })`. |

A complete policy with a nonce:

```http theme={"system"}
Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-YOUR_NONCE' https://checkout.shoppex.io;
  frame-src https://checkout.shoppex.io;
  connect-src 'self' https://api.shoppex.io;
  style-src 'self' 'nonce-YOUR_NONCE';
```

And the page that goes with it:

```html theme={"system"}
<div id="checkout"></div>

<script src="https://checkout.shoppex.io/embed/embed.iife.js" nonce="YOUR_NONCE" defer></script>
<script type="module" nonce="YOUR_NONCE">
  Shoppex.init({ nonce: 'YOUR_NONCE' });
  Shoppex.mount('#checkout', {
    shopId: 'YOUR_SHOP',
    items: [{ productId: 'YOUR_PRODUCT_ID' }],
    mode: 'test',
  });
</script>
```

Your server makes a new nonce for every response.

* **Without `frame-src`** the browser refuses the frame, and after 15 seconds the block shows "Checkout didn't load" with the `frame_load_timeout` error.
* **Without `connect-src`** the script cannot ask whether your site is allowed. The block shows "Checkout didn't load" with `checkout_unavailable`.
* **Without `style-src`** the loading skeleton and the error message have no styles. The checkout itself is styled inside the frame and is not affected.
* Pages with the Buy Button need more sources. See [Checkout Embed SDK](/developers/embeds/reference#content-security-policy).
* A local dev server usually sends no CSP. Test the policy on your real domain.

## Which sites can show your checkout

A live block loads only on your [allowed sites](/developers/elements/sites). The checkout answers with `Content-Security-Policy: frame-ancestors` and that list, so the browser refuses the frame on every other site. The list applies to every page above the block, so a website builder that shows your page in its editor needs its own entry.

## Messages between your page and the block

* The block sends its events only to the origin of the page that loaded it, and only when that site may show the block.
* The script accepts events only from its own frame on `checkout.shoppex.io`, and only for its own block. Messages from other frames, ads or windows are dropped. With `debug: true` the console shows each dropped message and why.
* Your page can send the block only one thing: a new appearance. There is no message that starts, confirms or cancels a payment, or changes the product, the quantity or the amount.

## Payments inside the block

* Card details, wallet confirmations and provider logins happen inside the block or in the provider's own window. Your page never sees them.
* Every payment needs the buyer's own input at the provider: card details, a wallet confirmation or a login. A page that hides or covers the block cannot pay on the buyer's behalf.
* Some payment methods open a window or a new tab. The block sends a `redirect` event first. See [Payment methods in the block](/developers/elements/overview#payment-methods-in-the-block).

## Fulfil from webhooks

The browser is not a safe place to decide that an order was paid: any script on the page can send a `success` event. Deliver from the `order:paid` [webhook](/developers/webhook-events) or check the invoice with the [Developer API](/developers/invoices).


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