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

# Embed the checkout

> Drop the checkout into your site with two script tags. Full SDK reference.

The checkout runs in an iframe you open from your own page. Your customer never leaves your site.

## Install

```html theme={null}
<script src="https://www.cryptocheckout.ai/sdk.js"
        integrity="sha384-cjNZpyXGzEF9lSh5wnh8mtsi3YU56F0n0bToTaUBqdDCVZ2AFw4GYqnxlSU3I+ob"
        crossorigin="anonymous"></script>
```

<Warning>
  Copy the snippet from **API & SDK** in your dashboard rather than this page. Yours has your merchant ID and payout address filled in, and the integrity hash there is always current.
</Warning>

## Minimal integration

```html theme={null}
<script>
  const checkout = CryptoCheckout.init({
    merchantId: "your-merchant-id",
    settlementAnchor: "0xYourPayoutWalletAddress",
    onPaymentConfirmed: (payload) => {
      window.location = "/thank-you";
    },
  });

  document.querySelector("#pay").addEventListener("click", () => {
    checkout.updateCart({ total: 49.00, currency: "EUR" });
    checkout.open();
  });
</script>
```

## `CryptoCheckout.init(config)`

Returns a checkout instance.

<ParamField path="merchantId" type="string" required>
  Your merchant ID, from the dashboard.
</ParamField>

<ParamField path="settlementAnchor" type="string" required>
  Your on-chain payout address. The checkout verifies this against the blockchain before accepting payment and blocks on mismatch. [Why this matters](/concepts/verification).
</ParamField>

<ParamField path="onPaymentConfirmed" type="function">
  Called when the payment reaches finality. Receives the payment payload.

  **UI only** — fulfil orders from [webhooks](/webhooks/overview).
</ParamField>

<ParamField path="onPaymentFailed" type="function">
  Called when a payment attempt fails.
</ParamField>

<ParamField path="onWidgetClosed" type="function">
  Called when the customer dismisses the checkout.
</ParamField>

<ParamField path="onReady" type="function">
  Called when the checkout has loaded and completed verification.
</ParamField>

## Instance methods

<ResponseField name="updateCart(cart)" type="method">
  Sets the amount to charge. Call before `open()`.

  <Expandable title="cart">
    <ResponseField name="total" type="number" required>
      Order total in your display currency.
    </ResponseField>

    <ResponseField name="currency" type="string" required>
      `EUR` or `USD`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="open()" type="method">
  Opens the checkout overlay.
</ResponseField>

<ResponseField name="close()" type="method">
  Closes it programmatically.
</ResponseField>

<ResponseField name="destroy()" type="method">
  Tears down the instance and removes its listeners. Call this in your framework's cleanup hook.
</ResponseField>

## Framework examples

<CodeGroup>
  ```jsx React theme={null}
  import { useEffect, useRef } from "react";

  export function PayButton({ total, currency = "EUR" }) {
    const checkout = useRef(null);

    useEffect(() => {
      checkout.current = window.CryptoCheckout.init({
        merchantId: import.meta.env.VITE_CC_MERCHANT_ID,
        settlementAnchor: import.meta.env.VITE_CC_ANCHOR,
        onPaymentConfirmed: () => (window.location.href = "/thank-you"),
      });
      return () => checkout.current?.destroy();
    }, []);

    const pay = () => {
      checkout.current.updateCart({ total, currency });
      checkout.current.open();
    };

    return <button onClick={pay}>Pay with crypto</button>;
  }
  ```

  ```vue Vue theme={null}
  <script setup>
  import { onMounted, onUnmounted, ref } from "vue";

  const props = defineProps({ total: Number, currency: { default: "EUR" } });
  const checkout = ref(null);

  onMounted(() => {
    checkout.value = window.CryptoCheckout.init({
      merchantId: import.meta.env.VITE_CC_MERCHANT_ID,
      settlementAnchor: import.meta.env.VITE_CC_ANCHOR,
      onPaymentConfirmed: () => (window.location.href = "/thank-you"),
    });
  });

  onUnmounted(() => checkout.value?.destroy());

  function pay() {
    checkout.value.updateCart({ total: props.total, currency: props.currency });
    checkout.value.open();
  }
  </script>

  <template><button @click="pay">Pay with crypto</button></template>
  ```
</CodeGroup>

## Content Security Policy

If you set a CSP, allow our origin:

```
script-src  https://www.cryptocheckout.ai;
frame-src   https://www.cryptocheckout.ai;
```

<Warning>
  Use `https://www.cryptocheckout.ai`, with the `www`. The apex redirects, and a redirect breaks the origin check the SDK performs.
</Warning>

## Troubleshooting

<AccordionGroup>
  <Accordion title="The checkout opens but stays blank">
    Almost always CSP. Check the browser console for a `frame-src` violation.
  </Accordion>

  <Accordion title="The script doesn't execute at all">
    A stale `integrity` hash. The browser refuses to run a file whose hash doesn't match the pin. Re-copy the snippet from your dashboard.
  </Accordion>

  <Accordion title="It shows a configuration mismatch warning">
    Your `settlementAnchor` doesn't match what's attested on-chain. Check **Settings → Payout** — most often the anchor in your HTML is an old address. This is the protection working. [Verification](/concepts/verification).
  </Accordion>

  <Accordion title="onPaymentConfirmed never fires">
    Expected if the customer closed the tab. The payment still completed — your webhook is the reliable signal. [Finality](/concepts/finality).
  </Accordion>
</AccordionGroup>
