BaseLens / Guides

Verify a USDC payment on Base via API

If your service accepts USDC on Base, you eventually need to answer one question from a transaction hash: did the money arrive, and how much?

The problem

A raw receipt gives you logs and hex. To confirm a payment you must find the ERC-20 Transfer events, match the token contract, divide by the right number of decimals, check the receiver and make sure the transaction did not revert. Customers also paste hashes from the wrong chain or from a transaction that is still pending.

How /tx answers it

GET /tx?hash=0x... reads the transaction, receipt and block from Base and returns status (success, reverted or pending), confirmations, timestamp, sender, recipient, ETH value, total fee including the L1 data fee, and every ERC-20 transfer decoded into token, symbol, from, to and a human-readable amount. A one-line summary array is included for logs or chat replies. To verify a payment, check that status is success, that a tokenTransfers entry has the USDC contract as token, your wallet as to and the expected amount, and that confirmations meets your threshold. An unknown hash returns found: false with HTTP 404.

Request and response

Example with a real USDC transfer on Base.

$ curl -i "https://baselens.imac2014ville.workers.dev/tx?hash=0x98023b255a23cf26d93492a6c3c542247cea95fa201dc83ed3fa91d3b6fcb57f"
HTTP/2 402
payment-required: eyJ4NDAyVmVyc2lvbiI6Mi4uLn0=   # base64 JSON: scheme "exact", network eip155:8453,
                                                  # asset USDC, amount 10000 (= $0.01)
# An x402 client signs the payment, then retries with a PAYMENT-SIGNATURE header.

The paid response (abridged; confirmations grow over time):

{
  "found": true,
  "status": "success",
  "blockNumber": 52360287,
  "confirmations": 30041,
  "timestamp": "2026-10-09T01:38:41.000Z",
  "valueEth": "0",
  "feeEth": "0.000001007458660576",
  "tokenTransfers": [{
    "token": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
    "symbol": "USDC",
    "from": "0xab73fef230fa99f9ae6aa6ff9444ca5006938ece",
    "to": "0x85d3073a666f608715ae0cff0e9fa57d526fe420",
    "raw": "14990000",
    "amount": "14.99"
  }],
  "summary": ["14.99 USDC from 0xab73...8ece to 0x85d3...e420"]
}

JavaScript with @x402/fetch

import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";

const signer = privateKeyToAccount(process.env.PRIVATE_KEY); // wallet holding USDC on Base
const pay = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(signer) }],
});
const res = await pay("https://baselens.imac2014ville.workers.dev/tx?hash=0x98023b255a23cf26d93492a6c3c542247cea95fa201dc83ed3fa91d3b6fcb57f");
const tx = await res.json();
const USDC = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
const paid = tx.found && tx.status === "success" && tx.confirmations >= 3 &&
  tx.tokenTransfers.some(t => t.token === USDC && t.to === MY_WALLET.toLowerCase() && Number(t.amount) >= 14.99);

Pricing

/tx costs $0.01 per call. There is no API key and no account: each request is paid in USDC on Base over x402. Malformed input returns 400 and failed lookups return a non-2xx status, so those are not charged.

Limitations

More guides

Sister services