Reference

Networks & facilitators

Built-in EVM, Solana and NEAR networks, local development, facilitators, mainnet guardrails and public-network smoke tests.

Change the network and configure a remote facilitator to use a public network; the gateway code and pipeline stay the same.payments.x402 and experimental payments.mpp share the facilitator model and mainnet guardrails. MPP accepts only eip155:31337, Base Sepolia and Base.

Supported networks

networkNetworkKindNotes
eip155:31337Local AnvillocalAnvil's default chain id; no default asset; the only network for the local facilitator
eip155:84532Base Sepoliatestnetsettled, EIP-3009 and Permit2
eip155:8453Basemainnetsettled, EIP-3009 and Permit2
eip155:1Ethereummainnetsupported; no payment run
eip155:137Polygonmainnetsupported; no payment run
eip155:42161Arbitrum Onemainnetsupported; no payment run
eip155:421614Arbitrum Sepoliatestnetsupported; smoke target not yet run
eip155:43114Avalanche C-Chainmainnetsupported; no payment run
solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpSolanamainnetremote facilitator only; settled
solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1Solana Devnettestnetremote facilitator only; settled
near:mainnetNEARmainnetpartial; remote facilitator only
near:testnetNEAR Testnettestnetpartial; remote facilitator only

Every built-in EVM network is supported: the signing code is the same on each, and on 2026-10-10 each network's USDC signing domain matched the chain and Permit2 and its x402 proxy were deployed. Every network also needs a facilitator that lists it, or health fails. NEAR has settled on testnet and mainnet only through the SDK facilitator the test suite runs, so it stays partial. Other tokens on built-in EVM networks also remain partial: the settlement test uses a local chain with a built-in network's id (see the settlement asset). Solana and NEAR specifics are in Configuration.

Declared networks

Declare another EVM network with kind for mainnet guardrails, displayName and rpcUrl:

yaml
payments:
  x402:
    networks:
      eip155:10: { kind: mainnet, displayName: OP Mainnet }

A declared network has no default asset: supply the token's address, decimals and, for EIP-3009, its EIP-712 domain. Support is partial because the chain and token are operator-supplied. A built-in network cannot be redeclared; its entry may set rpcUrl only. Any other unknown id is CONFIG_INVALID at load: the chain id is part of the buyer's signed EIP-712 domain and must resolve explicitly.

Deployment mode

local, testnet or mainnet comes from the network: eip155:31337 is local, and every other network is the testnet or mainnet it names. Offers on several networks must share one mode. The mode is reported by doctor, by the payment provider's health check, and at /.well-known/agent-commerce. In local mode the health check also requires the RPC to answer Anvil's anvil_nodeInfo, because an RPC can report any chain id.

The facilitator

A facilitator verifies the buyer's authorization and broadcasts the transfer, paying gas on EVM, transaction fees through its Solana fee payer, or gas through its NEAR relayer. With remote, the gateway holds no facilitator signing key.

facilitator.modeWho signsWhere it is allowed
localthis process, with a key you configureeip155:31337 only; refused at config load anywhere else
remotean HTTP facilitator you point atanywhere; required on every public network

A config that still pairs the local facilitator with eip155:84532, the local chain's id before 2.1, is refused with a pointer to eip155:31337.

auth.typeWhat it sendsNeeds
nonenothingon mainnet, allowUnauthenticatedFacilitator: true
bearera static tokennothing installed
cdpa fresh Coinbase Developer Platform JWT per request@coinbase/x402, and url set to https://api.cdp.coinbase.com/platform/v2/x402

Omitting auth is the same as type: none. Any other type is refused at config load, and so is cdp with any other url, since it signs each request for CDP's.

A facilitator cannot redirect your money: the buyer's signature fixes the token, amount and recipient. What it can do is see every authorization you handle, delay or drop a broadcast until the authorization expires, and stop answering. The gateway accepts its reported success once it names the offer's network and a transaction in that family's form, without reading the chain.

In remote mode, health checks require the facilitator to list the scheme on every offer's network. One failing offer fails the x402 provider and /ready. With several offers, /.well-known/agent-commerce publishes each status anddoctor names the failing offers.

Configuration by network

