Apps for AI agents

Fund an agent wallet

Ounie's anonymous rail is paid for by your agent, from a wallet you hold the key to. That wallet needs exactly one thing: USDC on the Base network. It does not need ETH, and it does not need an Ounie account.

Network

base

Token

USDC

Contract

0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913

Gas

Not paid by you

USDC only — you do not need ETH

x402 never asks your wallet to send a transaction. It asks it to sign an EIP-3009 authorization — an offline signature meaning “this address may take this much USDC, once” — and a facilitator submits that on chain and pays the gas. So a wallet holding USDC and nothing else can pay. No ETH, no approval to send first, no failed transaction to debug.
YOUR WALLETUSDC onlysignFACILITATORpays the gassettleBASEUSDC moves once

It has to be USDC on Base#

USDC exists on a dozen chains and they are not interchangeable. Buying it on Ethereum and sending it to a Base address is the single most common way a first payment fails — the funds aren’t lost, but they aren’t spendable here either, and no amount of retrying the call will find them. Whichever route you take below, check the network says Base before you confirm.

  • Paid endpoints settle on Base, and only there. The value your agent signs for is the bare name base — not the CAIP-2 id eip155:8453, which names a newer protocol version. Read the network field out of the 402 response rather than hardcoding either.
  • The token is the USDC contract at 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913. A “USDC” with a different address on the same chain is a different token, whatever it calls itself.
  • Sending to the right address on the wrong network is not reversible by anyone here. Check the network selector, not just the address.

Verify the contract yourself rather than trusting this page: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 on BaseScan.

Create the wallet your agent holds#

The address that signs is the address that pays. That means the private key has to be somewhere your agent can read it — an exchange account, or a hardware wallet you haven’t exported, cannot sign an authorization on your agent’s behalf.

For an agent — generate a key#

Any EVM key works. The standard route is viem, which generates one locally and never phones anywhere:

# viem — generate a key your agent can read, and nothing else can
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";

const key = generatePrivateKey();          // 0x… — write this down once
const account = privateKeyToAccount(key);
console.log(account.address);              // 0x… — fund THIS address

Treat it like a spending float, not a vault

Put the key in your agent’s environment — never in a repo, a prompt, or a config you share. Fund the wallet with what you mean to spend and no more: it is a wallet for paying per call, not a place to keep anything. If it leaks, its whole balance is the blast radius.

For a person — use a Base-capable wallet#

If you just want to hold and send the funds yourself, Coinbase Wallet, Rainbow or Phantom all speak Base. Use one of these to buy and hold; export a key into the agent’s environment only if that same wallet is the one paying.

Get USDC onto Base#

  • Coinbase — buy USDC, then withdraw choosing Base as the network. Withdrawals to Base are free and Base is Coinbase’s own chain, so this is the shortest path from a bank account.
  • MoonPay — card straight to a wallet address, no exchange account. Costs more in fees; useful if you would rather not open one.
  • Inside the wallet itself — Coinbase Wallet, Rainbow and Phantom all let you buy USDC on Base directly. This is the least error-prone route, because there is no address to paste and no network to pick twice.
  • bridge.base.org — if you already hold USDC on Ethereum, bridge it across rather than buying again. Bridging costs Ethereum gas, so it is worth it for funds you already have and rarely worth it for a few dollars.

Check it arrived#

Open https://basescan.org/address/{your address} and look for a USDC balance against the contract above. If the balance shows up on a different network’s explorer, the tokens are on that network — that is the wrong-chain case, and the fix is a bridge rather than a retry. Nothing on ounie.com can read your balance for you: no page here connects a wallet, and no account holds one.

Make the first call#

With a funded wallet, the payment is one wrapped fetch. The client catches the 402, signs the requirements, and retries with the X-Payment header — the same exchange described in agent payments:

# x402-fetch wraps fetch: it catches the 402, signs, and retries
import { wrapFetchWithPayment } from "x402-fetch";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY);
const pay = wrapFetchWithPayment(fetch, account);

const res = await pay(endpoint, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ /* … */ }),
});
// one call: quoted, signed, settled, answered.

Endpoints that accept payment publish their URL in the app directory (“Add to agent” → x402), through ounie_describe_app, and in the Bazaar index. A thin result — an empty dataset or a failed render — settles zero, so a wallet is only ever debited for work that happened.

Prefer not to hold crypto?

You never have to. The same actions run on credits from an ordinary Ounie account paid for by card — and at a lower rate than the anonymous per-call price. The wallet route exists for agents that have no account and no human to sign them up.