Skip to content

Quickstart

Your agent pays a live x402 offer, and you confirm that the payment was recognized. Start free on Base Sepolia with test USDC, then move to mainnet with the same steps.

You need an agent that speaks MCP, or a script that uses a standard x402 v2 client. Both paths are below.

0. Pay from nothing in one command

With Node.js 20 or later, and nothing else:

npx -y @vauban-pay/mcp try

It creates your own key in ~/.vauban-pay, with file permissions 0600, and does not print it. It gets 1 test USDC on Base Sepolia for that key, then pays our demo x402 offer with it. It prints the funding and payment transactions, and a line to read the payment back yourself. Test USDC has no real value.

To do the same on Starknet Sepolia, with test STRK instead of test USDC:

npx -y @vauban-pay/mcp try --network starknet-sepolia

It creates your own Starknet key in ~/.vauban-pay, gets test STRK for it, deploys your account, pays our demo x402 offer on Starknet Sepolia and prints the transactions. Test STRK has no real value.

Steps 1 to 5 do the same by hand, so you can see each part and wire it into your own agent or program.

What you need for steps 1 to 5: Node.js 20 or later, and Foundry for the cast command.

1. Create a key for this purpose only

Use a key dedicated to agent payments, funded only with what you intend to spend, never a personal wallet's key. Any tool that writes a Web3 Secret Storage v3 keystore will do. With Foundry:

mkdir -p ~/.vauban-pay && cd ~/.vauban-pay && umask 077
openssl rand -base64 32 > payer.password
cast wallet new . payer --unsafe-password "$(cat payer.password)"

The keystore is the file payer, its password is in payer.password, and the command prints the address to fund. Both files are readable by you only.

2. Get test USDC

Ask Vauban for 1 test USDC on Base Sepolia, sent to the address of step 1:

cd ~/.vauban-pay
ADDR=$(cast wallet address --keystore payer --password-file payer.password)
curl -s -X POST https://demo.pay.vauban.tech/sponsor/v1/test-usdc \
  -H 'content-type: application/json' -d "{\"address\":\"$ADDR\"}"

The answer carries the transaction hash. Each address is funded once. Test USDC has no real value. You need no ETH: the payment is a signed EIP-3009 authorization, and the service submits it for you.

If the call is refused, open Circle's faucet, pick Base Sepolia and claim test USDC for the same address.

3. Read the offer

GET https://demo.pay.vauban.tech/x402-base-sepolia/v1/quote

answers 402. The offer is in the PAYMENT-REQUIRED response header, as base64-encoded JSON:

import base64, json, urllib.request, urllib.error
URL = "https://demo.pay.vauban.tech/x402-base-sepolia/v1/quote"
try:
    urllib.request.urlopen(URL)
except urllib.error.HTTPError as e:            # 402 expected
    h = e.headers["payment-required"]
    offer = json.loads(base64.b64decode(h + "=" * (-len(h) % 4)))
    print(offer["resource"], offer["accepts"])

Read on 2026-10-01:

field value
scheme exact, exact-pq
network eip155:84532 (Base Sepolia)
asset 0x036CbD53842c5426634e7929541eC2318f3dCF7e (test USDC)
amount 1000000 (1 test USDC)
payTo 0x9e04689ec4F4B6A8BdEe305Bcd0A93F8B908eA0d

The demo states its own limits in resource.description. Read them there before paying.

4. Pay it

With the MCP server

Add @vauban-pay/mcp to your MCP client (Claude Desktop, Claude Code, any MCP client), with absolute paths to your two files:

{
  "mcpServers": {
    "vauban-pay": {
      "command": "npx",
      "args": ["-y", "@vauban-pay/mcp"],
      "env": {
        "PAY_MCP_EVM_KEYSTORE_PATH": "/home/you/.vauban-pay/payer",
        "PAY_MCP_EVM_PASSWORD_PATH": "/home/you/.vauban-pay/payer.password",
        "PAY_MCP_EVM_NETWORKS": "eip155:84532",
        "PAY_MCP_EVM_PAYEES": "0x9e04689ec4F4B6A8BdEe305Bcd0A93F8B908eA0d",
        "PAY_MCP_EVM_MAX_PER_PAYMENT": "1000000",
        "PAY_MCP_EVM_MAX_PER_SESSION": "5000000"
      }
    }
  }
}

That pays at most 1 test USDC per payment and 5 per session, on Base Sepolia only, to that one payee. Then ask your agent:

Use pay_for_resource on https://demo.pay.vauban.tech/x402-base-sepolia/v1/quote.

The outcome is paid, with the resource, the transaction and the payer. If it is unpayable, its code names the setting to fix.

With any x402 v2 client

Use the x402 foundation's own client, not the older v1 packages:

npm install @x402/fetch @x402/evm viem
// Pay an x402 v2 URL with the x402 foundation's standard client.
// Usage: EVM_PRIVATE_KEY=0x... node pay.mjs <url>
import { wrapFetchWithPaymentFromConfig, x402HTTPClient, x402Client } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";

const url = process.argv[2];
const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);
console.log("payer", account.address);

const payFetch = wrapFetchWithPaymentFromConfig(globalThis.fetch, {
  schemes: [{ network: "eip155:*", client: new ExactEvmScheme(account) }],
});
const res = await payFetch(url, { method: "GET" });
const body = await res.text();
const result = new x402HTTPClient(new x402Client()).parsePaymentResult({
  status: res.status,
  getHeader: (n) => res.headers.get(n),
  body: (() => { try { return JSON.parse(body); } catch { return undefined; } })(),
});
console.log("status", res.status, result.paymentStatus);
console.log("payment header", JSON.stringify(result.header ?? null));

5. Confirm you are recognized

A settled payment returns 200. A receipt then records your EVM address as having paid for the resource, on Starknet. Read it with one call to any Starknet Sepolia JSON-RPC v0.10 endpoint, at block "latest". Vauban runs one at https://sepolia.rpc.vauban.tech/rpc/v0_10; any standard provider works equally well. You need no Starknet account and no Starknet key.

  • contract: 0x011e92d42cff92edd738ddc9405b3a53b5cce91371c4c520be20e2717f6ac8fa
  • est_ouverte(payer): selector 0x03600a7e6d7c7be91e03409ac690f0f4547fdb0f5147af3fcd4cc9ef9bbfbf35, calldata [payer], your EVM address as a plain hex felt
curl -s https://sepolia.rpc.vauban.tech/rpc/v0_10 \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"starknet_call","params":[{"contract_address":"0x011e92d42cff92edd738ddc9405b3a53b5cce91371c4c520be20e2717f6ac8fa","entry_point_selector":"0x03600a7e6d7c7be91e03409ac690f0f4547fdb0f5147af3fcd4cc9ef9bbfbf35","calldata":["0xYOUR_EVM_ADDRESS"]},"latest"]}'

It returns 0x1 once your payment is recognized, 0x0 otherwise. If it returns 0x0 right after paying, repeat the call a little later.

6. Pay with real funds

The steps are the same. What changes:

  • the offer URL, the network, the asset and the payee: read them from the offer, as in step 3;
  • your consent to spend real money, named per network in PAY_MCP_EVM_I_ACCEPT_MAINNET_SPEND;
  • on Ethereum, the USDC contract in PAY_MCP_EVM_ASSETS;
  • the Starknet mainnet endpoint and resource contract, named by the offer.

Need a card or a private payment? Contact us.