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

# Pay with Card - Memecoins

> Create a fully customized memecoin checkout experience that accepts credit cards

export const CreateApiKey = ({client, scopes, useJwt}) => {
  const scopeStr = (scope, index) => {
    if (index === scopes?.length - 1) {
      return <code>{scope}</code>;
    } else {
      return <span>
                    <code>{scope}</code>
                    <span>, </span>
                </span>;
    }
  };
  const localHostInAuthOrigin = client ? "http://localhost:3000" : "";
  return <div>
            <p>Navigate to the "Integrate" section on the left navigation bar, and ensure you're on the "API Keys" tab.</p>
            <p>
                Within the <b>{client ? "Client-side" : "Server-side"} keys</b> section, click the "Create new key"
                button in the top right.
            </p>
            {client ? <p>
                    On the authorized origins section, enter <code>http://localhost:3000</code> and click "Add origin".
                </p> : ""}
            {scopes && scopes.length > 0 && <p>
                    Next, check the scopes labeled {scopes.map((scope, index) => <span key={index}>{scopeStr(scope, index)}</span>)}.
                </p>}
            {useJwt ? <p>
                    Check the "JWT Auth" box.
                </p> : ""}
            <p>
                Finally, create your key and save it for subsequent steps.
            </p>
        </div>;
};

<Snippet file="enterprise-feature.mdx" />

## Introduction

This guide will show you how to accept credit card payments using Crossmint's Headless Checkout API for memecoin sales. You'll learn how to:

* Set up credit card payments for Solana memecoin purchases in JavaScript
* Implement a checkout UI
* Track order status and delivery

<Tip>
  For a faster, embedded checkout solution with minimal setup time, see our [embedded memecoin
  quickstart](/payments/embedded/quickstarts/credit-card-memecoin).
</Tip>

<Snippet file="memecoins_important_notes.mdx" />

<Snippet file="memecoins_prerequisites.mdx" />

<Snippet file="memecoins_fungible_token_specification.mdx" />

## Headless Memecoin Checkout

The headless checkout API allows complete control over your checkout experience, including:

* Custom UI components and styling
* Custom payment flow sequences
* Integrated analytics and tracking
* Custom error handling and retry logic
* Branded confirmation pages

### Create an Order

The first step in the headless checkout process is to create an order. An order is an object datastructure that represents an intent to purchase in Crossmint's systems. This guide will create a basic order, and then update it with required info step-by-step.

<Note>
  You can also create the entire order in one API call if the necessary information is available at the time of order
  creation. This can be used for custom "one-click-checkout" experiences, should you wish to make them.
</Note>

**Endpoint:** `POST` `https://www.crossmint.com/api/2022-06-09/orders`

Refer to the complete **create order** API reference [here](/api-reference/headless/create-order).

<Note>
  Memecoins are now testable in staging using the xmeme token (`7EivYFyNfgGj8xbUymR7J4LuxUHLKRzpLaERHLvi7Dgu`). All
  other token purchases will fail in staging. For production launch with other tokens, contact our sales team.
</Note>

Use the JavaScript code snippet below to create a starting point for your order. Alternatively, use the API playground to explore and create your own order.

