We shipped something a little unusual this week: your AI agent can now order a real, spendable card, paid for with its own crypto, without ever seeing the card number.
It's called the Payment Card Vault, and it's built on top of Laso, a payment API that takes x402 payments and turns them into prepaid Visa cards and gift cards in seconds.
The problem
Agents are increasingly asked to do things that cost money: buy a gift card for a contractor, pay for a subscription, cover a small purchase during an online checkout flow. The obvious way to enable that is to hand the agent a credit card number and let it fill out the form. The obvious way is also a bad idea. A credit card number sitting in an LLM's context window is a credit card number that can end up in a chat log, a debug trace, or the output of a prompt injection nobody saw coming. We've spent the last year building 1Claw specifically so that secrets don't have to live in an agent's context. Cards shouldn't be the exception.
So we built it the way we build everything else here: the sensitive part never leaves the vault.
How it actually works
An agent asks to order a card for a specific amount. 1Claw checks that card ordering is enabled for that agent, checks it against the per-order cap and the daily limit, and if it clears, signs an outbound x402 payment in USDC on Base using the agent's own Ethereum key. That payment goes straight to Laso. Laso issues a card. A background worker polls Laso every 15 seconds until the card is ready, then updates the record with a status, a last four digits, an expiry date, and a balance.
At no point in that sequence does the agent see a card number.
The agent gets back a card reference and a status. If it wants to check on things, it can list its cards, all masked. If it needs a human to actually use the card, to fill out a checkout form or redeem a gift code, the human reveals it, and that reveal requires a password, and it's logged.
You can also let an agent reveal a card itself, but only if a human explicitly turns that on for that specific card, with a cap on how many times it can happen and, if you want, an expiry on the permission. We didn't wire this into our MCP tools on purpose. A reveal tool would put a live card number directly into a model's context. That's exactly the thing this whole feature exists to prevent.
The code
Turning it on for an agent is one call, setting the caps that bound how much it can spend on cards:
await client.agents.update(agentId, {
cards_enabled: true,
card_max_order_usd: "100",
card_daily_limit_usd: "500",
});Ordering a card is another call:
const { data: card } = await client.cards.order(agentId, {
kind: "prepaid",
amount_usd: "25.00",
});
// card.status is "pending". No PAN, no CVV, ever, in this response.An Idempotency-Key gets attached automatically, so a timeout followed by a retry doesn't order two cards by mistake. A background worker polls Laso from there and moves the card to "ready" on its own. You can either poll client.cards.get(cardId) or register a webhook and listen for card.ready.
The only endpoint that ever returns a real PAN and CVV is this one, and it only runs for a human with a password:
const { data } = await client.cards.reveal(cardId, {
password: "your-password",
});
// { pan, cvv, exp_month, exp_year, disclaimer }Letting an agent reveal a card itself is a separate, explicit step a human takes on that one card, off by default:
await client.cards.update(cardId, {
agent_reveal: true,
max_reveals: 1,
reveal_expires_at: "2026-12-31T00:00:00Z",
});Everything else (listing cards, checking status, ordering a gift card instead of a prepaid card) comes back masked to last4. On MCP, an agent gets order_card, order_gift_card, search_gift_cards, list_cards, and get_card_status as tools. reveal_card is deliberately missing from that list.
A card can also be voided or refreshed after the fact. Void is a 1Claw-side lock: it blocks any further reveals or refreshes going forward, but it doesn't reach out and cancel a card that's already been revealed to someone. That card stays live wherever it ended up. Refresh just pulls the latest balance and status from Laso and is rate-limited on its own. And if a payment settles on our side but the card order doesn't come back cleanly from Laso, that doesn't fail silently. It fires its own webhook, card.orphaned_payment, so someone finds out instead of a card quietly going missing.
What we didn't do
We didn't try to control what happens after a card is revealed. Once a human (or an agent with permission) has the actual number, that card can be used anywhere, up to its balance, and 1Claw has no further say in it. Our guardrails bound the purchase, not the spend. We think that's an honest way to describe what this does. A system that claims to control spending after the number is already out is making a promise it can't keep.
We also didn't try to store card numbers long term. For Laso cards, we keep a card ID and a refresh token, encrypted the same way every secret in 1Claw is: envelope encryption, with the key wrapped by our HSM. The actual PAN and CVV get pulled from Laso just in time, at the moment of reveal, through that same HSM-gated path, and then they're gone again. That was a deliberate choice: the less raw card data exists anywhere, even encrypted, the smaller the blast radius if anything ever goes wrong, and the easier this is to reason about from a compliance standpoint. If you manually import a card you already have, it goes through that same HSM-backed vault encryption, and the CVV can only be read once before it's gone for good.
Try it
If you've got an agent running on 1Claw with USDC on Base, turning this on is a couple of API calls: enable card ordering, set a cap, order a card. Free tier ships with real caps already in place: $25 per order, $25 a day, five cards a month, and a 3% platform fee per order pulled from prepaid credits. The full writeup, including the guardrail options and the webhook events, is in the docs.
Docs: Payment Cards guide · Laso · Try it: agents.laso.finance
This is the first version. Merchant-locked cards, where 1Claw executes the checkout itself and the number never touches anyone's screen, not even a human's, are next.