> ## Documentation Index
> Fetch the complete documentation index at: https://crossmint-wallets-docs-2-5.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Upgrade to V3

> Learn how to migrate to the latest version, V3, of Crossmint's Embedded Checkout

export const PackageManagerCommand = ({npm, pnpm, yarn, command, packageName}) => {
  const PACKAGE_MANAGER_COMMANDS = {
    "add-package": {
      npm: `npm install ${packageName}`,
      pnpm: `pnpm add ${packageName}`,
      yarn: `yarn add ${packageName}`
    },
    install: {
      npm: "npm install",
      pnpm: "pnpm install",
      yarn: "yarn install"
    }
  };
  let prefixes = (() => {
    if (Object.keys(PACKAGE_MANAGER_COMMANDS).includes(command)) {
      return PACKAGE_MANAGER_COMMANDS[command];
    } else if (command) {
      console.warn(`[PackageManagerCommand] Unknown command: ${command}`);
    }
    return {
      npm: "",
      pnpm: "",
      yarn: ""
    };
  })();
  return <CodeGroup>
            <CodeBlock filename="npm">
                <pre className="language-bash">
                    <code className="language-bash">{prefixes.npm}{npm}</code>
                </pre>
            </CodeBlock>
            <CodeBlock filename="pnpm">
                <pre className="language-bash">
                    <code className="language-bash">{prefixes.pnpm}{pnpm}</code>
                </pre>
            </CodeBlock>
            <CodeBlock filename="yarn">
                <pre className="language-bash">
                    <code className="language-bash">{prefixes.yarn}{yarn}</code>
                </pre>
            </CodeBlock>
        </CodeGroup>;
};

## Overview

The latest version of Crossmint's Embedded Checkout, Embedded V3, introduces a new architecture focused on simplicity and developer experience. Migrating your existing checkout integration is straightforward and can typically be completed in under 15 minutes. This guide will walk you through each step.

### Which Version Am I Using?

Only two versions of Embedded Checkout exist, each using its own distinct component:

* **V3**: The new `<CrossmintEmbeddedCheckout />` component
* **V2**: The legacy `<CrossmintPaymentElement />` component

<Note>
  The Embedded Checkout V3 component is available in `@crossmint/client-sdk-react-ui@1.12.0` and above. Make sure to
  update your dependencies to the latest version.
</Note>

## What's New in V3?

<CardGroup cols={3}>
  <Card title="Better DX" icon="code" iconType="duotone">
    React hooks, TypeScript support, and simpler APIs
  </Card>

  <Card title="Multiple Items" icon="cart-shopping" iconType="duotone">
    Sell multiple NFTs in a single checkout with individual delivery tracking
  </Card>

  <Card title="Enhanced UI" icon="paintbrush" iconType="duotone">
    More customization options and better payment method support
  </Card>
</CardGroup>

## Key Changes

Embedded Checkout V3 introduces powerful new features focused on making your life easier:

1. **Simpler Developer Experience**: More intuitive and idiomatic component API - less code, easier to understand
2. **Built-in Order Management**: Complete order status UI out of the box - no more manual event handling (but fully customizable if needed)
3. **React Hooks for State Management**: Replace event listeners with hooks for better control over the order lifecycle and checkout state
4. **Multi-Item Support**: Sell multiple NFTs in a single checkout with individual delivery tracking for each item
5. **Better UI Customization**: Includes more UI customization options - now you can control every aspect of the checkout's appearance
6. **Advanced Cross-chain Support**: Streamlined payment flows with expanded cross-chain capabilities

### Component Renaming

The main checkout component has been renamed from `CrossmintPaymentElement` to `CrossmintEmbeddedCheckout` to better reflect its purpose and capabilities. This component now supports multiple line items, advanced payment methods, and enhanced UI customization.

### Provider Architecture

