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

# Checkout-js SDK

> Browser SDK reference for embedding Slash checkout.

<Info>
  Slash Payment Processing is in beta and not enabled for all accounts. Contact
  [support@joinslash.com](mailto:support@joinslash.com) to get access.
</Info>

`@slashfi/checkout-js` is a zero-dependency browser SDK for embedding the
Slash hosted checkout: mint a checkout session server-side, then mount its
hosted `url` on your page.

Payment method availability is configured when your backend creates the
checkout session. The browser SDK does not expose payment-method controls.

## Install

```bash theme={null}
npm install @slashfi/checkout-js
```

## `loadSlashCheckout()`

Loads the checkout client. Async so a CDN-hosted build can be swapped in
later without an API change.

```ts theme={null}
import { loadSlashCheckout } from "@slashfi/checkout-js";

const slashCheckout = await loadSlashCheckout();
```

## `createEmbeddedCheckoutPage(options)`

Creates one embedded checkout instance. Only one can be live per page at
a time — call `destroy()` before creating another.

| Option         | Type                          | Description                                                                                                  |
| -------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `fetchUrl`     | `() => Promise<string>`       | Resolves the hosted checkout URL, typically by calling your backend. Preferred.                              |
| `url`          | `string`                      | The hosted URL directly, if you already have it. Provide `url` **or** `fetchUrl`, not both.                  |
| `theme`        | `"light" \| "dark"`           | Pins the checkout's color scheme to match your page. When omitted, it follows the buyer's OS preference.     |
| `onReady`      | `() => void`                  | Fires once the embed has mounted and rendered.                                                               |
| `onProcessing` | `() => void`                  | Buyer completed checkout in-frame; settlement is in flight. UX only.                                         |
| `onComplete`   | `() => void`                  | Session confirmed settled server-side. UX only — still fulfill on the webhook.                               |
| `onError`      | `({ code, message }) => void` | Load failure, session expiry, or payment decline. Fires only after the instance exists — see the note below. |

```ts theme={null}
const checkout = await slashCheckout
  .createEmbeddedCheckoutPage({
    fetchUrl: () => createSessionOnMyBackend(),
    onReady: () => hideSpinner(),
    onProcessing: () => showOrderPending(),
    onComplete: () => showConfirmation(),
    onError: ({ code, message }) => handleError(code, message),
  })
  .catch((error) => {
    // Initialization failures (e.g. a rejected `fetchUrl`) reject this
    // promise; they never reach `onError`, which only reports failures
    // of an already-created instance.
    showSessionCreationFailed(error);
    return undefined;
  });
```

### Error codes

| Code                  | Terminal? | Meaning                                                                   |
| --------------------- | --------- | ------------------------------------------------------------------------- |
| `load_failed`         | No        | Couldn't mint/mount the checkout (network/provider). The buyer can retry. |
| `payment_failed`      | No        | Card declined. The embed remounts for another attempt.                    |
| `session_expired`     | Yes       | `expiresAt` passed. Create a new session.                                 |
| `session_not_payable` | Yes       | Session already complete or voided.                                       |

## Instance methods

| Method          | Description                                                           |
| --------------- | --------------------------------------------------------------------- |
| `mount(target)` | Attaches the iframe. `target` is a CSS selector or a DOM element.     |
| `unmount()`     | Detaches the iframe; the instance stays usable and can be re-mounted. |
| `destroy()`     | Unmounts and permanently disposes, freeing the one-per-page slot.     |

```ts theme={null}
checkout.mount("#checkout");
// ...later
checkout.unmount(); // remountable
checkout.destroy();  // permanent
```

## React

There is no React wrapper package — mount the SDK from an effect:

```tsx theme={null}
import { useEffect, useRef } from "react";
import { loadSlashCheckout } from "@slashfi/checkout-js";

export function Checkout() {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    let checkout;
    let cancelled = false;

    loadSlashCheckout()
      .then((sc) =>
        sc.createEmbeddedCheckoutPage({
          fetchUrl: () => createSessionOnMyBackend(),
          onComplete: () => showConfirmation(),
        })
      )
      .then((c) => {
        if (cancelled) return c.destroy();
        checkout = c;
        if (ref.current) c.mount(ref.current);
      })
      .catch(showSessionCreationFailed);

    return () => {
      cancelled = true;
      checkout?.destroy();
    };
  }, []);

  return <div ref={ref} />;
}
```

This pattern is safe under React strict-mode double mounting: the SDK
serializes `createEmbeddedCheckoutPage` calls, so the second mount's
create waits for the first to settle — and the first mount's cancelled
`destroy()` releases the one-per-page slot before the second create
proceeds. No card data passes through the SDK or your page — it is
entered inside the payment iframe.
