TL;DR — x402 turns the dormant HTTP 402 “Payment Required” status code into a real payment protocol: an agent hits a paid endpoint, the server returns a 402 manifest (asset, amount, recipient), the agent’s wallet signs a USDC transfer, and the request retries with proof in the
X-PAYMENTheader — no API key handoff, no checkout, no human. VirtualSMS wires x402 to a deposit-first top-up (POST/x402/topup, settle once, spend the balance down) because settling per call would burn 20–40% of a $0.05 code in gas. Live on Base, Solana, and BNB Chain; $2 minimum top-up; real carrier-issued SIM cards across 2500+ services in 145+ countries; auto-refund if no SMS arrives.
An autonomous agent that provisions accounts hits the same wall a human developer does: it needs a phone number to receive an OTP, and it needs to pay for that number. The human answer is a dashboard, a saved card, and a copied API key. The agent answer, until recently, was “have a human do all of that first.” x402 removes the human. This guide covers what x402 is, why VirtualSMS settles it deposit-first instead of per-call, the exact three-round-trip top-up flow, and reference implementations in Python and Node — so an agent can fund its own SMS verifications end-to-end.
Key Takeaways
- x402 revives HTTP 402 as a machine-readable settlement protocol — the server names asset/amount/recipient, the agent’s wallet signs, the request retries with proof.
- VirtualSMS settles deposits, not individual codes — one on-chain settlement, then normal bearer-token API calls, so gas never dominates a $0.05 activation.
- Minimum top-up is $2 USDC; a $10 top-up funds roughly 200 codes at the $0.05 floor.
- Three networks are live: Base (USDC), Solana (USDC + USDT), BNB Chain (USDC + USDT via Permit2).
- Every number is a real carrier-issued SIM across 2500+ services in 145+ countries, with an auto-refund credited to the api_key balance if no SMS lands.
What Does x402 Solve for Autonomous Agents?
HTTP 402 Payment Required sat unused in the spec for three decades. x402 — the agentic-payments standard — finally gives it a job. The mechanic is small and clean: when an agent calls a paid endpoint without a payment proof, the server responds 402 with a structured manifest naming the accepted asset, the amount, and the recipient. The agent’s wallet signs an on-chain transfer, retries the request with the proof carried in the X-PAYMENT header, and the server returns the resource. There is no API key to issue, no operator-managed checkout, and no human in the loop.
For SMS verification the fit is exact, because the SMS-OTP primitive is something AI agents already need. An agent standing up Discord, Telegram, or WhatsApp presence — or any of 2500+ services across 145+ countries — can fund itself, top up its own balance, and keep verifying accounts indefinitely without an operator ever opening a billing portal. The agent owns its money path end to end.
For the cases that don’t need autonomous spend — operator-managed budgets, prepaid keys, or an assistant running inside Claude Desktop or Claude Code — the bearer-token API and the MCP server remain the right primitives. x402 is the tool for the self-funding-agent case specifically, not a replacement for everything else.
Why Deposit-First Instead of Pay-Per-Call?
VirtualSMS’s x402 endpoint settles deposits, not individual SMS codes. You POST to /x402/topup with an amount, settle the 402 response once, and the server returns an api_key bound to your wallet plus the deposited balance. Every verification after that is an ordinary bearer-token call against /v1/orders — no on-chain settlement per code.
The reason is gas economics, and the math is unforgiving:
| Model | On-chain settlements | Gas per code | Gas as % of a $0.05 code |
|---|---|---|---|
| True pay-per-call | One per SMS | ~1–2¢ | 20–40% |
| Deposit-first (VirtualSMS) | One per top-up | Amortized to ~0¢ | Rounding error |
Paying per call would burn a fifth to two-fifths of every activation in gas alone — a tax that scales linearly with throughput. Amortizing a single settlement across a $2–$10 deposit collapses that to nothing while keeping the property that actually matters: the agent still funds itself with no operator click. The $2.00 USDC minimum top-up exists for the same reason — anything smaller is uneconomic on-chain after gas. A $2 top-up funds 40 codes at the $0.05 floor, comfortably more than most single-task agent runs need.
How Does the x402 Top-Up Flow Work End-to-End?
Three round trips. The first request returns the manifest. The second carries the payment proof and the server hands back the API key. From there the agent just spends.
1. Initial request — the server returns a 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. An x402-fetch or x402-axios client reads this, picks the right scheme automatically, and signs the transfer.
2. Retry with X-PAYMENT — the server settles and 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 is bound to the wallet that paid — save it and reuse it for every subsequent 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 holds the key, every endpoint behaves exactly like 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 check what’s left. When balance approaches zero, top up again.
What Does the Python Reference Implementation Look Like?
Wrap a requests.Session with x402_fetch.wrap_fetch_with_payment, hand it the agent’s wallet, and the 402 dance runs automatically on the first POST. Subsequent SMS calls reuse the returned api_key with an ordinary 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 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")
To wire this into a LangChain, OpenAI Assistants, CrewAI, or Claude tool-use agent, drop the spend block into the body of a verify_phone tool — the full framework patterns are in the AI agent phone verification guide.
What Does the Node / TypeScript Version Look Like?
Same protocol, same flow, a viem wallet client in place of web3.py (Node 18+).
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 — the 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 deposit-first flow — swap the wallet client for @solana/web3.js and target the solana network entry in the manifest. x402-fetch selects the SVM exact scheme automatically when the signer is a Solana keypair.
BNB Chain variant: the wallet client stays viem-on-EVM; the difference is the 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, after which every payment is a gasless EIP-712 signature settled through a canonical proxy contract. The witness pattern on the proxy cryptographically binds the destination so the facilitator can’t redirect funds, and x402-fetch handles method selection from the manifest for you.
For the most common x402 target — agents provisioning Discord moderation bots, multi-server presence, or region-specific community managers — the Discord real-SIM API guide shows the verify-phone body collapsing identically against the api_key returned from the top-up.
How Should I Price and Size the Agent Wallet?
- Verifications from $0.05 per SMS code. Live per-service and per-country pricing is on the pricing page; a programmatic readout is available at
GET /v1/services/{service}/cheapest(unauthenticated). - Minimum x402 top-up: $2 USDC. Top up larger to reduce settlement frequency — a $10 top-up at $0.05/code funds roughly 200 activations.
- Recommended wallet float: $50–$100. Treat the payment wallet as a short-lived float, not a treasury: one wallet per agent (or per fleet), capped, swept daily to a cold wallet. That keeps the blast radius small if the key leaks.
- Auto-refund on no-SMS credits the api_key’s balance, not the wallet — the agent loop simply sees restored balance and continues.
- Discovery endpoints are unauthenticated — list services, list countries, check price, and find cheapest don’t require auth and don’t consume balance, so an agent can plan before it spends.
x402 vs Bearer-Token API vs MCP — Which Should You Pick?
Every number these paths return is a real carrier-issued SIM on networks like Vodafone, O2, T-Mobile, and Lebara — not a VoIP line — so the verification outcome is identical across all three. The choice is about control structure, not delivery quality.
| Use case | Recommended path | Why |
|---|---|---|
| Operator-funded SaaS (your server pays) | Bearer-token API + crypto deposit | One key, ops dashboard, monthly accounting |
| Claude Desktop / Claude Code agent | MCP server (operator key) | One-line install, no payment plumbing |
| Autonomous agent with its own wallet | x402 top-up | Agent self-funds, no operator in the loop |
| Multi-tenant platform (per-user billing) | x402 top-up per tenant | One api_key per wallet, clean billing isolation |
| Prototype or one-off script | Bearer-token API | Zero on-chain setup, fastest start |
x402 is a strict superset only when the agent already owns a wallet. For everything else, the bearer-token API and the MCP server stay the right primitives. Pick by how spending is controlled, not by which option is newest. If you’re weighing the non-x402 doors against each other, the MCP vs API comparison breaks down latency, auth, and discovery in detail.
What Are the Current Limitations?
- Network scope. x402 settlement is live on Base (USDC via EIP-3009), Solana (USDC + USDT via the SVM exact scheme), and BNB Chain (USDC + USDT via Permit2). Polygon, Arbitrum, and Optimism share the same Permit2 wire format and unlock with a configuration change rather than new implementation work.
- Per-call x402 is not exposed. Every paid endpoint returns the deposit manifest, not a per-call one — intentional, per the gas-economics section above. Per-call settlement may ship for high-value endpoints if the amortization math changes.
- Refund mechanics. Activation refunds restore
balance_usdon the api_key, not the wallet. Programmatic balance withdrawal back to the wallet is on the roadmap; until then, extraction goes through support. - Rate limits. 120 requests per minute per api_key by default — the same ceiling as the bearer-token API, liftable on request for production accounts.
Pre-launch checklist: seed the agent wallet with $2–$10 USDC on Base, run one top-up against production, confirm the api_key and balance came back, then run a single $0.05 activation end to end. After that, the agent loop runs without further operator involvement.
Rental Tiers — When One Code Isn’t Enough
Not every agent workload is a single OTP. Some need a number that stays reachable across sessions, or a dedicated inbox for a service over days. VirtualSMS covers those with two rental tiers:
- Full Access Rental — an entire real SIM, any service, for 1, 3, 7, 14, or 30 days. Every SMS from any service routes to your private inbox with no sharing.
- Platform Rental — one service on the partner network for 1, 3, or 7 days, with a 20-minute auto-refund window if no SMS arrives.
All tiers — single activations and both rentals — run on the same real carrier SIM inventory, so an x402-funded agent can mix a one-shot verification with a multi-day rental against the same balance.
The Bottom Line
x402 matters for SMS verification for one reason: it lets an autonomous agent fund its own OTPs with no operator in the money path. VirtualSMS makes that practical by settling deposits, not codes — one on-chain top-up, then ordinary bearer-token calls — so gas never taxes a $0.05 activation into unprofitability. Live on Base, Solana, and BNB Chain, with x402-fetch reference clients in Python and Node, an agent seeds a $2 wallet, runs one top-up, and verifies accounts indefinitely against real carrier SIMs.
Start with the API docs, read the MCP vs API breakdown if you’re not sure which door fits, or browse live SMS verifications and rental options to see coverage across 145+ countries.
Frequently Asked Questions
What is x402 and why does it matter for AI agents?
x402 is an open agentic-payments standard that turns the long-dormant HTTP 402 “Payment Required” status code into a real machine-readable settlement protocol. When an agent calls a paid endpoint without proof of payment, the server replies 402 with a structured manifest naming the accepted asset, the amount, and the recipient address. 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. For autonomous agents this matters because it removes the operator from the spending path entirely — no API key to issue by hand, no monthly invoice, no checkout form. The agent funds itself from a pre-authorized wallet and keeps working without anyone touching a billing portal.
How does x402 SMS verification work on VirtualSMS?
VirtualSMS exposes an x402 top-up endpoint that follows a deposit-first model instead of settling every SMS code on-chain. The agent POSTs to /x402/topup with an amount, the server returns a 402 with the USDC payment manifest, the agent’s wallet settles the transfer, and the 200 response carries an api_key plus the deposited balance. From there, every verification call is an ordinary bearer-token request against the same /v1/orders, /v1/services, and /v1/balance endpoints the operator-funded API uses. One on-chain settlement funds many activations, so the agent gets the autonomous-spend property without paying gas on each individual code.
Why deposit-first instead of true pay-per-call?
Gas economics. Each on-chain settlement costs roughly one to two cents in gas, while an SMS code starts from $0.05. Settling per call would burn 20–40% of the activation in gas alone — a tax that grows linearly with throughput. The deposit-first model amortizes a single settlement across a $2–$10 deposit, collapsing gas to a rounding error while preserving the property that matters most: the agent still funds itself with no operator click. Per-call x402 manifests are intentionally not exposed today; they may ship for high-value endpoints if the gas-amortization math ever changes.
Which networks and assets does the x402 endpoint accept?
Three networks are live for x402 settlement. Base mainnet settles USDC via EIP-3009 and is the primary EVM chain thanks to low gas and the broadest x402-fetch / x402-axios client support. Solana mainnet settles USDC and USDT via the SVM exact scheme. BNB Chain settles USDC and USDT via Permit2, using a canonical proxy contract and a witness pattern so the facilitator cannot redirect funds — this covers BEP-20 tokens that lack native EIP-3009. Polygon, Arbitrum, and Optimism share the same Permit2 wire format and unlock with a configuration change rather than new implementation work. For non-x402 customers, the standard bearer-token API additionally accepts deposits on several chains through the normal /deposit flow.
Can I use x402-fetch or x402-axios with VirtualSMS?
Yes — both reference clients work out of the box, and x402-fetch is the recommended path. In Node 18+, wrap globalThis.fetch with wrapFetchWithPayment and hand it a wallet client; any 402 response is auto-settled by the time the promise resolves. In Python, wrap a requests session with the equivalent adapter and the same 402 handshake happens on the first POST. After the top-up returns an api_key, every subsequent SMS call is a normal bearer-token request — no custom payment loop to write or maintain.
How much should I keep in the agent wallet?
Treat the payment wallet as a short-lived float, not a treasury. The recommended pattern is one wallet per agent (or per agent fleet), capped at roughly $50–$100 of USDC, with a daily sweep that pulls accumulated balance back to a cold wallet. Because verifications bill from $0.05 per code, $50 of float covers around 1,000 activations — ample headroom for any single-agent workload while keeping the blast radius small if the key ever leaks. Refunds on failed activations restore the api_key balance rather than the wallet, so the agent loop simply sees restored balance and continues.
When should I use the bearer-token API or MCP server instead of x402?
Pick by control structure, not novelty. If your own server pays for verification in an operator-funded SaaS, the bearer-token API with a crypto deposit gives you one key, an ops dashboard, and clean monthly accounting. If an AI assistant like Claude is in the loop, the MCP server is a one-line install with no payment plumbing. x402 is specifically for the case where an autonomous agent already owns a wallet and needs to fund itself with no operator in the loop — or for a multi-tenant platform that wants one api_key per wallet for clean per-tenant billing isolation. For a prototype or one-off script, the bearer-token API is the fastest start with zero on-chain setup.