🕒 This guide takes 60 minutes to embed a credit card checkout on your app.

CheckoutWithCard embeds a form on your app that accepts credit/debit card, Apple Pay, and Google Pay.

This component also handles:

  • Apple Pay and Google Pay options, if supported
  • Bot and anti-fraud detection
  • 3D Secure prompted by the issuing bank, if necessary
  • KYC of the buyer, if necessary



Try a demo!


This SDK is available in ReactJS and JavaScript.

Integration: ReactJS

  1. Install the ReactJS SDK:
    npm install @paperxyz/react-client-sdk
    yarn add @paperxyz/react-client-sdk
  2. Copy your API key from Developer Dashboard: Developers and contract ID from Developer Dashboard: Contracts.
  3. To begin a buyer session, create an SDK Client Secret via a backend API call. You'll provide some buyer info and configure checkout behavior.
  4. On your frontend, render the CheckoutWithCard component with this SDK client secret.

Example code


const resp = await fetch("https://withpaper.com/api/2022-08-12/checkout-sdk-intent", {
  method: "POST",
  headers: { "Authorization": "Bearer MY_API_KEY" },
  body: JSON.stringify({
    contractId: "MY_CONTRACT_ID",
    walletAddress: "0x...",
if (resp.ok) {
  const { sdkClientSecret } = await resp.json();
  // Pass this sdkClientSecret to your frontend 👇


import { CheckoutWithCard } from "@paperxyz/react-client-sdk";
  onPaymentSuccess={(result) => {
    console.log("Payment successful.");

CheckoutWithCard props

sdkClientSecret *stringThe SDK Client Secret returned from the Create Checkout Elements Client Secret API.
onPaymentSuccess *({
id: string;
}) => void
This method is called after the payment has been submitted for processing.

This payment may still be rejected by the cardholder's bank.
onError(PaperSDKError) => voidThis method is called when an error is encountered.
quantity: number;
unitPrice: PriceDetail;
networkFees: PriceDetail;
serviceFees: PriceDetail;
total: PriceDetail;
}) => void

Where PriceDetail is
display: string;
valueInSubunits: number;
currency: string;
This method is called when the price is updated or loaded for the first time. This summary is helpful to show a granular price breakdown.
Valid values: en, fr, es, it, de, ja, ko, zh
The language to show text in.
Defaults to en.
optionsobjectCustomize component styling. See Customization.

Integration: JavaScript

  1. Install the JavaScript SDK with your preferred package manager.
    • npm install @paperxyz/js-client-sdk
    • yarn add @paperxyz/js-client-sdk
  2. Copy your API key from the Developer Dashboard: Developers page.
  3. When a buyer wants to make a purchase, create a Checkout Elements Client Secret (API reference) to generate an SDK Client Secret. You will provide some buyer information and configure behavior via this API.
  4. Call createCheckoutWithCardElement to insert the iframe on your page. Pass the SDK Client Secret to this component.
    1. If you don't provide elementOrId, this call returns an iframe element for you to insert into your page.

Example code

import { createCheckoutWithCardElement } from "@paperxyz/js-client-sdk";

// Assume a container exists:
//      <div id="paper-checkout-container" width="380px" />
  sdkClientSecret: "MY_SDK_CLIENT_SECRET",
  elementOrId: "paper-checkout-container",
  appName: "My Web3 App",
  onError(error) {
    console.error("Payment error:", error);
  onPaymentSuccess({ id }) {
    console.log("Payment successful.");

// Alternatively, insert the iframe programmatically:
//      const iframe = createCheckoutWithCardElement(...)
//      document.getElementById('paper-checkout-container').appendChild(iframe);


sdkClientSecret *stringThe client secret returned from the Checkout SDK intent API.
elementOrIdstring | HTMLElementIf provided, the iframe will be appended this element.

You can pass in the DOM element or the id associated with the element.

A minimum width of 380px is recommended.
appNamestringIf provided, the wallet card will display your appName.
Valid values: en, fr, es, it, de, ja, ko, zh
The language to show text in.
Defaults to en.
optionobjectCustomize component styling. See Customization.
onLoad() => voidThis method is called when the iframe loads.
onError(error: PaperSDKError) => voidThis method is called when an error occurs during the payment process.
onPaymentSuccess(props : { id: string }) => voidThis method is called when the buyer has successfully paid.
onReview(props: { cardholderName: string, id: string }) => voidThis method is called after the user enters their card details.


The optional options argument allows you to customize the component's styling. All customization fields are optional.

options object

In hex, e.g. #cf3781
The primary brand color for buttons and links.
In hex, e.g. #cf3781
The background color of the page.
In hex, e.g. #cf3781
The color for text on the page and UI elements.
In px, e.g. 0 for sharp corners, 12 for rounded corners, 24 for pill shape
The roundness of buttons and input elements.
In hex, e.g. #cf3781
The border color of the input field.
In hex, e.g. #cf3781
The background color of the input field.


Here's an example component with the following props:

    colorBackground: '#fefae0',
    colorPrimary: '#606c38',
    colorText: '#283618',
    borderRadius: 6,
    inputBackgroundColor: '#faedcd',
    inputBorderColor: '#d4a373',


How do I prevent the 3D Secure or KYC modal from popping up behind my other frontend components?

The SDK uses a z-index of 10000 for these modals. If they are appearing behind other components, please lower your component's z-index values.