Skip to main content
Veil supports standard x402 payments funded from your private Veil USDC balance. Instead of paying a metered API or paid resource from a public EOA you use elsewhere, Veil withdraws the exact amount to a fresh, single-use payer address and signs a standard x402 payment from it. The merchant sees an ordinary x402 payment and settles through any facilitator that supports this scope—nothing on their side changes.
x402 support is built for agents and developers paying for resources programmatically, via the SDK & CLI (@veil-cash/sdk) and the MCP Server (@veil-cash/mcp). It funds payments from your private USDC balance—no custom merchant integration required.

How it works

private Veil USDC → withdraw exact amount to fresh payer EOA → payer signs x402 payment → facilitator settles
  1. Your agent requests a paid resource and receives a standard 402 with x402 v2 payment requirements.
  2. The SDK derives a fresh payer address deterministically from your Veil key and a payer index.
  3. The SDK builds a normal Veil USDC withdrawal proof and funds that payer with the exact payment amount through the Veil relay.
  4. The payer address signs the standard x402 payment, and the merchant’s facilitator settles it onchain and pays gas for that leg.
Each payment uses a fresh payer address (via a new payerIndex), which avoids reusing the same public address across payments. The Veil withdrawal to fund that payer and the x402 payment from it are still public onchain legs.

Privacy boundaries

Veil hides your source wallet and private balance graph. It does not hide the funding or payment legs. Still visible or correlatable:
  • the Veil pool withdrawal to the fresh payer address
  • the payer address’s payment to the merchant
  • the USDC amount
  • timing between funding and payment
  • merchant and resource-server metadata
  • your agent’s IP/session metadata, unless routed separately
Fresh per-payment payer addresses reduce address reuse across payments, but they do not remove amount and timing correlation. Treat x402 payments as unlinkable from your wallet, not fully anonymous.

Supported scope

The MVP is intentionally narrow:
  • Protocol: x402 v2, exact scheme
  • Network: Base mainnet (eip155:8453)
  • Asset: Base USDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913)
  • Funding: your private Veil USDC balance
Requests for other schemes (upto, batch settlement), other networks, or non-USDC assets are rejected with a clear error before any funds move.

Paying from an agent (MCP)

The Veil MCP server exposes veil_pay_x402 for agents:
veil_pay_x402({ url, method?, body?, headers?, maxPayment?, payerIndex?, forceFresh?, confirm })
  • Requires confirm: true.
  • Pre-flights the endpoint before funding—if the unpaid probe does not return 402, it withdraws nothing (useful for malformed requests). If the probe returns 402 but the merchant validates only after payment, the payer may still be funded while delivery fails; see Recovery.
  • Enforces a spend cap: maxPayment is a decimal USDC string (e.g. "0.10"), defaulting to and hard-capped at 10 USDC. A requirement above the cap is rejected before funding.
  • Reuses funded payers: before a fresh withdrawal it scans already-funded payer addresses; if one holds enough USDC it offers reuse instead of withdrawing again. This recovers funds when a payment funded but delivery failed. Reusing a funded payer links both attempts to the same public EOA—MCP surfaces this as reuse_available rather than doing it silently.
Use veil_x402_quote for a dry run, veil_x402_receipts for spend history, and veil_x402_payer_balances to check for funds stranded on a payer. See the MCP Server page for the full tool list and setup.
Funding many small payments produces small change notes that can fragment your balance. veil_get_balances reports a per-pool fragmentation summary, and veil_consolidate_utxos merges notes via a private self-transfer.

Paying from application code (SDK)

import { payX402Resource } from '@veil-cash/sdk';

const result = await payX402Resource({
  url: 'https://merchant.example/paid-resource',
  rootPrivateKey: process.env.VEIL_KEY as `0x${string}`,
  payerIndex: 42n,
  maxPayment: '0.10', // cap exposure; reject if the resource demands more
  relayUrl: process.env.X402_RELAY_URL,
  rpcUrl: process.env.RPC_URL,
});

console.log({
  status: result.response.status,
  payerAddress: result.payerAddress,
  relayTx: result.relayTransactionHash,
  paymentTx: result.paymentTransactionHash,
});
Use a fresh, persisted payerIndex for each payment. quoteX402Resource() probes a resource without paying; getX402PayerBalances() reports USDC held by each derived payer address (useful for recovering funds after a failed payment); and reuseExistingBalance: true retries a payment whose funding succeeded but whose delivery failed, paying directly from the already-funded payer with no new withdrawal. See SDK & CLI for install and setup.

Recovery

If a payment fails after funding, the USDC stays on the payer address and is recoverable—the payer key is derived from your Veil key and the payer index. The MCP reuse flow and the SDK’s reuseExistingBalance path recover these funds without a second withdrawal. For the underlying tooling, see SDK & CLI and MCP Server. For how your keys work, see Veil Keypair.