Enterprise feature. Contact us for access.
Crossmint’s Headless Checkout API allows developers to create a seamless onramp experience for users to purchase various crypto tokens (including USDC and other supported tokens) using their credit card while completing the necessary KYC (Know Your Customer) process. This guide walks you through the steps to implement this functionality in your application, with support for users across any geography.

1. Setup

  • Create a developer account in the Crossmint Console
  • Create a server-side API key with the orders.create and orders.read scopes enabled
    • Contact Crossmint Support to include your project in our allowlist

2. Create Order

Use the Create Order API to initiate the purchase process. Use the following token addresses for Solana USDC:
  • Staging: 4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU
  • Production: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Here’s an example API call:
const response = await fetch("https://staging.crossmint.com/api/2022-06-09/orders", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "x-api-key": "YOUR_API_KEY",
    },
    body: JSON.stringify({
        lineItems: [
            {
                tokenLocator: "solana:example-token-address", // Token address, e.g., USDC in staging: "solana:4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
                // production: "solana:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                executionParameters: {
                    mode: "exact-in",
                    amount: "2",
                },
            },
        ],
        payment: {
            method: "checkoutcom-flow",
            receiptEmail: "user@example.com",
        },
        recipient: {
            walletAddress: "example-wallet-address", // Replace with actual recipient wallet address
        },
    }),
});

const data = await response.json();

3. Check KYC Requirements

After creating an order, check the response for KYC requirements:
  • If payment.status is requires-kyc, direct your user through the KYC flow
  • If payment.status is awaiting-payment, the user has already completed KYC and can proceed

4. Complete KYC Process

Crossmint uses Persona for KYC (Know Your Customer) verification. The Persona SDK allows you to embed the verification flow directly into your application.

Embedded experience

Use the provided identifiers to specify which verification template to use (templateId), which user this verification applies to (referenceId), and which environment to connect to (environmentId).
📝 Note:
Customization of the KYC flow’s look-and-feel is an enterprise feature. Please contact Crossmint support to enable this feature.
import Persona from "persona";

const client = new Persona.Client({
    // Fill out from previous response
    templateId: "example-template-id",
    referenceId: "example-reference-id",
    environmentId: "example-environment-id",
    onReady: () => client.open(),
    onComplete: ({ inquiryId, status, fields }) => {
        console.log(`Sending finished inquiry ${inquiryId} to backend`);
    },
    onCancel: ({ inquiryId, sessionToken }) => console.log("onCancel"),
    onError: (error) => console.log(error),
});
⚠️ Warning: snippet code bellow is only intended for frontend apps (i.e React or Nextjs)
For a mobile integration, check Persona’s React Native guide.

Hosted experience

If you want to redirect users to a URL, opening it in a WebView, you can construct the proper Persona URL given the IDs above. Here is an URL example:
https://inquiry.withpersona.com/verify?inquiry-template-id=itmpl_eq9Za7FkEeqTiGwWUDRAihafYiku&reference-id=%7B%22referenceEntity%22%3A%7B%22type%22%3A%22userId%22%2C%22id%22%3A%22688a6cacdbb38888231282c2%22%7D%2C%22trigger%22%3A%7B%22type%22%3A%22order%22%2C%22orderId%22%3A%220454dfb6-29c1-419f-a96c-c32324f48e05%22%7D%7D&environment-id=env_YxXyTmeMbZrh6AaYSp79bbEm

5. Poll KYC Status

Poll Crossmint’s Get Order API, replacing {orderId} with the order ID received when initiating the payment, to check the status of the verification. Polling at reasonable intervals is recommended (i.e. every 5 seconds).
const checkOrderStatus = async (orderId) => {
    const response = await fetch(`https://staging.crossmint.com/api/2022-06-09/orders/${orderId}`, {
        method: "GET",
        headers: {
            "Content-Type": "application/json",
            "x-api-key": "YOUR_API_KEY",
        },
    });

    return await response.json();
};
The possible KYC status values are:
  • If payment.status is awaiting-payment, user has successfully completed KYC, proceeding to pay
  • If payment.status is rejected-kyc, verification was rejected and the user can’t onramp
  • If payment.status is manual-kyc, verification requires manual review and the user will be notified via email about its ultimate success or rejection

6. Execute Transactions

Initialize Checkout.com’s Flow component for Desktop or Mobile to render an embedded payment form using the payment session and public key obtained in the prior response.
// Example implementation using Checkout.com Flow component
const initializePayment = (checkoutcomPaymentSession, checkoutcomPublicKey) => {
    const checkout = new Checkout.Flow({
        publicKey: checkoutcomPublicKey,
        paymentSession: checkoutcomPaymentSession,
        onSuccess: (event) => {
            console.log("Payment successful", event);
            // Handle successful payment
        },
        onFailure: (event) => {
            console.log("Payment failed", event);
            // Handle payment failure
        },
    });

    checkout.mount("#payment-container");
};

7. Transaction Completion

Upon successful payment:
  • The purchased tokens (minus fees) are sent directly to the user’s wallet
  • User receives an email receipt from hello@crossmint.io