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
- Base mainnet only. A hash from another chain returns not found.
- Only ERC-20
Transferevents are decoded. Native ETH sent through internal calls and NFT transfers are not listed;valueEthreflects the top-level transaction value. - Token metadata is read for at most 30 distinct tokens per transaction. Compare addresses, not symbols, because anyone can deploy a token called USDC.
More guides
BaseLens overview/openapi.jsonllms.txt
Sister services
- DepVet: npm and PyPI package vetting before install
- TokenGuard: honeypot and rug pull checks for Base tokens, plus pre-screened new launches
- MacroLens: country macro statistics and company registries (Norway, France)
- SkyFeed: weather forecasts, US alerts, earthquakes and public holidays
- ChainRead: gas, balances, ENS and Basename resolution on Base and Ethereum