2b. One-Time Checkout Links

πŸ•’ This guide takes 20 minutes to create a fully functional checkout link.

A One-Time Checkout Link is a prebuilt checkout experience that is customized per buyer by providing a fixed price, email, wallet address, quantity, and more.

Each unique link allows at most one purchase and expires after the specified duration.

Use cases

  • Gate purchases via an off-chain allowlist. After verifying the buyer's identity on your app, navigate them to the checkout link.
  • Implement dynamic pricing by passing in the price for each checkout. This feature allows you to provide coupon codes, bulk discounts, and loyalty discounts.
  • Restrict the quantity of NFTs your buyers can purchase.
  • Directly email the checkout URL directly to the buyer's inbox.

πŸ“˜

Remember that the blockchain is public and anyone can call your contract's methods. Restrict Contract Calls to Paper to ensure that only Paper's float wallets are able to call your mint method.

Prerequisites

  • You have deployed your NFT smart contract to the blockchain.

Integration

  1. Register your contract on the Dashboard: Contracts page.
  2. When a buyer wants to make a purchase, call the API to create a One-Time Checkout Link (API reference).
    1. The request body allows you to pass in fields to customize this specific checkout session, including email, wallet address, mint method (to pass in different args or price). See the API reference for the full list of fields.
    2. This API returns a unique URL: https://withpaper.com/checkout-link-intent/...
  3. Navigate the user to this URL to complete their checkout.

Render the Checkout Link in a drawer (optional)

To keep buyers on your page, render your One-Time Checkout Link in a drawer:

  1. Install the JavaScript SDK with your preferred package manager.
    • npm install @paperxyz/js-client-sdk
    • yarn add @paperxyz/js-client-sdk
  2. Call the function renderPaperCheckoutLink when the buyer clicks your Buy now button.
import { renderPaperCheckoutLink } from "@paperxyz/js-client-sdk"

const openCheckout = () => renderPaperCheckoutLink({
  checkoutLinkUrl: "https://withpaper.com/checkout-link-intent/eyJhbGc...",
});

<button onClick={openCheckout}>Buy with Paper</button>

Customization

Set your checkout's button color, dark mode, or button shape when creating your Shareable Checkout Link.

Need further customization? You can append query parameters (URI-encoded, e.g. set the button color to #FF8822 by passing colorPrimary=%23FF8822).

Query ParamTypeDescription
colorPrimarystring
In hex, e.g. #6dcbb6
The primary brand color for buttons and links.
colorBackgroundstring
In hex, e.g. #163643
The background color of the page.
colorTextstring
In hex, e.g. #f0f0f0
The color for text on the page and UI elements.
borderRadiusnumber
In px, e.g. 0 for sharp corners, 12 for rounded corners, 24 for pill shape
The roundness of buttons and input elements.

Here's an example with the following query params:
?colorPrimary=%236dcbb6&colorBackground=%23163643&colorText=%23f0f0f0&borderRadius=2

FAQ

How do I restrict this checkout to my allowlisted buyers?

One-Time Checkout Links are generated on-demand, allowing you to gate access to a checkout link based on your backend's business logic. If the buyer is allowed to make a purchase, generate a unique link and navigate them to the URL. Otherwise, show them an error message.

This pattern allows you to restrict access by any criteria you want, such as:

  • Has followed your company on Twitter for more than 30 days
  • Has been in your Discord community for 30 days
  • Owns a specific NFT in their wallet
  • Verifies a student .edu email address
  • and more!

See Buyer Allowlists for more details on implementing off-chain allowlists.

How do I directly email the user this unique URL?

In the API request body, make sure to set these fields:

  • "email": <your buyer's email address>
  • "sendEmailOnCreation": true

How can I pass in a signature to my smart contract method?

Generate the signature on your backend. Paper does not handle any signature generation. This restriction is intentional to prevent Paper from generating mints without your consent and business logic.

If your contract is custom, pass the signature to the mintMethod field for the appropriate argument.

If your contract is thirdweb signature drop, pass the signature in the contractArgs field.

How can I provide dynamic pricing (e.g. bulk discounts or coupon codes)?

If your contract is custom, your API request body will include a mintMethod.payment object that sets the price to charge the buyer.

To offer a bulk discount, you can pass in a different price based on the quantity. Here's a simple example of a "buy 2 or more and get one free" logic:

const quantity = // ...get the amount user is purchasing

let priceInEth = 0.1 * quantity
if (quantity >= 2) {
  price -= 0.1
}

const requestBody = {
  // ...
  quantity: quantity,
  mintMethod: {
    payment: {
      value: priceInEth,
      currency: "ETH"
    }
  }
}
// Call the "Create One-Time Checkout Link" API

Please test your integration to ensure your contract accepts different prices! Paper will send your contract the amount in mintMethod.payment and if that does not match what your mint method expects, the transaction will fail.

If your smart contract is thirdweb signature drop, generate the signature with the price in the payload and provide this payload in the contractArgs field.