<CodeGroup>
  ```javascript Node.js theme={null}
  const apiKey = "your-server-api-key"; // CHANGE THIS TO YOUR SERVER API KEY
  const tokenId = "solana:7EivYFyNfgGj8xbUymR7J4LuxUHLKRzpLaERHLvi7Dgu"; // xmeme token for staging
  const deliveryAddress = "your-solana-wallet-address"; // CHANGE THIS TO YOUR RECEIVING SOLANA WALLET ADDRESS
  const receiptEmail = "your-email@example.com"; // CHANGE THIS TO YOUR EMAIL

  const options = {
      method: "POST",
      headers: {
          "x-api-key": apiKey,
          "Content-Type": "application/json",
      },
      body: JSON.stringify({
          lineItems: [
              {
                  tokenLocator: tokenId, // Token address in format solana:tokenAddress (e.g., solana:7EivYFyNfgGj8xbUymR7J4LuxUHLKRzpLaERHLvi7Dgu for xmeme token)
                  executionParameters: {
                      mode: "exact-in", // The execution method for the order. It tells Crossmint to operate in buying fungibles mode
                      amount: "1", // default currency USD
                      maxSlippageBps: "500", // Optional, or else default autogenerated slippage will be applied
                  },
              },
          ],
          payment: {
              method: "card",
              receiptEmail: receiptEmail,
          },
          recipient: {
              walletAddress: deliveryAddress,
          },
      }),
  };

  fetch("https://staging.crossmint.com/api/2022-06-09/orders", options)
      .then((response) => response.json())
      .then((response) => console.log(JSON.stringify(response, null, 2)))
      .catch((err) => console.error(err));
  ```

  ```json JSON theme={null}
  {
      "lineItems": [
          {
              "tokenLocator": "solana:tokenAddress",
              "executionParameters": {
                  "mode": "exact-in",
                  "amount": "1",
                  "maxSlippageBps": "500"
              }
          }
      ],
      "payment": {
          "method": "card",
          "receiptEmail": "receiptEmail"
      },
      "recipient": {
          "walletAddress": "deliveryAddress"
      }
  }
  ```

  For more details on tokenLocator formatting and other item selection options, see the [item selection page](/payments/headless/guides/item-selection#json-item-selection-examples).
</CodeGroup>

<Accordion title="Example Response">
  ```json theme={null}
  {
    "clientSecret": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmRlcklkZW50aWZpZXIiOiJlZDM0YTU3OS03ZmJjLTQ1MDktYjhkOC05ZTYxOTU0Y2Q1NTUiLCJpYXQiOjE3Mzk0MDI3NjEsImV4cCI6MTczOTQ4OTE2MX0.8AU0Y31lJhnQD2-vAXEZp3ZeMSyh_Wdm9An02Z5AW0M",
    "order": {
      "orderId": "ed34a579-7fbc-4509-b8d8-9e61954cd555",
      "phase": "payment",
      "locale": "en-US",
      "lineItems": [
        {
          "chain": "solana",
          "metadata": {
            "name": "xmeme",
            "description": "Token xmeme from the contract: 7EivYFyNfgGj8xbUymR7J4LuxUHLKRzpLaERHLvi7Dgu",
            "imageUrl": "https://arweave.net/VQrPjACwnQRmxdKBTqNwPiyo65x7LAT773t8Kd7YBzw"
          },
          "quote": {
            "status": "valid",
            "charges": {
              "unit": {
                "amount": "35.73",
                "currency": "usd"
              }
            },
            "totalPrice": {
              "amount": "1",
              "currency": "usd"
            },
            "quantityRange": {
              "lowerBound": "0.0265905",
              "upperBound": "0.0293895"
            }
          },
          "delivery": {
            "status": "awaiting-payment",
            "recipient": {
              "locator": "solana:BuWmGweapdysxU5VuUdi1RGoc4ibDG7TNirWjRtqF995",
              "walletAddress": "your-solana-wallet-address"
            }
          },
          "executionMode": "exact-in",
          "maxSlippageBps": "500",
          "executionParams": {
            "mintHash": "7EivYFyNfgGj8xbUymR7J4LuxUHLKRzpLaERHLvi7Dgu",
            "mode": "exact-in",
            "amount": "1",
            "maxSlippageBps": "500"
          }
        }
      ],
      "quote": {
        "status": "valid",
        "quotedAt": "2025-02-12T23:26:00.397Z",
        "expiresAt": "2025-02-12T23:26:30.397Z",
        "totalPrice": {
          "amount": "1",
          "currency": "usd"
        }
      },
      "payment": {
        "status": "awaiting-payment",
        "method": "basis-theory",
        "currency": "usd",
        "preparation": {},
        "receiptEmail": "test@example.com"
      }
    }
  }
  ```
</Accordion>

Note the following parameters in the request body:

* `maxSlippageBps`: Optional, or else default autogenerated slippage will be applied
* `receiptEmail`: Required for credit card payments to deliver receipt
* `executionParameters.mode`: The execution method for the order. "exact-out" is for NFTs, "exact-in" is for fungible tokens

### Render the Crossmint Embedded Component

After creating an order, you'll need to render the Crossmint Embedded Component to collect payment information. This secure, embeddable UI component lets you accept payment methods, validates input, and handles errors:

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

export function MyCheckoutPage({ clientSecret, order, recipientWalletAddress, receiptEmail }) {
  return (
    <div className="w-full">
      <CrossmintProvider apiKey="<YOUR CLIENT SIDE KEY>">
        <CrossmintEmbeddedCheckout 
          recipient={{ walletAddress: recipientWalletAddress}}
          clientSecret={clientSecret}
          orderId={order.orderId}
          payment={{
            crypto: {
                enabled: false,
            },
            fiat: {
                enabled: true,
            },
            defaultMethod: "fiat",
            receiptEmail: receiptEmail,
          }}
          appearance={{
              rules: {
                  DestinationInput: {
                      display: "hidden",
                  },
                  ReceiptEmailInput: {
                      display: "hidden",
                  },
              },
          }} />
      </CrossmintProvider>
    </div>
  );
}
```

<Tip>
  The `CrossmintEmbeddedCheckout` component is highly customizable. You can adjust colors, styling, layout, and behavior to match your brand. Learn more in our [UI customization guide](/payments/embedded/guides/ui-customization).
</Tip>

### Poll for Status Updates

After making the payment, you'll need to poll the [Get Order API](/api-reference/headless/get-order) to check on the delivery status and present this information to your user.

**Endpoint:** `GET` `https://staging.crossmint.com/api/2022-06-09/orders/<orderId>`

Refer to the complete **get order** API reference [here](/api-reference/headless/get-order).

**Example Response:**

```json theme={null}
{
    "id": "order_xyz",
    "status": "completed",
    "phases": {
        "quote": { "status": "completed" },
        "payment": { "status": "completed" },
        "delivery": { "status": "completed", "details": "Memecoins delivered to specified wallet" }
    }
}
```

### Handling Refunded Payments

When polling for order status, you may encounter a situation where `payment.status` is `completed` but the order also contains a `payment.refunded` property. This indicates that the payment was initially successful but has since been refunded.

```json theme={null}
{
    "order": {
        "payment": {
            "status": "completed",
            "refunded": {
                "amount": "1.00",
                "currency": "usd",
                "txId": "0x1234abcd...",
                "chain": "ethereum"
            }
        }
    }
}
```

The `payment.refunded` object includes the following fields:

* `amount`: The amount that was refunded
* `currency`: The currency of the refund
* `txId`: The on-chain transaction ID the refund was sent in
* `chain`: The blockchain where the refund transaction occurred

When you encounter this state, your application should:

1. Display an appropriate message to the user indicating that their payment was refunded
2. Provide the transaction ID (`txId`) so users can verify the refund on-chain
3. Prevent any further actions related to the order (such as delivery expectations)
4. Provide options for the user to place a new order if desired

This state typically occurs when there was an issue with processing the order after payment was received, such as insufficient liquidity for memecoin purchases or compliance issues.

🎉 Congratulations! You've successfully set up your headless memecoin checkout. Check out the [Next Steps](#next-steps) section below to learn how to customize your integration.

<Snippet file="memecoins-understanding-the-code.mdx" />

## Next Steps

<CardGroup cols={2}>
  <Card title="Design Your UI" icon="paintbrush" href="/payments/headless/guides/design-your-ui">
    Learn how to design your headless checkout experience
  </Card>

  <Card title="Handle Webhooks" icon="bell" href="/payments/advanced/webhooks">
    Implement webhook handling for order updates
  </Card>
</CardGroup>

<Snippet file="memecoins_order_lifecycle.mdx" />

## Refreshing Orders

For memecoin checkout, the order expiration is 1 minute. The Crossmint Embedded Checkout will automatically refresh the order for you when the time comes. Alternatively, you can either create a new order or use the refresh quote API:

```javascript theme={null}
async refreshOrder(orderId, clientSecret) {
  try {
    const ancestorOrigins = typeof window !== 'undefined' && window.location?.ancestorOrigins
      ? Array.from(window.location.ancestorOrigins)
      : [];

    const response = await this.callApi(`2022-06-09/orders/${orderId}/refresh`, "POST", {}, {
      "authorization": `${clientSecret}`,
      "x-ancestor-origins": JSON.stringify(ancestorOrigins)
    });

    const parsed = await response.json();
    return parsed;
  } catch (error) {
    console.error("Error refreshing quote:", error);
    throw error;
  }
}
```

<Snippet file="memecoins_faq.mdx" />
