What you will do
Receive USDC on Base for an AI agent: find its wallet address, fund and test on Base Sepolia, watch for incoming payments, and understand what finality means on an L2. This page is the chain-specific angle, what receiving on Base actually involves, network by network. For the stablecoin framing see how-to-accept-stablecoin-payments-as-agent, and for the receive mechanics in depth see how-to-receive-payments-as-ai-agent. The agent wallets product page is the broader reference.
What Base is and why it is used
Base is an Ethereum layer-2 network. The short version of why it matters here: it settles transactions fast and for very low fees, while inheriting Ethereum's security. USDC on Base moves for a fraction of a cent, which is the property that makes agent payments work, a half-cent payment cannot survive a fee larger than itself, and on Base the fee is far smaller than the payment.
For receiving, Base behaves like any Ethereum-compatible chain: your agent has an address, and USDC sent to that address on Base credits it. The difference from a raw wallet is that the address belongs to the agent's managed wallet, so you observe arrivals through the API and webhooks rather than running a node or holding keys. You get the chain's properties, low fees and fast finality, without the operational weight of managing chain infrastructure yourself.
Prerequisites
- A Blockchain0x account with an agent created, so it has a wallet on Base.
- A
sk_test_API key for testing on Base Sepolia. - Node 18 or newer. The SDK targets
>=18.
export B0X_API_KEY=sk_test_... # sk_test_ -> Base Sepolia, sk_live_ -> Base mainnet
export B0X_WEBHOOK_SECRET=... # webhook signing secret, shown once at creationGet the wallet address and network
The agent's wallet address is on Base, and which Base depends on the key prefix. A sk_test_ key gives a wallet on Base Sepolia; a sk_live_ key gives one on Base mainnet. Read the agent to confirm the network, and copy the address from the dashboard or the agent's public profile at wallet.blockchain0x.com/a/{slug}.
import { createClient } from "@blockchain0x/node";
const client = createClient({ apiKey: process.env.B0X_API_KEY! });
const agent = await client.agents.get("agt_...");
console.log(agent.network); // "testnet" -> Base Sepolia (eip155:84532), "mainnet" -> Base (eip155:8453)The chain ids are worth knowing because a sender needs them: Base mainnet is eip155:8453 and Base Sepolia is eip155:84532. Sending USDC on any other chain, or to an address on the wrong Base network, means it does not arrive.
Fund and receive on Base Sepolia
On testnet, you fund the agent's wallet yourself to exercise the receive path. Copy the wallet address, then send it test USDC from a public Base Sepolia USDC faucet. That arrival is a real receive event on testnet, so it is the cleanest way to confirm your handling works before any real value moves.
On mainnet, you do not fund to test; real callers or your own treasury send the USDC. The address and the flow are identical, only the network and the realness of the money change. Because of that symmetry, anything you confirm on Base Sepolia behaves the same on Base mainnet.
Watch for the payment
Receiving is event-driven: subscribe to payment.received and verify each delivery against the raw bytes.
import express from "express";
import { webhooks } from "@blockchain0x/node";
const app = express();
app.use(express.raw({ type: "application/json" }));
app.post("/webhooks/blockchain0x", (req, res) => {
const result = webhooks.verify({ headers: req.headers, rawBody: req.body, secret: process.env.B0X_WEBHOOK_SECRET! });
if (!result.ok) return res.status(400).json({ code: result.code });
if (result.eventType === "payment.received") {
const payload = JSON.parse(req.body.toString("utf8"));
creditAgent(payload); // your logic
}
return res.status(200).end();
});The webhook is the signal that USDC landed on Base. Do not poll a balance in a loop; let the event tell you, and look up the canonical record with client.transactions.get(id) when you need to reconcile.
Verify a payment on a block explorer
One thing receiving on Base gives you that a closed payment system does not: an independent public record. Every payment is an on-chain transaction with a hash, and you can look that hash up on a Base block explorer to confirm it, separate from anything Blockchain0x tells you.
This is useful in two situations. During development, pasting the transaction hash into the explorer shows you the transfer, the amount, the sender, and the receiving address, which is the fastest way to confirm a test payment really moved the USDC you expected to the address you expected. In production, the explorer is a neutral source of truth for a support question or a dispute: if a caller claims they paid and you have no payment.received event, the hash either shows a confirmed transfer to your address or it does not, and that settles it without trusting either party's logs. Keep the transaction identifier from the webhook payload or transactions.get so the lookup is a direct paste rather than a search. The point is that on-chain receiving is auditable by anyone, which is a property worth using, not just a side effect.
Finality and confirmations
A property specific to receiving on chain, worth understanding before you build on it: a Base payment is final once its transaction confirms. There is no pending-then-reversible window like a card authorization, and no chargeback path. When you act on payment.received, you are acting on a settled transfer.
That finality is a feature for a payee, you keep what you are paid, but it puts the responsibility on the sender to get the details right, because a transfer to a wrong address or the wrong network is gone. For your own receiving, it means you can deliver the paid result as soon as the event fires, without holding it back against a future reversal. Base confirms quickly, so the gap between a caller paying and your handler seeing payment.received is short, which is part of why the per-call model feels synchronous even though real settlement is happening underneath.
A practical consequence worth designing for: because the payment is final and fast, you can make delivery and payment a single tight loop. The caller pays, the event fires, you return the result, and there is no settlement period to reconcile later, no holdback, and no reversal window to reserve against. That is simpler than a card flow, where you often deliver on an authorization and reconcile against capture and possible chargeback days later. On Base you reconcile against a fact, not a promise, which removes a whole class of accounting state you would otherwise carry.
Common pitfalls
Three traps.
Wrong network. A sk_test_ agent receives on Base Sepolia only. USDC sent on Base mainnet, or another chain entirely, does not arrive. Match the network to the key before sharing an address.
Polling instead of webhooks. Looping on a balance is slow and brittle. Subscribe to payment.received and verify it; that is the intended signal.
Assuming reversibility. A confirmed Base payment is final. Build as if there are no chargebacks, because there are none, and double-check the address and network on anything you send.
What to ship today
Read the agent's network, copy its Base address, send it test USDC on Base Sepolia from a faucet, and confirm the payment.received event lands. When that works, the same flow runs on Base mainnet with a sk_live_ key. For the stablecoin framing see how-to-accept-stablecoin-payments-as-agent; for the full receive mechanics see how-to-receive-payments-as-ai-agent. Pricing is on the pricing page.