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)

Browser (SDK)

import { pay, getPaymentStatus } from '@base-org/account';

// Trigger a payment – user will see a popup from their wallet service
const { id } = await pay({
  amount: '1.00',           // USD amount (we quote USDC internally)
  to:    '0xRecipient',     // your address
  testnet: true            // set false for Mainnet
});

// Option 1: Poll until mined
const { status } = await getPaymentStatus({ 
  id,
  testnet: true            // MUST match the testnet setting used in pay()
});
if (status === 'completed') console.log('🎉 payment settled');
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:
await pay({
  amount: '25.00',
  to: '0xRecipient',
  payerInfo: {
    requests: [
      { type: 'email' },
      { type: 'phoneNumber', optional: true }
    ],
    callbackURL: 'https://your-api.com/validate' // Optional - for server-side validation
  }
});
Supported request types:
typereturns
emailstring
name{ firstName, familyName }
phoneNumber{ number, country }
physicalAddressfull address object
onchainAddressstring
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.

Polling example

Backend (SDK)
import { getPaymentStatus } from '@base-org/account';

export async function checkPayment(txId, testnet = false) {
  const status = await getPaymentStatus({ 
    id: txId,
    testnet  // Must match the testnet setting from the original pay() call
  });
  if (status.status === 'completed') {
    // fulfil order
  }
}

Add the Base Pay Button

Use the pre-built component for a native look-and-feel:
Checkout.tsx
import { BasePayButton } from '@base-org/account-ui/react';
import { pay } from '@base-org/account';

export function Checkout() {
  return (
    <BasePayButton
      colorScheme="light"
      onClick={() => pay({ amount: '5.00', to: '0xRecipient' })}
    />
  );
}
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.