Issue a virtual card with one x402 call
Last reviewed: August 2026
One paid HTTP request that returns a spendable virtual prepaid card. The flow: GET /get-card?amount=X answers with an x402 challenge quoting the exact USDC price, your client pays it and replays, the response carries a card_id plus API credentials, and polling the free GET /get-card-data endpoint returns the card number, expiry, CVV, and billing address about 7 to 10 seconds later. Works with any x402 client library, or with no wallet at all via the Laso-managed wallet.
Prerequisites
- A wallet holding USDC on Base or Solana, controlled by your agent or script. No Laso account, API key, or sign-up exists in this flow; the paying wallet is the identity.
- An x402 client library (
x402-fetch,x402-axios, or equivalent), or the willingness to construct the payment header yourself. - No wallet? Skip to the managed-wallet section at the end; a human approves a wallet once and the agent never touches a key.
Step 1 — Request a card and read the challenge
Call the endpoint with no payment attached. You get HTTP 402 with a machine-readable challenge. For a $50 card the price is exactly $50: U.S. cards carry a 0% Laso fee.
curl -i "https://laso.finance/get-card?amount=50"
# HTTP/1.1 402 Payment Required
# {
# "x402Version": 2,
# "accepts": [
# { "scheme": "exact", "network": "eip155:8453",
# "amount": "50000000",
# "payTo": "0x3291e96b3bff7ed56e3ca8364273c5b4654b2b37", ... },
# { "scheme": "exact", "network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
# "payTo": "3MZVk97x9SeRxbYpc3jhzRfU2fyA3emYutnqfn9kNfYX", ... }
# ]
# }
Two things worth noting. The amount is in atomic units: USDC has six decimals, so 50000000 is $50.00, and this figure is authoritative, fee-inclusive pricing you can check against your balance before paying. And the challenge offers both networks; pay whichever one your wallet lives on.
Step 2 — Pay the challenge and replay
Client libraries do the challenge handling for you. With x402-fetch on Base:
import { wrapFetchWithPayment } from "x402-fetch";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY);
const fetchWithPay = wrapFetchWithPayment(fetch, account);
const res = await fetchWithPay("https://laso.finance/get-card?amount=50");
const data = await res.json();
The paid response contains the order and, importantly, your API credentials for the free follow-up calls:
{
"auth": {
"id_token": "eyJ...",
"refresh_token": "AMf...",
"expires_in": "3600"
},
"user_id": "0xabc...",
"card": {
"card_id": "card_abc123",
"usd_amount": 50,
"country": "US",
"status": "pending"
}
}
The card number is deliberately not in this response. status is always pending at first; the details come from the next step.
Step 3 — Poll for the card details
Poll the free /get-card-data endpoint with the Bearer token every 2 to 3 seconds. status flips to ready in roughly 7 to 10 seconds:
curl "https://laso.finance/get-card-data?card_id=card_abc123" \
-H "Authorization: Bearer eyJ..."
# {
# "card_id": "card_abc123",
# "status": "ready",
# "usd_amount": 50,
# "card_details": {
# "card_number": "4111111111111111",
# "exp_month": "12",
# "exp_year": "2027",
# "cvv": "123",
# "available_balance": 50,
# "billing_address": {
# "name": "Laso Finance",
# "line_1": "440 N Barranca Avenue",
# "line_2": "#4496",
# "city": "Covina", "state": "CA", "zip": "91723", "country": "US",
# "required": false
# }
# },
# "transactions": []
# }
Everything a checkout form asks for is here. When a merchant wants a billing address or ZIP, use the returned billing_address; the billing name is always Laso Finance, and for U.S. cards any valid U.S. address also works (required: false). The same endpoint later returns the card’s transactions and remaining balance, so spend tracking needs no other tooling.
Step 4 — Keep your credentials alive
The id_token expires after an hour. Renew it for free, no wallet signature needed:
curl -X POST "https://laso.finance/auth" \
-H "Content-Type: application/json" \
-d '{"grant_type": "refresh_token", "refresh_token": "AMf..."}'
# { "id_token": "eyJ...", "refresh_token": "AMf...", "expires_in": "3600", "user_id": "0xabc..." }
If you need credentials before ever buying anything, GET /auth signs you in free with a wallet signature: send a SIGN-IN-WITH-X header (a CAIP-122 signed message; wrapFetchWithSIWx from @x402/extensions/sign-in-with-x builds it). A missing or rejected signature returns 402 with a fresh challenge to sign, never 401.
When the payment fails
The most common failure is an underfunded wallet. You get a second 402, distinguishable from the challenge by its body: a challenge carries accepts, a failed settlement carries success: false:
{
"success": false,
"errorReason": "insufficient_funds",
"errorMessage": "the transfer could not be settled on-chain",
"payer": "9sZE...9WXR",
"network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
}
Nothing is charged for a failed settlement, so retrying with a smaller amount is safe. Branch on errorReason, not the HTTP status.
No wallet? Use the managed wallet
An agent with no wallet at all can route the same purchase through a Laso-managed wallet: a human approves the wallet once from the agent dashboard and hands the agent a lasoak_ key. The agent signs in via /auth, then calls the agentX402Pay callable naming the route; Laso constructs and settles the x402 payment server-side, so the agent never builds a payment header or holds a private key:
curl "https://us-central1-kyc-ts.cloudfunctions.net/agentX402Pay" \
-X POST -H "Authorization: Bearer <id_token>" \
-H "Content-Type: application/json" \
-d '{"data": {"route": "get-card", "params": {"amount": "50"}}}'
# { "result": { "status": 200, "body": { "card": { "card_id": "...", "status": "pending" }, ... } } }
From there the flow is identical: poll /get-card-data, spend the card. The full agent-readable version of everything on this page, including gift cards, payouts, bank rails, and webhooks, lives at laso.finance/SKILL.md.
Limits and constraints, stated plainly
- U.S. cards: $5 to $1,000 each, USD, U.S. merchants and U.S. shipping addresses only, non-reloadable. Order one card per checkout, sized to the exact total.
- International cards:
GET /order-intl-card, $100 to $1,000 in whole dollars plus a 3.8% fee, queued and fulfilled by a human operator, typically within 24 hours. Not instant; plan for the delay or cancel free withPOST /cancel-intl-order. - No identity documents are involved in card orders. Identity verification exists only on specific features (Venmo/PayPal payouts), where the API returns a link for the agent’s human.
- Cards are single-load: spend down the balance across as many transactions as you like, but you cannot top them up. Leftover balances stay visible via
/get-card-data.
Frequently asked questions
Is it really one call?
One paid call. GET /get-card is the only request that costs anything; the polling call and token refresh are free. Counting HTTP round trips it is typically three requests over about ten seconds from nothing to a spendable card number.
How much USDC do I need for a $50 card?
Exactly $50 plus network transaction costs: U.S. cards carry a 0% Laso fee. The 402 challenge quotes the authoritative total in atomic units (50000000 for $50.00) before you pay, so verify against your balance rather than assuming.
Which chains and tokens can I pay with?
USDC on Base (eip155:8453) or Solana. Every challenge offers both networks and your client pays whichever one the wallet lives on. Deposits into a Laso account balance additionally accept USDC, USDT, and DAI on Ethereum, Solana, Stellar, Arbitrum, Base, and Polygon.
Can I test without spending real money?
There is no sandbox: payments settle on mainnet. The cheapest real test is the free path: GET /auth costs nothing with a wallet signature, and /get-card-data, /get-account-balance, and /search-gift-cards are free with the resulting Bearer token. The smallest card order is $5.
What happens to leftover balance on a card?
It stays on the card and remains spendable until depleted; /get-card-data shows the available balance and transactions. The intended pattern avoids leftovers: determine the exact checkout total first and size the card to it.
More guides
- How to give your AI agent a credit card — An AI agent cannot pass credit underwriting, but it can issue itself a virtual prepaid card over an API in about a minute. The working pattern, with real requests: x402 payment in, card number out.
- x402 vs AP2 vs ACP vs MPP vs UCP: which should your agent use? — All five agent payment protocols compared honestly: x402 and MPP for machine-to-machine HTTP payments, ACP for ChatGPT checkout, UCP for Google surfaces, AP2 for authorization. Which layer each one is, when to use each, and a worked x402 example.
- x402 vs Stripe Issuing for AI agents — Two real ways to put a card in an AI agent’s hands: Stripe Issuing behind a business account, or x402 card issuance the agent drives itself. An honest comparison of onboarding, funding, controls, and when each wins.
- All agent guides, or how Laso compares to the alternatives
Try it: connect a wallet at laso.finance and you'll have a card, gift card, or payout in minutes.
Building an agent? Point it at laso.finance/SKILL.md — it can set itself up.