Skip to content
stablecoin-paymentsusdcdeveloper-guide
Joshua C.

Requesting USDC Payments with Onchain Settlement Links

Learn how to generate and send USDC payment request links that settle onchain to your wallet. Includes a worked example, code, and best practices.

Requesting USDC Payments with Onchain Settlement Links

Many businesses want to bill customers and receive stablecoins straight to their own wallets, without intermediaries holding funds. If you need to send a USDC payment request that settles onchain, directly to your wallet on Base, Ethereum, or Polygon, this guide covers the mechanics, from generating the link to confirming receipt.

How Onchain Payment Links Work

A payment link is a URL you send to a customer. When they open it, they see an invoice or payment request. The customer connects their wallet and confirms a USDC transfer. The funds move from their wallet to a settlement address you control. You do not take custody of their private keys, and they never share a seed phrase.

You can use payment links for one-time invoices, deposits, or ad hoc payments. The payer does not need to know your address in advance. They follow the link, review the terms, and sign the transaction. Once confirmed onchain, the payment is final.

Key Terms and Flow

  • Settlement address: The address that receives the USDC payment. You control this wallet.
  • Payment link: The URL you share with your customer, representing the request.
  • USDC token contract: The ERC-20 contract on the chosen chain (Base, Ethereum, or Polygon).
  • Invoice details: The amount, currency, description, and optional metadata.

The core flow: 1. You generate a payment link with the amount, your settlement address, and context. 2. The customer opens the link, connects their wallet, reviews the invoice, and signs a transaction. 3. USDC moves from their wallet to your settlement address. The transfer is visible onchain. 4. You receive the funds. No one can reverse the transaction after confirmation.

Generating a USDC Payment Request Link

To create a payment link, you need to: - Specify the chain (Base, Ethereum, or Polygon). - Specify your settlement address. - Set the USDC amount (using the correct decimal places). - Optionally, add a memo or invoice description.

Manual Example: ERC-20 Payment URI

The ERC-681 URI format lets you encode payment requests as a URL. Most wallets support this format.

Assume you want to request 125 USDC on Polygon, paid to your wallet 0xMerchantAddress....

USDC on Polygon: 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 (6 decimals).

Amount: 125 USDC = 125,000,000 (since USDC uses 6 decimals)

The URI looks like this:

ethereum:0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174/transfer?address=0xMerchantAddress&uint256=125000000&chainId=137

Or as a clickable link (encode as needed):

https://wallet.example.com/send?to=0xMerchantAddress&token=0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174&amount=125000000&chainId=137

You can also generate a QR code for the URI, making it easy to scan in wallet apps.

Programmatic Example: Generating a Payment Link

Most developers want to automate link generation. Here’s a code snippet in JavaScript:

const USDC_POLYGON = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
const merchantAddress = "0xMerchantAddress"; // Your wallet
const amountUSDC = 125;
const decimals = 6;
const amountRaw = (amountUSDC * (10 ** decimals)).toString();

const uri = `ethereum:${USDC_POLYGON}/transfer?address=${merchantAddress}&uint256=${amountRaw}&chainId=137`;
console.log(uri); // Use this as a QR code or payment link

You can adapt this code for Base or Ethereum by swapping the USDC contract address and chainId (Base: 8453, Ethereum: 1).

Sending the Payment Link

Share the payment URI or a link to your hosted checkout with your customer: - Email - Chat app - Embedded in your app or dashboard - QR code in person

When the payer opens the link, their wallet parses the details. They review the amount, destination, and network. They sign a USDC transfer. Funds arrive at your address once the transaction confirms.

What Happens When the Customer Pays

  • The wallet prompts the customer to sign a USDC transfer transaction.
  • If this is the first time paying USDC from that wallet, they may need to approve the USDC token for spending. This is a standard “approve” then “transfer” flow, but for direct transfers, no approval is needed, only for contracts.
  • When the transaction confirms, you have the funds. You do not wait for an offchain process. No one else can reverse the payment.
  • You can track the transaction hash and confirm onchain receipt.

Handling Payment Failures

Payments can fail if: - The customer does not have enough USDC. - The customer is paying on the wrong chain. - The wallet is not connected to the correct network. - Gas fees are not available in the customer’s wallet.

If a payment fails, the wallet usually shows an error. The payer can retry after fixing the problem (e.g., adding gas, switching networks, or topping up USDC).

You do not need to issue refunds or reversals for failed transactions. If the transfer does not appear onchain, no funds have moved. If you receive the USDC, it is final.

Tracking and Reconciling Payments

After you send a payment link, you want to know when the payment arrives.

  • Monitor your settlement address for incoming USDC transfers.
  • Use block explorers (Polygonscan, Etherscan, etc.) to search by address or transaction hash.
  • For high frequency or automated reconciliation, use the chain’s RPC or a webhook service to watch for incoming transfers.

You can also attach metadata (like an invoice ID) in your internal database, tying the payment link to a customer or order.

Example: Watch for USDC Transfers in JavaScript

This snippet uses ethers.js to watch for incoming USDC payments to your address on Polygon:

const { ethers } = require("ethers");

const provider = new ethers.providers.JsonRpcProvider("https://polygon-rpc.com");
const usdcAddress = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
const merchantAddress = "0xMerchantAddress";

const usdcAbi = [
  "event Transfer(address indexed from, address indexed to, uint256 value)"
];

const usdc = new ethers.Contract(usdcAddress, usdcAbi, provider);
usdc.on("Transfer", (from, to, value, event) => {
  if (to.toLowerCase() === merchantAddress.toLowerCase()) {
    console.log(`Received USDC: ${value.toString()} from ${from}`);
    // Match value to your invoice, mark as paid
  }
});

This lets you automate marking invoices as paid, or trigger a webhook in your backend.

Security and Best Practices

  • Only specify your own wallet as the settlement address. Never use an address you do not control.
  • Never ask customers for their private keys or seed phrases. Only request a standard USDC transfer.
  • Double-check the chain and contract address you use in the link.
  • USDC is fungible, but transfers are chain-specific. A payment on Polygon does not appear on Ethereum.
  • Use a new payment link (with a unique ID or memo) for each invoice if you want granular tracking.

Using Reclack for Payment Links and Settlement

At Reclack, we provide hosted payment links, invoices, and a customer portal for USDC payments. Our checkout lets your customers pay from their own wallets, on Base, Ethereum, or Polygon. We never take custody of funds, never ask for private keys, and every payment settles directly to your wallet. Each payment link shows the exact amount, destination, and network. You can track status, trigger webhooks, and reconcile payments in our dashboard. Learn more at reclack.com.

stablecoin-paymentsusdcdeveloper-guide