Skip to main content

Why Base Pay?

USDC on Base is a fully-backed digital dollar that settles in seconds and costs pennies in gas. Base Pay lets you accept those dollars with a single click—no cards, no FX fees, no chargebacks.
  • Any user can pay – works with every Base Account (smart-wallet) out of the box.
  • USDC, not gas – you charge in dollars; gas sponsorship is handled automatically.
  • Fast – most payments confirm in <2 seconds on Base.
  • Funded accounts – users pay with USDC from their Base Account or Coinbase Account.
  • No extra fees – you receive the full amount.
Please Follow the Brand GuidelinesIf you intend on using the BasePayButton, please follow the Brand Guidelines to ensure consistency across your application.

Client-side (Browser SDK)

Interactive Playground: Try out the pay() and getPaymentStatus() functions in our Base Pay SDK Playground before integrating them into your app.
Browser (SDK)
Important: The testnet parameter in getPaymentStatus() must match the value used in the original pay() call. If you initiated a payment on testnet with testnet: true, you must also pass testnet: true when checking its status.
This is what the user will see when prompted to pay:
Pay Popup

Collect user information (optional)

Need an email, phone, or shipping address at checkout? Pass a payerInfo object:
Supported request types:
Required by default — set optional: true to avoid aborting the payment if the user declines.
How to validate the user’s information?You can use the callbackURL to validate the user’s information on the server side.Learn more about this in the callbackURL reference.

Server Side

When accepting payments, your backend must validate transactions and user info received from the frontend. This section covers two critical aspects: verifying transaction completion and validating user information.

Verify User Transaction

Use getPaymentStatus() on your backend to confirm that a payment has been completed before fulfilling orders. Never trust payment confirmations from the frontend alone.
Backend (SDK)
Prevent Replay and Impersonation Attacks
  • Replay attacks: A malicious user could submit the same valid transaction ID multiple times. Always track processed transaction IDs in your database.
  • Impersonation attacks: A malicious user could submit someone else’s transaction ID to fulfill their own order. Always verify that the payment sender matches the authenticated user.
Here’s an example that prevents both attack vectors:
Backend (with replay protection)
Database recommendations for tracking transactions:
  • Store the transaction ID, order ID, sender address, amount, timestamp, and fulfillment status
  • Use a unique constraint on the transaction ID to prevent duplicates
  • Consider adding an index on the transaction ID for fast lookups

Validate User Info

If you’re collecting user information (email, phone, shipping address) during checkout, use the callbackURL parameter to validate this data server-side before the transaction is submitted. Your callback endpoint receives the user’s information and must respond with either a success or error response:
Backend (validation endpoint)
The callback is invoked before the transaction is submitted. If you return errors, the user is prompted to correct their information. If you return success, the transaction proceeds.
For complete details on the callback request/response format and all supported data types, see the dataCallback reference.

Add the Base Pay Button

Use the pre-built component for a native look-and-feel:
Checkout.tsx
See full props and theming options in the Button Reference and Brand Guidelines.
Please Follow the Brand GuidelinesIf you intend on using the BasePayButton, please follow the Brand Guidelines to ensure consistency across your application.

Test on Base Sepolia

  1. Get test USDC from the Circle Faucet (select “Base Sepolia”).
  2. Pass testnet: true in your pay() and getPaymentStatus() calls.
  3. Use Sepolia BaseScan to watch the transaction.