VirtualSMS
    VirtualSMS
    Ask AI:
    ← Back to Blog
    Technical

    Published: April 30, 2026 | 12 min read

    HTTP 402 Payment Required has sat dormant in the spec for thirty years; the x402 standard finally puts it to work as a machine-readable settlement primitive for autonomous agents. This guide ships the deposit-first integration on VirtualSMS — USDC on Base mainnet, USDC + USDT on Solana, USDC + USDT on BNB Chain (via Permit2), $2 minimum top-up, $0.05 per SMS code — with reference x402-fetch snippets in Python and Node so an agent can fund itself, verify accounts, and stay in the loop without an operator touching billing.

    x402 SMS Verification — Pay-Per-Call OTP for Autonomous Agents (2026)

    x402 SMS verification — pay-per-call OTP for autonomous AI agents on VirtualSMS

    What x402 Solves For Autonomous Agents

    HTTP 402 Payment Required is a status code that’s sat dormant in the spec for thirty years. x402 — the agentic-payments standard — finally puts it to work. The protocol is simple: when an agent hits a paid endpoint without a payment proof, the server replies 402 with a structured manifest naming the accepted asset, amount, and recipient. The agent’s wallet signs an on-chain transfer, retries the request with the proof in the X-PAYMENT header, and the server returns the resource. No API key issuance, no operator-managed checkout, no human in the loop.

    For x402 sms verification specifically, the value proposition lines up cleanly with the SMS-OTP primitive that AI agents already need. An agent provisioning Discord, Telegram, WhatsApp, or any of 2,500+ services across 145+ countries can fund itself, top up its balance, and keep verifying accounts indefinitely — without an operator touching a billing portal. The agent owns its money path end-to-end.

    For the integration patterns that don’t need x402 (operator-managed budgets, prepaid keys, MCP deployments inside Claude Desktop or Claude Code), the bearer-token API and the Claude MCP server are the path. x402 is for the autonomous-spend case.

    Deposit-First, Not Per-Call — And Why That Matters

    VirtualSMS’s x402 endpoint settles deposits, not individual SMS codes. Hit POST /x402/topup with an amount, settle the 402 response on Base mainnet, and the server returns an api_key bound to that wallet plus the deposited balance. From there, every SMS-verification call is a normal bearer-token request against /v1/orders — no on-chain settlement per code.

    The reason is gas economics. Each x402 settlement on Base costs roughly 1-2 cents in gas. SMS codes start from $0.05 per activation. Pay-per-call would burn 20-40% of the activation in gas alone — a tax that scales linearly with throughput. Amortizing one settlement across a $2-$10 deposit collapses gas to a rounding error.

    Minimum top-up: $2.00 USDC. Anything smaller is uneconomic on Base after gas. A $2 top-up funds 40 SMS codes at the $0.05 floor, comfortably more than most single-task agent runs need.

    The Top-Up Flow End-to-End

    Three round-trips. First request returns the manifest. Second request carries the payment proof and the server hands back the API key. Then the agent spends.

    1. Initial request — server returns 402 manifest

    HTTP/1.1 402 Payment Required
    Content-Type: application/json
    
    {
      "x402Version": 1,
      "accepts": [{
        "scheme": "exact",
        "network": "base",
        "asset": "USDC",
        "maxAmountRequired": "2000000",
        "payTo": "0xfEc5...5F32",
        "resource": "https://api.virtualsms.io/x402/topup"
      }]
    }

    The manifest names the network (base), the asset (USDC), the amount in smallest units (maxAmountRequired — 2000000 is $2 in 6-decimal USDC), and the recipient address. An x402-fetch / x402-axios client picks the right scheme automatically and signs the transfer.

    2. Retry with X-PAYMENT — server settles + responds 200

    HTTP/1.1 200 OK
    Content-Type: application/json
    
    {
      "api_key": "vsms_x402_AbCd1234...",
      "balance_usd": "2.00",
      "tx_hash": "0xa1b2c3..."
    }

    The api_key in the response is bound to the wallet that paid. Save it; reuse it for every subsequent SMS call. The tx_hash is the on-chain proof — useful for accounting and dispute resolution.

    3. Spend — normal bearer-token API calls

    Once the agent has the key, every other endpoint behaves identically to the operator-funded API: POST /v1/orders to buy a number, GET /v1/orders/{id} to read the SMS code, POST /v1/orders/{id}/cancel on timeout, and GET /v1/balance to read the remaining balance. When balance approaches zero, top up again.

    Python Agent — x402-fetch + requests

    Reference implementation. Wrap a requests.Session with x402_fetch.wrap_fetch_with_payment, hand it the agent’s wallet, and the 402 dance is automatic on the first POST. Subsequent SMS calls use the returned api_key with the unwrapped requests client.

    import os
    from x402_fetch import wrap_fetch_with_payment
    from web3 import Account
    import requests
    
    # Agent's pre-funded EOA on Base mainnet (USDC). Cap the wallet at $50-$100
    # of float and rotate / sweep daily — this is the "money-path" wallet.
    account = Account.from_key(os.environ["AGENT_PRIVATE_KEY"])
    fetch = wrap_fetch_with_payment(requests.Session(), account)
    
    # 1. Top up. The 402 response is auto-paid by x402-fetch and we get
    #    back the api_key + balance bound to this wallet.
    r = fetch.post(
        "https://api.virtualsms.io/x402/topup",
        json={"amount_usd": 2.00},
    )
    api_key = r.json()["api_key"]
    
    # 2. Spend the balance. Calls below use the api_key normally.
    H = {"Authorization": f"Bearer {api_key}"}
    order = requests.post(
        "https://api.virtualsms.io/v1/orders",
        headers=H,
        json={"service": "discord", "country": "uk"},
    ).json()
    print(order["phone"], "→ waiting for SMS")

    For the full LangChain / OpenAI Assistants / CrewAI / Claude tool-use wrapping patterns — drop the spend block above into the body of the verify-phone tool and wire it as shown in the AI agent phone verification guide.

    Node Agent — x402-fetch + viem

    TypeScript / Node 18+ shape. Same protocol, same flow, viem wallet client instead of web3.py.

    import { createWalletClient, http } from "viem";
    import { privateKeyToAccount } from "viem/accounts";
    import { base } from "viem/chains";
    import { wrapFetchWithPayment } from "x402-fetch";
    
    const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`);
    const wallet  = createWalletClient({ account, chain: base, transport: http() });
    const fetch   = wrapFetchWithPayment(globalThis.fetch, wallet);
    
    // 1. Top up — 402 response auto-settles via the wrapped fetch.
    const topup = await fetch("https://api.virtualsms.io/x402/topup", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ amount_usd: 2.00 }),
    }).then(r => r.json());
    
    const apiKey = topup.api_key;
    
    // 2. Spend the balance with the returned api_key.
    const order = await fetch("https://api.virtualsms.io/v1/orders", {
      method: "POST",
      headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
      body: JSON.stringify({ service: "discord", country: "uk" }),
    }).then(r => r.json());
    console.log(order.phone, "→ waiting for SMS");

    Solana variant: same protocol, same deposit-first flow — swap the wallet client for @solana/web3.js and target the solana network entry in the manifest (USDC mint or USDT mint). x402-fetch picks the SVM exact scheme automatically when the wallet client is a Solana keypair signer.

    BNB Chain variant: the wallet client stays the same as Base (viem on EVM). The difference is settlement method: BEP-20 USDT and Binance-Peg USDC don't support EIP-3009, so x402 uses Permit2 — a one-time approve(Permit2, MaxUint) from your wallet, then every subsequent payment is a gasless EIP-712 signature settled through the canonical x402ExactPermit2Proxy at 0x402085c248EeA27D92E8b30b2C58ed07f9E20001. The witness pattern on the Proxy cryptographically binds the destination so the facilitator can't redirect funds. x402-fetch handles the method selection from the manifest automatically.

    For Discord-specific verification flows (the most common x402 target — agents provisioning moderation bots, multi-server presence, region-specific community managers), see the dedicated Discord real-SIM API guide. The verify-phone body collapses identically against the api_key returned from the x402 top-up.

    Pricing + Wallet Sizing

    • Activations from $0.05 per SMS code. Live per-service+country pricing on the pricing page; programmatic readout via GET /v1/services/{service}/cheapest (unauthenticated).
    • Minimum x402 top-up: $2 USDC. Top up larger amounts to reduce settlement frequency — a $10 top-up at $0.05/code funds ~200 activations.
    • Recommended wallet float: $50-$100. Treat the agent’s payment wallet as a short-lived float, not a treasury. One wallet per agent (or per agent fleet), capped, swept daily to a cold wallet. Reduces blast radius if the key leaks.
    • Auto-refund on no-SMS — failed activations refund to the api_key’s balance, not back to the wallet. The agent loop sees the refund as restored balance and continues.
    • Discovery endpoints are unauthenticated — list_services, list_countries, check_price, find_cheapest don’t require auth and don’t consume balance. Plan before spending.

    x402 vs Bearer-Token API — When To Pick Which

    Use caseRecommended pathWhy
    Operator-funded SaaS (your server pays)Bearer-token API + crypto depositOne key, ops dashboard, monthly accounting
    Claude Desktop / Code agentMCP server (operator key)One-line install, 18 tools, no payment plumbing
    Autonomous agent with own walletx402 top-upAgent self-funds, no operator in the loop
    Multi-tenant platform (per-user billing)x402 top-up per tenantOne api_key per wallet, clean billing isolation
    Prototype / one-off scriptBearer-token APIZero on-chain plumbing, fastest start

    x402 is a strict superset only if the agent already owns a wallet. For everything else, the bearer-token API and the MCP server stay the right primitives. Pick by control structure, not novelty.

    Roadmap + Current Limitations

    • Network scope. x402 settlement is live on three networks: Base mainnet (USDC) via EIP-3009, Solana mainnet (USDC + USDT) via the SVM exact scheme, and BNB Chain (USDC + USDT) via Permit2 (using the canonical x402ExactPermit2Proxy contract for witness-pattern security on BEP-20 USDT and other tokens without EIP-3009). Polygon, Arbitrum, and Optimism share the same Permit2 wire format — they unlock with an env-var change, not new implementation work.
    • Per-call x402 is not exposed. Every paid endpoint returns the deposit manifest, not a per-call manifest. This is intentional — see the gas-economics section above. Per-call x402 may ship for high-value endpoints if the gas-amortization math changes.
    • Refund mechanics. Activation refunds restore balance_usd on the api_key, not the wallet. To extract balance back to the wallet, contact [email protected] — programmatic balance withdrawal is on the roadmap.
    • Rate limits. 120 requests/min per api_key default; same as the bearer-token API. Production accounts can be lifted higher on request.

    Pre-launch checklist: seed the agent wallet with $2-$10 USDC on Base, run a single top-up against staging or production, confirm the api_key + balance came back, run one $0.05 activation end-to-end. After that, the agent loop runs without further operator involvement.

    Ask AI about this article

    Get a summary or follow-up answer in your favourite AI assistant.

    Frequently Asked Questions

    What is x402, and why does it matter for AI agents?

    x402 revives the dormant HTTP 402 Payment Required status code as a machine-readable settlement protocol. When an agent hits a paid endpoint, the server returns 402 with a structured manifest describing accepted assets and amounts; the agent's wallet signs and submits an on-chain payment, the server verifies, and returns the resource. For autonomous agents this matters because it removes the operator from the spending path — no API key issuance, no monthly invoicing, no checkout form. The agent funds itself from a pre-authorized wallet and pays per call.

    How does x402 SMS verification work on VirtualSMS?

    VirtualSMS exposes an x402 top-up endpoint that follows the deposit-first model rather than per-call settlement. The agent POSTs to /x402/topup with an amount, the server returns 402 with the USDC payment manifest, the agent's wallet settles on Base mainnet, and the response carries an api_key + balance. Subsequent SMS-verification calls use that key normally — same /v1/orders, /v1/services, /v1/balance endpoints as the bearer-token API. Top-up amounts start from $2 to keep the on-chain settlement worthwhile.

    Why deposit-first instead of pay-per-call?

    Each on-chain settlement on Base costs roughly 1-2 cents in gas. For a $0.05 SMS code, paying per-call would burn 20-40% of the activation in gas alone. The deposit-first model amortizes one settlement across many activations — top up $2-$10, spend it down across 40-200 SMS codes, top up again when the balance runs low. The agent still owns the autonomous-spend property (no operator click required) without paying gas on every code.

    Which networks and assets does the x402 endpoint accept?

    Three networks are live for x402 settlement: Base mainnet (USDC) via EIP-3009, Solana mainnet (USDC + USDT) via the SVM exact scheme, and BNB Chain (USDC + USDT) via Permit2. Base is the primary EVM chain (lowest gas, broadest x402-fetch / x402-axios client support); BNB uses the canonical x402ExactPermit2Proxy contract for trustless witness-pattern settlement on tokens without native EIP-3009. Polygon, Arbitrum, and Optimism share the same Permit2 wire format and unlock with an env-var change — they're queued behind operator config, not implementation. The bearer-token API additionally accepts deposits in USDC on Tron, Polygon, Arbitrum, and BNB Chain via the standard /deposit flow for non-x402 customers.

    Can I use x402-fetch or x402-axios with VirtualSMS?

    Yes — both reference clients work out of the box. x402-fetch is the recommended path: wrap globalThis.fetch (Node 18+) with wrapFetchWithPayment, hand it the wallet client, and any 402 response is auto-settled by the time the promise resolves. The Python equivalent (x402-fetch via the requests session adapter, or coinbase-x402) follows the same shape. The reference snippets on this page show both. No custom payment loop required.

    How much should I keep in the agent wallet?

    Treat it as a $50-$100 float, not a treasury. The recommended pattern is one wallet per agent (or per agent fleet), capped at $50-$100 of USDC float, with a daily sweep cron that pulls accumulated balance back to a cold wallet. Activations bill at $0.05 per code, so $50 covers 1,000 SMS codes — more than enough headroom for any single-agent workload while keeping the blast radius small if the wallet is compromised.

    Published:
    VirtualSMS
    Engineering

    VirtualSMS

    Maintained by the VirtualSMS team. We've been shipping real-SIM SMS verification infrastructure since 2022 — 2500+ services across 145+ countries, MCP server v1.2.0 listed on Smithery and the official MCP registry. Open source, MIT licensed.

    Last updated:

    Related Articles

    Try x402 SMS Verification

    Three networks live: Base USDC · Solana USDC+USDT · BNB Chain USDC+USDT (Permit2) · $2 minimum top-up · $0.05 per SMS code · 2500+ services · 145+ countries · Auto-refund on no-SMS · 120 req/min default