> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.coinflow.cash/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.coinflow.cash/_mcp/server.

# One-Time Purchase Integration - EVM Contract Settlement

> **Warning**
>
> **This page is for advanced / cryptocurrency-native companies.** If that's not you, head back to the [Quickstart](/guides/getting-started/quickstart) for the standard flows.

This guide walks you through integrating Coinflow checkout to accept one-time credit card purchases with USDC settlement to your whitelisted EVM contract (Base, Polygon, Arbitrum, etc.).

## Prerequisites

> **Warning**
>
> Complete these steps before starting the integration.

#### Create your sandbox account

[Register](https://sandbox-merchant.coinflow.cash/register) or [login](https://sandbox-merchant.coinflow.cash/login) to your sandbox merchant account

#### Generate API keys

[Create a sandbox API key](https://sandbox-merchant.coinflow.cash/api-keys) for authentication

#### Add chargeback protection

[Add the protection script](/guides/checkout/payment-security-risk-management/fraud-protection/implement-chargeback-protection#how-to-add-chargeback-protection) to every page of your app

#### Whitelist your contract

[Whitelist your EVM contract address](https://sandbox-merchant.coinflow.cash/whitelist-request) for settlement.

## Quick Reference

#### Authorization Headers

| Header                        | Description                                                                                                     |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `Authorization`               | Your API key from [the merchant dashboard](https://sandbox-merchant.coinflow.cash/api-keys)                     |
| `x-coinflow-auth-user-id`     | Unique customer ID from your system                                                                             |
| `x-coinflow-auth-session-key` | [JWT token](/api-reference/api-reference/authentication/get-session-key) authorizing the payer (valid 24 hours) |

#### Helpful Resources

* [Test card numbers for sandbox](/guides/checkout/testing/testing-credit-cards)
* [Checkout webhooks](/guides/developer-resources/webhooks/checkout-webhooks)
* [Custom branding](/guides/developer-resources/custom-branding)

---

## Choose Your Implementation

#### Checkout Link

Best for simple integrations. Generate a hosted checkout URL to redirect users or embed in an iframe.

### Step 1: Generate the checkout link

**`Request`**

```bash title="Request"
  curl -X POST https://api-sandbox.coinflow.cash/api/checkout/link \
    -H "x-coinflow-auth-user-id: payer123" \
    -H "Authorization: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
  "email": "payer123@gmail.com",
  "subtotal": {
    "cents": 500,
    "currency": "USD"
  },
  "blockchain": "polygon",
  "transactionData": {
    "transaction": {
      "data": "0x...",
      "to": "0x..."
    }
  }
}'
```

**`Response`**

```json title="Response"
{
  "link": "https://sandbox.coinflow.cash/polygon/purchase-v2/YOUR_MERCHANT_ID?sessionKey=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21lcklkIjoicGF5ZXIxMjMiLCJtZXJjaGFudElkIjoibWVsbG8iLCJpYXQiOjE3NjU5MjQ5NTIsImV4cCI6MTc2NjAxMTM1Mn0.exsrE2_FVoOAiVVBm8uTol31zsPyc_voRTR27YuZUjo&cents=500&currency=USD&email=payer123%40gmail.com&useHeightChange=true&jwtToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoi456C4oKW26LXgtGg5piC44CU7IGmYOOGgFx1ZDgwYeyAu8SA54yW6qWJ6oGA6bCEy4Loi5vlgInoqZvhhojDkOiKgOeZmMS407DDoNeF4KyA4oiB4LCl7KaCzJrhsKzEse6YouyEplx1ZGRjNO-Co-yqmOmwuueItO6Jg-mGluujleqko-mdicS5XHVkYmE57Lqn6I2u46GY4KKE5qGY4aGW5qmo5auU6qm454CY46Ca4qCE5qGy5KCY4rGw4rCc5KCI6Jm-5aG01LjohbjnkI7ErOqzhOGrlOmjtOWhqOeQuNCJ56CY4aCW5pS47JCM55KE4rCs74WY7ZCa4aKl4KGo4qGh6JWa4rm45quE5Lmw7rKs56Gy6ZeU5aOa4qGk6aq45KC17ZCo34vho4jouKvlo6zrmqbrm4jnkITisYjnkbTrk4TlroTsvJrmsLjni7TpjprmjIflp6volrDqgJ5cdWQ4NWLij4fEt-qDoO6AuuKQnOGvreiAoeaErOGguOC4jdKEXHVkOWM455CY46S85I2F5oWh6ZSQ56Gt4biF6J6C4K615oq-4Ymt5LOnzoDhgpDojL3NjeGGoeKBqO6RieScnOC1ieaAo-GmtOWhh-iCsuWZhOihoei6peOoi-GvgeqKoeyBjOi5jeKWkeK7tuKGi-SZqOGSrumAp-KQtu-ksOuztOeyrey9geGhqO6hnC_pgIAiLCJtZXJjaGFudElkIjoibWVsbG8iLCJpZGVtcG90ZW5jeUtleSI6IklLMTY5ZDEwNmMtZDQxMi00YWZhLWFhZTQtMTg3ZTQxM2E3M2M4Iiwic3VidG90YWwiOnsiY2VudHMiOjUwMCwiY3VycmVuY3kiOiJVU0QifSwiaWF0IjoxNzY1OTI0OTUyLCJleHAiOjE3NjU5MjY3NTJ9.2w0_tNOzv58drmQTSSpeqPxpmFCku31mWqVpF65PXhU"
}
```

### Step 2: Use the checkout link

**Embed in an iframe**

```html
<iframe
  allow="payment"
  src="CHECKOUT_LINK_FROM_STEP_1"
  style="width: 100%; height: 600px; border: none;"
/>
```

### Step 3: Handle success events

Listen for payment completion when using an iframe:

```javascript
window.addEventListener('message', (event) => {
  // Use 'https://coinflow.cash' in production.
  if (event.origin !== 'https://sandbox.coinflow.cash') return;
  if (typeof event.data === 'string') {
    const data = JSON.parse(event.data);
    if (data.data === 'success') {
      console.log('Payment ID:', data.info.paymentId);
      // Handle successful payment
    }
  }
});
```

#### React SDK

Best for React applications. Provides a pre-built checkout component.

### Step 1: Install the SDK

```bash
npm install @coinflowlabs/react
```

### Step 2: Tokenize checkout parameters

Encrypt checkout parameters to prevent tampering. Call this from your backend.

**`Request`**

```bash title="Request"
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/checkout/jwt-token \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
       "webhookInfo": {
         "nftId": "123abc"
       },
       "subtotal": {
         "currency": "USD",
         "cents": 500
       },
       "transactionData": {
         "transaction": {
           "data": "0x...",
           "to": "0x..."
         }
       },
       "email": "customer@example.com",
       "blockchain": "base",
       "chargebackProtectionData": [{
         "productType": "inGameProduct",
         "productName": "NFT Item",
         "quantity": 1,
         "rawProductData": {
           "description": "A digital collectible"
         }
       }],
       "deviceId": "123456789"
     }'
```

**`Response`**

```json title="Response"
{
  "checkoutJwtToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

> **Info**
>
> Replace `transactionData.transaction.data` with your contract function call data and `transactionData.transaction.to` with your whitelisted contract address.

### Step 3: Render the checkout component

```tsx
import { CoinflowPurchase, Currency } from '@coinflowlabs/react';

function Checkout() {
  return (
    <CoinflowPurchase
      wallet={{
        address: "USER_WALLET_ADDRESS",
        sendTransaction: (transaction) => Promise.resolve({ hash: "0x..." }),
        signMessage: (message: string) => Promise.resolve("signature")
      }}
      merchantId="your-merchant-id"
      env="sandbox"
      blockchain="base"
      jwtToken="JWT_TOKEN_FROM_STEP_2"
      subtotal={{ cents: 500, currency: Currency.USD }}
      onSuccess={(paymentId) => {
        console.log('Payment successful:', paymentId);
      }}
    />
  );
}
```

### Step 4: Configure your dashboard

1. [Customize the UI](/guides/developer-resources/custom-branding) to match your brand from [your dashboard](https://sandbox-merchant.coinflow.cash/theme)
2. [Whitelist your domain](https://sandbox-merchant.coinflow.cash/frame-ancestors) to prevent unauthorized embedding

#### API Only

Best for custom checkout UIs. Full control over the payment flow.

### Step 1: Get a session key

Authorize the payer with a JWT token.

**`Request`**

```bash title="Request"
curl --request GET \
     --url https://api-sandbox.coinflow.cash/api/auth/session-key \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'accept: application/json' \
     --header 'x-coinflow-auth-user-id: customer123'
```

**`Response`**

```json title="Response"
{
  "key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

> **Warning**
>
> Session keys expire after 24 hours. Refresh them before expiration.

### Step 2: Get pricing totals

Show the customer a quote including all fees.

**`Request`**

```bash title="Request"
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/checkout/totals/YOUR_MERCHANT_ID \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-coinflow-auth-session-key: SESSION_KEY_FROM_STEP_1' \
     --data '{
       "subtotal": { "cents": 500 },
       "settlementType": "USDC"
     }'
```

**`Response`**

```json title="Response"
{
  "card": {
    "subtotal": { "cents": 500 },
    "creditCardFees": { "cents": 40 },
    "chargebackProtectionFees": { "cents": 0 },
    "gasFees": { "cents": 0 },
    "total": { "cents": 540 }
  }
}
```

### Step 3: Tokenize the credit card

Securely collect and tokenize the card number. See [PCI-compliant card tokenization](/recipes/recipes/pci-compliant-card-tokenization) for implementation details.

### Step 4: Tokenize checkout parameters

Encrypt checkout parameters to prevent tampering.

**`Request`**

```bash title="Request"
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/checkout/jwt-token \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
       "webhookInfo": { "nftId": "123abc" },
       "subtotal": { "currency": "USD", "cents": 500 },
       "transactionData": {
         "transaction": {
           "data": "0x...",
           "to": "0x..."
         }
       },
       "email": "customer@example.com",
       "blockchain": "base",
       "chargebackProtectionData": [{
         "productName": "NFT Item",
         "quantity": 1,
         "productType": "inGameProduct",
         "rawProductData": {
           "description": "A digital collectible"
         }
       }],
       "deviceId": "123456789"
     }'
```

**`Response`**

```json title="Response"
{
  "checkoutJwtToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

### Step 5: Process the payment

**For new cards:**

**`Request`**

```bash title="Request"
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/checkout/card/YOUR_MERCHANT_ID \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-coinflow-auth-session-key: SESSION_KEY' \
     --header 'x-coinflow-client-ip: CUSTOMER_IP_ADDRESS' \
     --header 'x-device-id: DEVICE_ID_FROM_PROTECTION_SCRIPT' \
     --header 'user-agent: CUSTOMER_USER_AGENT' \
     --data '{
       "subtotal": { "currency": "USD", "cents": 500 },
       "jwtToken": "JWT_TOKEN_FROM_STEP_4",
       "card": {
         "cardToken": "TOKENIZED_CARD_FROM_STEP_3",
         "expYear": "30",
         "expMonth": "10",
         "email": "customer@example.com",
         "firstName": "John",
         "lastName": "Doe",
         "address1": "123 Main St",
         "city": "New York",
         "zip": "10001",
         "state": "NY",
         "country": "US"
       }
     }'
```

**`Response`**

```json title="Response"
{
  "paymentId": "f3fc8a34-680b-4b91-905b-1db5628bbb0e"
}
```

**For saved cards:**

Re-tokenize the saved card with CVV first (see [card tokenization docs](/recipes/recipes/pci-compliant-card-tokenization)), then:

**`Request`**

```bash title="Request"
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/checkout/token/YOUR_MERCHANT_ID \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-coinflow-auth-session-key: SESSION_KEY' \
     --header 'x-coinflow-client-ip: CUSTOMER_IP_ADDRESS' \
     --header 'x-device-id: DEVICE_ID' \
     --data '{
       "subtotal": { "currency": "USD", "cents": 500 },
       "jwtToken": "JWT_TOKEN_FROM_STEP_4",
       "token": "REFRESHED_CARD_TOKEN"
     }'
```

**`Response`**

```json title="Response"
{
  "paymentId": "0090c04b-1ae8-4672-a108-32874df36f11"
}
```

### Step 6: Verify the payment (optional)

**`Request`**

```bash title="Request"
curl --request GET \
     --url https://api-sandbox.coinflow.cash/api/merchant/payments/enhanced/PAYMENT_ID \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'accept: application/json'
```

**`Response`**

```json title="Response"
{
  "info": {
    "firstName": "John",
    "lastName": "Doe",
    "email": "customer@example.com",
    "streetAddress": "123 Main St",
    "city": "New York",
    "state": "NY",
    "zip": "10001",
    "country": "US"
  }
}
```

---

## 3DS Authentication

After implementing basic checkout, add 3DS for enhanced security. Contact Coinflow to enable 3DS on your account.

#### [Complete Checkout with 3DS Challenge](/recipes/recipes/complete-checkout-with-3-ds-challenge-react)

Learn how to add 3DS to your new card and saved card requests

---

## Chargeback Protection

Improve approval rates and reduce fraud by sharing payer events with Coinflow.

### Send user events

Track key user actions throughout their journey on your app.

**`Sign Up`**

```bash title="Sign Up"
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/events \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'content-type: application/json' \
     --data '{
       "eventType": "SignUp",
       "customerId": "user-123-abc",
       "country": "US",
       "username": "johndoe",
       "email": "john@example.com",
       "firstName": "John",
       "lastName": "Doe"
     }'
```

**`Sign In`**

```bash title="Sign In"
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/events \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'content-type: application/json' \
     --data '{
       "eventType": "SignIn",
       "customerId": "user-123-abc",
       "country": "US",
       "email": "john@example.com"
     }'
```

**`Sign In Failure`**

```bash title="Sign In Failure"
curl --request POST \
     --url https://api-sandbox.coinflow.cash/api/events \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'content-type: application/json' \
     --data '{
       "eventType": "SignInFailure",
       "customerId": "user-123-abc",
       "country": "US",
       "email": "john@example.com",
       "failureReason": "Password Failed"
     }'
```

### Required headers for checkout

When processing payments, include these headers for chargeback protection:

| Header                 | Description                                                                                                                                           |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x-device-id`          | Device ID from the [chargeback protection script](/guides/checkout/payment-security-risk-management/fraud-protection/implement-chargeback-protection) |
| `x-coinflow-client-ip` | Customer's IPv4 address                                                                                                                               |
| `user-agent`           | Customer's browser user agent                                                                                                                         |

> **Info**
>
> On sandbox, use the test `partnerId` provided by the Coinflow team when configuring the protection script.

---

## Next Steps

#### [Test Your Integration](/guides/checkout/testing/testing-credit-cards)

Use sandbox test cards to verify your implementation

#### [Configure Webhooks](/guides/developer-resources/webhooks/checkout-webhooks)

Receive real-time payment notifications

#### [Go Live](https://merchant.coinflow.cash/register)

Create your production merchant account

#### [API Reference](/api-reference/api-reference/checkout/card-checkout)

Explore the complete API documentation