Powered by Coinflow
Payments · Documentation
Operational

One-Time Purchase Integration - EVM Contract Settlement

This page is for advanced / cryptocurrency-native companies. If that’s not you, head back to the 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

Complete these steps before starting the integration.

Create your sandbox account

Register or login to your sandbox merchant account

Generate API keys

Create a sandbox API key for authentication

Add chargeback protection

Add the protection script to every page of your app

Whitelist your contract

Whitelist your EVM contract address for settlement.

Quick Reference

Authorization Headers

Header Description
Authorization Your API key from the merchant dashboard
x-coinflow-auth-user-id Unique customer ID from your system
x-coinflow-auth-session-key JWT token authorizing the payer (valid 24 hours)

Helpful Resources


Choose Your Implementation

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

  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..."
    }
  }
}'
{
  "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"
}

Embed in an iframe

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

window.addEventListener('message', (event) => {
  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

npm install @coinflowlabs/react

Step 2: Tokenize checkout parameters

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

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"
     }'
{
  "checkoutJwtToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

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

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 to match your brand from your dashboard
  2. Whitelist your domain 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.

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'
{
  "key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Session keys expire after 24 hours. Refresh them before expiration.

Step 2: Get pricing totals

Show the customer a quote including all fees.

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"
     }'
{
  "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 for implementation details.

Step 4: Tokenize checkout parameters

Encrypt checkout parameters to prevent tampering.

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"
     }'
{
  "checkoutJwtToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Step 5: Process the payment

For new cards:

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"
       }
     }'
{
  "paymentId": "f3fc8a34-680b-4b91-905b-1db5628bbb0e"
}

For saved cards:

Re-tokenize the saved card with CVV first (see card tokenization docs), then:

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"
     }'
{
  "paymentId": "0090c04b-1ae8-4672-a108-32874df36f11"
}

Step 6: Verify the payment (optional)

curl --request GET \
     --url https://api-sandbox.coinflow.cash/api/merchant/payments/enhanced/PAYMENT_ID \
     --header 'Authorization: YOUR_API_KEY' \
     --header 'accept: application/json'
{
  "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

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.

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"
     }'
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"
     }'
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
x-coinflow-client-ip Customer’s IPv4 address
user-agent Customer’s browser user agent

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


Next Steps

Test Your Integration

Use sandbox test cards to verify your implementation

Configure Webhooks

Receive real-time payment notifications

Go Live

Create your production merchant account

API Reference

Explore the complete API documentation