config.yamlyaml
payments:
  x402:
    enabled: true
    network: ${X402_NETWORK:-eip155:31337}   # CAIP-2; the local chain
    rpcUrl: ${X402_RPC_URL:-http://127.0.0.1:8545}
    asset: ${X402_ASSET}                # ERC-20 with EIP-3009
    assetName: ${X402_ASSET_NAME}       # EIP-712 domain name
    assetVersion: ${X402_ASSET_VERSION}
    assetDecimals: ${X402_ASSET_DECIMALS}
    payTo: ${MERCHANT_WALLET}           # merchant-controlled. NEVER the gateway's.
    maxTimeoutSeconds: 120
    paymentFlow: authorization          # default; or upfront
    facilitator:
      mode: local                       # eip155:31337 only
      signerPrivateKey: ${X402_FACILITATOR_PRIVATE_KEY}

signerPrivateKey must be a 32-byte hex key. Provider construction refuses a well-known Anvil key against an RPC that is not local or private, and the local health check requires the RPC to answer as Anvil.

Solana and NEAR take the same shape with their own network id and payTo. To accept several networks at once, see Several options.

Mainnet guardrails

All of these are refused at config load, before the gateway starts:

RefusedBecause
allowMainnet absent or falsemainnet is never a default
facilitator.mode: locala funded gas key inside the resource server
facilitator.auth.type: noneunless allowUnauthenticatedFacilitator accepts it by name
a non-HTTPS facilitator.urlauthorizations and settlement results in the clear
a well-known Anvil payTo or MPP recipientits private key is public knowledge
an asset other than USDC for MPP, Solana or NEARthey settle only in USDC
the wrong USDC assetName or assetVersionthe buyer signs that EIP-712 domain

A declared mainnet has no default asset to check. The same rules apply to any non-local deployment where they make sense: plain HTTP is allowed only to a local or private host, and a development payTo is refused on testnet too.

assetName is the EIP-712 domain, not the symbolBase Sepolia's USDC reports "USDC"; Base mainnet's reports "USD Coin". The buyer signs that string, so the wrong one gets every payment refused with invalid_exact_evm_token_name_mismatch after they signed. The network registry pins the domain of each built-in network's USDC: omit the asset fields to use it, and config load refuses an override that does not match.

Recorded settlements

Each of these moved 0.01 USDC from a buyer to a merchant through a remote facilitator:

RailNetworkMethodTransaction
x402Base SepoliaEIP-30090xea41b234c4…
x402Base SepoliaPermit20xa66f56cf39…
x402BaseEIP-30090x57ec81c2a3…
x402BasePermit20x79d3da1145…
x402Solana DevnetSPL transfer5289xbeyHJ…
x402SolanaSPL transferE7gAuG8pMA…
x402NEAR TestnetNEP-141 transfer5tdtGLv4TB…
x402NEARNEP-141 transfer7hU3imHepV…
MPPBase SepoliaEIP-30090x5d9fcd111b…
MPPBaseEIP-30090xf4255bd7ec…

Facilitators broadcast these payments and paid their ETH, SOL or NEAR fees. Permit2 needs a one-time, gas-paying token approval from the buyer. The NEAR runs used the suite's SDK facilitator and relayer, so NEAR support stays partial until a hosted facilitator settles. Buyer and merchant keys stayed outside the gateway.

Smoke tests

npm run test:testnet spends test USDC and npm run test:mainnet real USDC on public x402 payments, then verifies settlement on chain. Run them by hand on the wallet holder's machine, never in CI, where funded keys would enter repository secrets. Without settings, both skip and list what each target needs.

TargetNetworkDefault facilitatorRuns unnamed
base-sepoliaeip155:84532, EIP-3009x402.orgyes
base-sepolia-permit2eip155:84532, Permit2x402.orgno
arbitrum-sepoliaeip155:421614, EIP-3009PayAIno
solana-devnetSolana Devnetx402.orgyes
near-testnetnear:testnetthe SDK's, started by the suiteyes
baseeip155:8453, EIP-3009none: X402_FACILITATOR_URLno
base-permit2eip155:8453, Permit2none: X402_FACILITATOR_URLno
solanaSolana mainnetnone: X402_SOLANA_MAINNET_FACILITATOR_URLno
nearnear:mainnetthe SDK's, started by the suiteno

Set X402_SMOKE_TARGETS to a comma-separated list for a release check: an unknown target or a missing setting fails before signing, so the check cannot pass by skipping. Without it, test:testnet runs the configured targets marked “runs unnamed” and test:mainnet runs nothing. Mainnet also needs ALLOW_X402_MAINNET=true. Each target pays X402_SMOKE_AMOUNT USDC once, 0.01 by default, and the suite refuses a payment above 1.00 on testnet or 0.10 on mainnet.

For each target, a run proves in order:

  1. on mainnet, the same config without allowMainnet is refused;
  2. discovery reports the target's network and mode without the facilitator's URL, and the provider's health check passes;
  3. the buyer holds enough USDC, and the target's preparation is in place: a Permit2 approval, the merchant's Solana token account or the NEAR buyer's full-access key;
  4. the SDK client pays once, and the gateway answers 200 with a successful PAYMENT-RESPONSE on the target's network;
  5. the chain shows the transfer the settlement reported: the token's Transfer on EVM, the token balances of the confirmed Solana transaction, or the buyer's ft_transfer and the token's successful receipt on NEAR;
  6. exactly one gateway receipt names the transaction;
  7. the same payment presented again gets 402 or 409, and the backend is not called again;
  8. nothing the gateway logged contains a key or a credential.

Balance changes alone cannot prove settlement; an unrelated transfer could explain them. Each settled target prints an evidence record, and X402_SMOKE_EVIDENCE_FILE appends them as JSON lines. The full settings table is in docs/smoke-tests.md.

Worked configurations

Accept paymentsThe integration walkthrough for each network.