DEV Community

Cover image for How to Verify USDC Payments on Base Without a Payment Processor
Mario Semper
Mario Semper

Posted on • Originally published at paragraph.com

How to Verify USDC Payments on Base Without a Payment Processor

The Problem Nobody Talks About

You want to accept a $10,000 USDC payment. You have two options:

Option A: Integrate a payment processor like Coinbase Commerce. Set up an account, embed their checkout widget, handle their SDK. Pay $100 in fees (1%).

Option B: Build your own blockchain listener. Learn ethers.js, subscribe to USDC transfer events, handle reorgs, confirmations, edge cases. Two weeks of work, minimum.

There's no middle ground. No service that just tells you: "Yes, this specific payment arrived."

Until now.


What If Verification Was a Simple API Call?

PayWatcher is a verification layer for stablecoin payments on Base. It doesn't process payments. It doesn't touch your funds. It doesn't require a checkout flow.

You tell it what payment you expect. It watches the blockchain. When the payment arrives, you get a webhook.

That's it.

Here's the cost comparison for verifying a $10,000 USDC transfer:

Service Fee Model
Coinbase Commerce $100.00 1% of transaction
NOWPayments $50.00 0.5% of transaction
PayWatcher $0.05 Flat fee, always

The fee is the same whether you're verifying $1 or $1,000,000.


How It Works (3 Steps)

Step 1: Create a Payment Intent

Tell PayWatcher what payment you're expecting:

curl -X POST https://api.paywatcher.dev/v1/payments \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "10000.00",
    "token": "USDC",
    "network": "base",
    "recipient": "0xYourWalletAddress",
    "webhook_url": "https://yourapp.com/webhook/payment",
    "reference": "invoice-2026-001"
  }'
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "id": "pay_abc123",
  "status": "watching",
  "unique_amount": "10000.03",
  "expires_at": "2026-02-23T12:00:00Z"
}
Enter fullscreen mode Exit fullscreen mode

Notice the unique_amount? PayWatcher adds a few cents to make your payment uniquely identifiable on-chain. Your customer sends $10,000.03 instead of $10,000.00 — and that tiny difference is how we match the exact transfer to your intent.

Step 2: Your Customer Sends USDC

Your customer sends USDC directly to your wallet. No checkout page, no intermediary, no redirect. Just a standard USDC transfer on Base.

You keep 100% of the payment. PayWatcher never has custody.

Step 3: Get Notified

When the transfer is confirmed on Base, PayWatcher fires a webhook:

{
  "event": "payment.confirmed",
  "payment_id": "pay_abc123",
  "reference": "invoice-2026-001",
  "amount": "10000.03",
  "token": "USDC",
  "network": "base",
  "tx_hash": "0xabc...def",
  "confirmed_at": "2026-02-22T10:30:00Z"
}
Enter fullscreen mode Exit fullscreen mode

Your backend processes the webhook, marks the invoice as paid, and you're done. No polling, no manual checking on Basescan.


JavaScript Example

Here's a minimal Node.js integration:

// Create a payment intent
const response = await fetch('https://api.paywatcher.dev/v1/payments', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.PAYWATCHER_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: '500.00',
    token: 'USDC',
    network: 'base',
    recipient: '0xYourWallet',
    webhook_url: 'https://yourapp.com/api/webhook',
    reference: `order-${orderId}`
  })
});

const payment = await response.json();
// Show payment.unique_amount to your customer
Enter fullscreen mode Exit fullscreen mode

And the webhook handler:

// Express webhook endpoint
app.post('/api/webhook', (req, res) => {
  const { event, reference, amount, tx_hash } = req.body;

  if (event === 'payment.confirmed') {
    // Mark order as paid
    await db.orders.update({
      where: { reference },
      data: { status: 'paid', tx_hash }
    });
  }

  res.status(200).send('ok');
});
Enter fullscreen mode Exit fullscreen mode

When to Use PayWatcher (and When Not To)

Use PayWatcher when:

  • You accept USDC payments and want automatic confirmation
  • You don't want to give up 0.5–1% per transaction
  • You need a non-custodial solution (regulatory, preference, or principle)
  • You want webhook notifications instead of polling Basescan
  • You're building on Base

Don't use PayWatcher when:

  • You need fiat on/off ramps (use Coinbase Commerce or Stripe)
  • You need multi-currency checkout flows
  • You want a hosted payment page (PayWatcher is API-only)

PayWatcher is verification, not processing. We don't hold, transfer, or have custody of funds.


What's Unique About This Approach?

Most crypto payment solutions are trying to be the next Stripe for crypto — full checkout flows, currency conversion, custody, settlement. That's valuable for some use cases.

But if you're already comfortable with USDC on Base, you don't need all that. You need someone to watch the blockchain and tell you when money arrived. That's a fundamentally different service, and it should be priced differently.

A flat $0.05 per verification instead of a percentage of the transaction value.


Architecture Overview

Your App                    PayWatcher                  Base Network
   │                            │                            │
   ├── POST /v1/payments ──────►│                            │
   │   (create intent)          │                            │
   │◄── { unique_amount } ──────┤                            │
   │                            │                            │
   │   Show amount to customer  │                            │
   │                            │                            │
   │                            │◄── Monitor USDC transfers ─┤
   │                            │    (event listener)        │
   │                            │                            │
   │                            │── Match transfer to intent │
   │                            │── Wait for confirmations   │
   │                            │                            │
   │◄── Webhook: confirmed ─────┤                            │
   │                            │                            │
   └── Process payment          │                            │
Enter fullscreen mode Exit fullscreen mode

PayWatcher sits between your application and the blockchain. It handles the complexity of monitoring transfers, matching amounts, waiting for confirmations, and handling edge cases like reorgs — so you don't have to.


Try It

PayWatcher is live on Base. We're onboarding early testers now.

Free tier: 50 verifications/month — enough to test and validate your integration.

Request API Access
Read the Docs

Built by masemIT — we also build ChainSights, identity-first analytics for DAOs.


Questions? Reach out on Farcaster or X.

Top comments (0)