The new Embedded Checkout V3 uses [React Context](https://react.dev/learn/passing-data-deeply-with-context) providers to manage state and configuration. The `CrossmintProvider` handles API authentication and environment setup using a client-side API key (more details in [Step 1](#1-get-a-client-api-key)), while `CrossmintCheckoutProvider` manages order state and checkout flow.

```tsx theme={null}
<CrossmintProvider apiKey="_YOUR_CLIENT_API_KEY_">
    <CrossmintCheckoutProvider>
        <CrossmintEmbeddedCheckout />
    </CrossmintCheckoutProvider>
</CrossmintProvider>
```

### Property Updates

Key property changes in Embedded Checkout V3:

* Introduces new `lineItems` property for multi-item support
* Uses `callData` object in each line item, replacing the previous `mintConfig` property
* Supports primary sales through `collectionLocator` with format `crossmint:${collectionId}` or `${chain}:${contractAddress}`
* Supports secondary sales through `tokenLocator` with format `${chain}:${contractAddress}:${tokenId}`
* Replaces `uiConfig` with `appearance` - see our [UI Customization guide](/payments/embedded/guides/ui-customization)
* Determines environment automatically from your API key
* Replaces event handlers with React hooks - see our [Hooks guide](/payments/embedded/guides/hooks)

### React Hooks for State Management

Events have been replaced with React hooks, providing better TypeScript support and a more intuitive development experience:

```tsx theme={null}
// Old - Event-based system
<CrossmintPaymentElement
    onEvent={(event) => {
        switch (event.type) {
            case "payment:process.succeeded":
                console.log("Payment successful!");
                break;
            case "payment:process.failed":
                console.log("Payment failed:", event.payload.error);
                break;
        }
    }}
/>;

// New - Hook-based system
function Checkout() {
    const { order } = useCrossmintCheckout();

    useEffect(() => {
        switch (order?.phase) {
            case "completed":
                console.log("Purchase complete!");
                break;
            case "delivery":
                console.log("Delivering NFTs...");
                break;
            case "payment":
                console.log("Processing payment...");
                break;
        }
    }, [order]);
}
```

### Multiple Line Items Support

Embedded Checkout V3 supports checking out multiple items (with different token IDs or collections) at once. Each line item has its own delivery status, allowing for granular tracking of each of the line items:

```tsx theme={null}
<CrossmintEmbeddedCheckout
    lineItems={[
        {
            collectionLocator: `crossmint:${collectionId}`,
            callData: {
                totalPrice: "0.001",
                quantity: 1,
            },
        },
        {
            collectionLocator: `crossmint:${collectionId}`,
            callData: {
                totalPrice: "0.002",
                quantity: 1,
            },
        },
    ]}
    payment={{
        crypto: { enabled: true },
        fiat: { enabled: true },
    }}
/>
```

### Secondary Sales Support

Embedded Checkout V3 introduces a cleaner way to handle secondary sales using the new `tokenLocator` property:

```tsx theme={null}
// EVM secondary sale
<CrossmintEmbeddedCheckout
    lineItems={[
        {
            tokenLocator: "base:0xbC…307e:1",
            callData: {
                totalPrice: "0.1"
            }
        }
    ]}
/>

// Solana secondary sale
<CrossmintEmbeddedCheckout
    lineItems={[
        {
            tokenLocator: "solana:4oDd…x6NC",
            callData: {
                totalPrice: "0.1",
                buyerCreatorRoyaltyPercent: 100  // Required for Solana
            }
        }
    ]}
/>

```

<Note>
  When handling multiple items (e.g., marketplace or multi-item sales), each item has its own delivery status. If one
  item fails to deliver, others may still complete successfully. Make sure to handle each item's status independently:
</Note>

```tsx theme={null}
function CheckoutStatus() {
    const { order } = useCrossmintCheckout();

    return (
        <div>
            {order?.lineItems.map((item, index) => (
                <div key={index}>
                    Item {index + 1}: {item.status}
                    {item.status === "failed" && <div>Error: {item.error}</div>}
                </div>
            ))}
        </div>
    );
}
```

### Orders API Integration

The new version integrates with our [Orders API](/api-reference/orders/overview), enabling programmatic access to order status, history, and management. This allows you to build custom experiences and integrate with your backend systems.

## Migration Steps

### 1. Get a Client API Key

Create a client-side API key with the `orders.create` scope enabled. [More info on creating API keys here](/introduction/platform/api-keys#how-to-get-and-use-api-keys).

### 2. Update Dependencies

<Note>Upgrade the Crossmint React SDK to version `1.12.0` or above.</Note>

<PackageManagerCommand command="add-package" packageName="@crossmint/client-sdk-react-ui@latest" />

### 3. Update Import Statements

```tsx theme={null}
// Old
import { CrossmintPaymentElement } from "@crossmint/client-sdk-react-ui";

// New
import { CrossmintProvider, CrossmintEmbeddedCheckout } from "@crossmint/client-sdk-react-ui";
```

### 4. Update Environment Variables

Change your Crossmint environment variables (e.g. in your `.env.local` file or Vercel configuration):

```bash theme={null}
# Old
NEXT_PUBLIC_PROJECT_ID="_YOUR_PROJECT_ID_" # No longer needed - derived from the API key
NEXT_PUBLIC_COLLECTION_ID="_YOUR_COLLECTION_ID_"
NEXT_PUBLIC_ENVIRONMENT="staging"          # No longer needed - derived from the API key

# New
NEXT_PUBLIC_CLIENT_API_KEY="_YOUR_CLIENT_API_KEY_"    # From API Keys page
NEXT_PUBLIC_COLLECTION_ID="_YOUR_COLLECTION_ID_"      # From Collection details page
```

<Note>The `projectId` and `environment` values are now automatically derived from the client-side API key.</Note>

### 5. Update Component Structure

Instead of a single react component, `<CrossmintPaymentElement />`, the new checkout now has
one provider, `<CrossmintProvider />` that can be added in your layout page, or the same page you
have checkout on, and one react component, that has been renamed to `<CrossmintEmbeddedCheckout />`.

The properties in the react component have changed:

* `projectId` and `environment` are no longer needed
* You now specify which items to buy using `lineItems`, an array of items that support both `collectionLocator` (for primary sales with formats `"crossmint:${collectionId}"` or `${chain}:${contractAddress}`) and `tokenLocator` (for secondary sales with the format `${chain}:${contractAddress}:${tokenId}`). Each item includes `callData` that takes the same object previously passed to `mintConfig`

#### Primary Sales

```tsx theme={null}
// Old
<CrossmintPaymentElement
    projectId={projectId}
    collectionId={collectionId}
    environment={environment}
    mintConfig={{
        totalPrice: "0.001",
        quantity: 1,
    }}
/>

// New
<CrossmintProvider apiKey={clientApiKey}>
    <CrossmintEmbeddedCheckout
        lineItems={{
            collectionLocator: `crossmint:${collectionId}`,
            callData: {
                totalPrice: "0.001",
                quantity: 1,
            },
        }}
        payment={{
            crypto: { enabled: true },
            fiat: { enabled: true },
        }}
    />
</CrossmintProvider>
```

#### Secondary Sales

```tsx theme={null}
// Old - EVM Secondary Sale
<CrossmintPaymentElement
    projectId={projectId}
    collectionId={collectionId}
    environment={environment}
    mintConfig={[
        {
            type: "secondary-eth",
            contractAddress: "0xbC…307e",
            tokenId: "7777"
        }
    ]}
/>

// New - EVM Secondary Sale
<CrossmintProvider apiKey={clientApiKey}>
    <CrossmintEmbeddedCheckout
        lineItems={{
            tokenLocator: "ethereum:0xbC…307e:7777",
            callData: {
                totalPrice: "0.1"
            }
        }}
    />
</CrossmintProvider>

// Old - Solana Secondary Sale
<CrossmintPaymentElement
    projectId={projectId}
    collectionId={collectionId}
    environment={environment}
    mintConfig={{
        mintHash: "4oDd…x6NC",
        buyerCreatorRoyaltyPercent: 100,
        type: "solana-secondary"
    }}
/>

// New - Solana Secondary Sale
<CrossmintProvider apiKey={clientApiKey}>
    <CrossmintEmbeddedCheckout
        lineItems={{
            tokenLocator: "solana:4oDd…x6NC",
            callData: {
                totalPrice: "0.1",
                buyerCreatorRoyaltyPercent: 100
            }
        }}
    />
</CrossmintProvider>
```

<Note>Don't forget to add payment configuration to enable crypto/fiat payments:</Note>

```tsx theme={null}
payment={{
    crypto: { enabled: true },
    fiat: { enabled: true }
}}
```

## Advanced Features

Once you have the basic setup working, V3 now supports these additional features:

### Payment Methods

Enable crypto and fiat payment options, and set preferred chains and currencies for your users. Learn more in our [Payment Methods guide](/payments/embedded/guides/payment-methods).

```tsx theme={null}
payment={{
    crypto: {
        enabled: true,
        defaultChain: "polygon",
    },
    fiat: {
        enabled: true,
        allowedMethods: {
            card: true,
            applePay: true,
            googlePay: true,
        }
    }
}}
```

<Note>
  To enable Apple Pay, you'll need to follow our [Apple Pay setup guide](/payments/embedded/guides/apple-pay). Apple
  Pay is now rendered directly on your site in V3, which requires domain verification through Apple.
</Note>

### UI Customization

Customize colors, typography, and component styles to match your brand. Learn more in our [UI Customization guide](/payments/embedded/guides/ui-customization).

```tsx theme={null}
appearance={{
    variables: {
        fontSizeUnit: '1rem',
        borderRadius: '8px',
        colors: {
            backgroundPrimary: '#ffffff',
            textPrimary: '#000000',
        }
    }
}}
```

### Order Tracking

Embedded Checkout V3 now makes it easier to track order status using React hooks. Learn more in our [React hooks guide](/payments/embedded/guides/hooks).

Wrap your checkout component with `CrossmintCheckoutProvider` and use the `useCrossmintCheckout` hook:

```tsx theme={null}
import {
    CrossmintProvider,
    CrossmintCheckoutProvider,
    CrossmintEmbeddedCheckout,
    useCrossmintCheckout,
} from "@crossmint/client-sdk-react-ui";

const clientApiKey = process.env.NEXT_PUBLIC_CLIENT_API_KEY;
const collectionId = process.env.NEXT_PUBLIC_COLLECTION_ID;

function Checkout() {
    const { order } = useCrossmintCheckout();

    useEffect(() => {
        if (order && order.phase === "completed") {
            console.log("Purchase completed!");
            // Handle successful purchase
        }
    }, [order]);

    return (
        <CrossmintEmbeddedCheckout
            lineItems={[
                {
                    collectionLocator: `crossmint:${collectionId}`,
                    callData: {
                        totalPrice: "0.001",
                        quantity: 1,
                    },
                },
            ]}
            payment={{
                crypto: { enabled: true },
                fiat: { enabled: true },
            }}
        />
    );
}

// Wrap with both providers
function App() {
    return (
        <CrossmintProvider apiKey={clientApiKey}>
            <CrossmintCheckoutProvider>
                <Checkout />
            </CrossmintCheckoutProvider>
        </CrossmintProvider>
    );
}
```

Learn more about available hooks in our [React hooks guide](/payments/embedded/guides/hooks).

### Complete Example

A complete example combining all features:

```tsx theme={null}
<CrossmintProvider apiKey={clientApiKey}>
    <CrossmintEmbeddedCheckout
        lineItems={{
            collectionLocator: `crossmint:${collectionId}`,
            callData: {
                totalPrice: "0.001",
                quantity: 1,
            },
        }}
        payment={{
            crypto: {
                enabled: true,
                defaultChain: "polygon",
            },
            fiat: {
                enabled: true,
                allowedMethods: {
                    card: true,
                    applePay: true,
                    googlePay: true,
                },
            },
        }}
        recipient={{
            email: "buyer@example.com",
        }}
        appearance={{
            variables: {
                fontSizeUnit: "1rem",
                borderRadius: "8px",
                colors: {
                    backgroundPrimary: "#ffffff",
                    textPrimary: "#000000",
                },
            },
        }}
    />
</CrossmintProvider>
```

## Related Resources

* [Quickstart Guide](/payments/embedded/quickstart)
* [Custom Payer Guide](/payments/embedded/guides/custom-payer)
* [Payment Methods](/payments/embedded/guides/payment-methods)
* [UI Customization](/payments/embedded/guides/ui-customization)
