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

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.

What’s New in V3?

Better DX

React hooks, TypeScript support, and simpler APIs

Multiple Items

Sell multiple NFTs in a single checkout with individual delivery tracking

Enhanced UI

More customization options and better payment method support

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 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), while CrossmintCheckoutProvider manages order state and checkout flow.

<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
  • Determines environment automatically from your API key
  • Replaces event handlers with React hooks - see our Hooks guide

React Hooks for State Management

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

// 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:

<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:

// 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
            }
        }
    ]}
/>

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:

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

2. Update Dependencies

Upgrade the Crossmint React SDK to version 1.12.0 or above.

3. Update Import Statements

// 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):

# 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
The projectId and environment values are now automatically derived from the client-side API key.

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

// 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

// 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>
Don’t forget to add payment configuration to enable crypto/fiat payments:
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.

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

To enable Apple Pay, you’ll need to follow our Apple Pay setup guide. Apple Pay is now rendered directly on your site in V3, which requires domain verification through Apple.

UI Customization

Customize colors, typography, and component styles to match your brand. Learn more in our UI Customization guide.

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.

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

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.

Complete Example

A complete example combining all features:

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