Documentation
Everything you need to give your AI agent a payment capability.
AgentPays gives your AI agents a safe way to pay for things. Agents request purchases through MCP tools. You approve them, set spending limits, and AgentPays issues a single-use virtual card for each approved transaction.
Small purchases auto-approve based on rules you configure. Larger ones come to you for review. Your real credit card and bank account never touch the agent.
Sign up at agentpays.dev.
AgentPays issues single-use virtual Mastercards through Privacy.com when a purchase is approved. Sign up for a Privacy.com account, then go to Settings and paste your Privacy.com API key to enable card issuance.
Go to Agents → Create agent. Give it a name, set an auto-approve threshold, and add any spend rules you want enforced.
If you'll connect via OAuth (Claude Desktop, Claude.ai, ChatGPT), skip to step 4.
If you'll connect via API key (Claude Code, Codex, custom frameworks), copy the API key now. It's shown once and never again.
OAuth is recommended for Claude Desktop, Claude.ai, and ChatGPT, with no API key required. Use the API key method for Claude Code, Codex, or custom agent frameworks.
MCP endpoint: https://agentpays.dev/api/mcp
For Claude Desktop, Claude.ai, and ChatGPT. No API key required. Authentication happens through a sign-in flow on first use.
Claude Desktop
Add to claude_desktop_config.json, then restart Claude Desktop. A browser window will open on first use to complete sign-in.
{
"mcpServers": {
"agentpays": {
"command": "npx",
"args": [
"mcp-remote",
"https://agentpays.dev/api/mcp"
]
}
}
}Claude.ai
https://agentpays.dev/api/mcp as the URLChatGPT
https://agentpays.dev/api/mcp as the URLFor Claude Code, Codex, or custom agent frameworks. Requires an API key from the agent's settings page.
{
"mcpServers": {
"agentpays": {
"url": "https://agentpays.dev/api/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}Replace YOUR_API_KEY with the full key shown when you created the agent.
request_purchaseSubmit a purchase requestInput fields
merchant_urlstringrequiredMerchant domain (e.g. amazon.com, aws.amazon.com). Used to enforce the per-agent allowed/blocked domain rules with subdomain matching. Allowing amazon.com also allows aws.amazon.com and smile.amazon.com.amountnumberrequiredPurchase amount in the specified currencydescriptionstringrequiredWhat is being purchasedjustificationstringrequiredWhy this purchase is needed. Used for human review and auto-approval decisionsmerchant_namestringHuman-readable merchant name (e.g. "AWS", "GitHub"). Descriptive only, not used for allow/deny decisions.currencystringISO 4217 currency code, defaults to USDcategory_hintstringMerchant category slug (e.g. cloud_compute, software_saas)idempotency_keystringA stable key that uniquely identifies this purchase intent. Pass the same key if the agent retries after a timeout or unclear response — AgentPays returns the original result instead of issuing a second card or charging a second fee. An agent that always passes a key cannot accidentally buy the same thing twice. Omitting it falls back to a best-effort duplicate check on merchant and amount within ~90 seconds, but a key is the reliable mechanism.Possible responses
request_id and a virtual_card object with the card's last4 digits and a secure view_url for retrieving the full card number, expiry, and CVC. The link expires 20 minutes after approval.reason explaining why the request was rejected (limit exceeded, merchant blocked, etc.) and an optional suggestion for how to proceed.request_id and estimated_wait. Use check_status to poll for a decision.check_statusCheck the status of a pending purchase requestInput fields
request_idstringrequiredThe request_id returned by request_purchasePossible responses
request_purchase. Includes the card's last4, a secure view_url for retrieving full details, and card_expires_at.reason with the denial explanation.get_spending_summaryGet current spending vs. configured limitsNo input required.
Response fields
Only configured limits appear in the response. If you have not set a daily limit for the agent, the daily fields will be absent.
Daily fields
Only present if a daily limit is configured for the agent.
daily_spentSpend so far todaydaily_limitThe configured daily capdaily_remainingRemaining headroom for todaydaily_resets_atTimestamp when the daily window resetsWeekly fields
Only present if a weekly limit is configured. Same shape as the daily fields, scoped to the weekly window.
weekly_spentSpend so far this weekweekly_limitThe configured weekly capweekly_remainingRemaining headroom for this weekweekly_resets_atTimestamp when the weekly window resetsMonthly fields
Only present if a monthly limit is configured. Same shape, scoped to the monthly window.
monthly_spentSpend so far this monthmonthly_limitThe configured monthly capmonthly_remainingRemaining headroom for this monthmonthly_resets_atTimestamp when the monthly window resetsTotal budget fields
Only present if a total budget is configured for the agent.
total_budget_spentLifetime spendtotal_budgetThe configured total budgettotal_remainingRemaining headroom against the total budgetuser_aggregate
Only present if the user has configured cross-agent caps.
daily, weekly, and monthly, one for each configured aggregate cap. Each sub-object contains spent, limit, remaining, and resets_at, reporting cross-agent totals against the owner's caps.AgentPays sits between an AI agent and your real funding source. The design goal is straightforward: even if the agent is compromised, prompt-injected, or simply wrong, the worst it can do is spend one approved single-use card. The sections below describe the threats we explicitly defend against, the mechanisms we use, and the things we do not claim to solve.
Giving an LLM agent access to a payment instrument opens a specific set of failure modes. These are the ones we built around:
Credential exfiltration via prompt injection
A malicious tool result, web page, or document instructs the agent to leak its payment credentials to an attacker-controlled destination.
Compromised or malfunctioning agent
An agent that has been jailbroken, tampered with, or is simply behaving incorrectly drains funds at full speed against any stored payment method.
Rogue purchases at non-approved merchants
The agent decides (or is convinced) to spend at a merchant the operator never intended to authorize.
Replay with leaked card details
Card details captured from logs, screenshots, or shared context get reused later for unauthorized charges.
Card data persisting in agent memory and logs
Full PANs, expiry dates, and CVCs end up in long-lived agent context, transcript exports, tool-call traces, or third-party log sinks where they remain useful long after the original purchase.
Credential isolation
Your real credit card, bank account, and Privacy.com API key live behind AgentPays and are never sent to the agent or exposed through any MCP response. The agent only ever holds material it could not reuse against your underlying funding source.
Single-use virtual cards
Every approved purchase generates a new virtual Mastercard scoped to that one transaction amount. After it is charged once, it is dead. There is no persistent card the agent can spend against tomorrow.
Out-of-band card delivery
Card number, expiry, and CVC never appear in the MCP response itself. The response carries only the last 4 digits and a secure view URL. The agent must fetch the full details from that URL to complete checkout.
Short-lived view URL
The secure view link is signed with a time-limited token that expires 20 minutes after approval. A URL captured from logs or chat history past that window cannot be opened.
Bounded blast radius
If the view URL is opened by an attacker or the card details are scraped before expiry, the damage is capped at the single approved transaction amount at the approved merchant category. Your underlying funding source is untouched.
Server-side rule enforcement
Per-transaction limits, daily/weekly/monthly caps, allowed/blocked merchant domains, and the auto-approve threshold are evaluated by AgentPays before any card is issued. The agent cannot bypass a rule by lying about the request or ignoring the configuration.
Cross-agent aggregate caps
Per-agent limits don't stop two agents from each spending up to their own cap and collectively going past your real intent. AgentPays lets you set optional daily, weekly, and monthly aggregate caps that apply across every agent on your account combined. The rules engine checks them after per-agent rules and denies the request if the user-level total would exceed the cap. Configure them in Settings.
Three-tier approval architecture
Requests that pass all rules and are under the auto-approve threshold execute immediately. Requests above the threshold land in a human review queue and only issue a card after explicit approval. Any rule violation is a hard denial. No card is ever issued.
Full audit trail
Every request, approval, denial, rule evaluation, and card issuance is recorded and visible in the dashboard. There is a complete record of who asked for what, when, and how it was decided.
The line between “what AgentPays defends” and “what is still your problem” matters more than marketing copy. Honest framing here:
The agent does see the single-use card
AgentPays does not hide all card data from the agent. To complete a checkout the agent has to open the view URL and read the card number, expiry, and CVC. What we isolate is your real funding source (credit card, bank account, Privacy.com API key), not the disposable card that exists for one transaction.
We do not prevent all prompt injection
An injected instruction can still cause the agent to call request_purchase with attacker-influenced inputs. Our defense is what happens after the call (rules, thresholds, human approval, and a single-use card with a bounded amount), not stopping the call from being attempted.
The view URL page can be scraped
A sufficiently capable attacker who obtains a live view URL within the 20-minute window can render the page and exfiltrate the card details. The mitigation is not page-level scrape resistance; it is that the card behind the page is single-use and scoped to one transaction, so the captured details are usable exactly once and only at the approved amount.
We rely on Privacy.com's underlying issuing security
AgentPays uses Privacy.com as the card issuer in v1. The security properties of card issuance, network authorization, and merchant controls come from Privacy.com. A failure in their issuing stack would affect AgentPays customers like any other Privacy.com user.
Your agent is helping you run an engineering team. Mid-task it hits a paid-tier wall on Cloudflare Workers and needs to top up credits to keep going. Rather than stopping and asking you to grab a card, it requests the purchase through AgentPays:
{
"merchant_url": "cloudflare.com",
"merchant_name": "Cloudflare",
"amount": 5.00,
"description": "Cloudflare Workers paid plan top-up",
"justification": "Hitting free tier limits on production worker, need paid plan to keep handling traffic"
}The amount is under the agent's auto-approve threshold, so AgentPays approves it and issues a single-use virtual card scoped to this transaction:
{
"status": "approved",
"request_id": "req_7f3c9a21",
"virtual_card": {
"last4": "8061",
"view_url": "https://agentpays.dev/card/0d4a1e8c2b",
"view_expires_at": "2026-05-29T18:20:00Z"
},
"message": "Purchase approved. A virtual card ending in 8061 has been issued."
}The agent opens the view_url, reads the card number, expiry, and CVC, and uses them at Cloudflare's checkout. The card is good for exactly one authorization. Once Cloudflare runs the charge, the card auto-closes. No standing card sits with the merchant. No reusable credential exists after this purchase.
Same agent, but this time it wants to renew a GitHub Copilot seat. The amount is above the agent's auto-approve threshold:
{
"merchant_url": "github.com",
"merchant_name": "GitHub",
"amount": 12.00,
"description": "GitHub Copilot seat renewal",
"justification": "Engineering team needs Copilot autocomplete restored, seat renewal at standard monthly rate"
}AgentPays does not issue the card. The purchase goes into a pending state and you get an email:
{
"status": "pending_review",
"request_id": "req_b18d40f5",
"message": "Awaiting owner approval. You will be notified by email.",
"estimated_wait": "Typically within an hour"
}You open the email, read what the agent is asking to buy and why, and approve it in the dashboard. The agent has been polling in the meantime:
{
"status": "approved",
"request_id": "req_b18d40f5",
"virtual_card": {
"last4": "8213",
"view_url": "https://agentpays.dev/card/9c7b3f0a1d",
"view_expires_at": "2026-05-29T19:05:00Z"
}
}Now the card exists, the agent retrieves it, and the GitHub renewal goes through. The point of the review step is not to slow agents down. It is to give you a clear stop on anything above a threshold you set, with full context (merchant, amount, justification, requesting agent) before money moves.
You have aggregate caps set on your account: $30 daily, $100 weekly across all your agents. Your engineering agent has already spent $17 today on smaller purchases. Now your research agent wants to spin up AWS credits for a training job over the weekend, and the amount is significant. Before sending the request, the agent checks where you stand:
{}AgentPays responds with what is available, both for this agent and for the account overall:
{
"daily_spent": 0.00,
"daily_limit": 30.00,
"daily_remaining": 30.00,
"daily_resets_at": "2026-05-30T00:00:00Z",
"user_aggregate": {
"daily": {
"spent": 17.00,
"limit": 30.00,
"remaining": 13.00
},
"weekly": {
"spent": 17.00,
"limit": 100.00,
"remaining": 83.00
}
}
}The agent's own daily budget is untouched, but the account is close to its daily cap. The research agent wanted $25 of credits, that would push the daily aggregate to $42, well past the $30 limit. Rather than fire off a request that will get denied, the agent has a few real options. It can wait until the cap resets and try then. It can split the purchase into a smaller piece that fits today and a larger piece for tomorrow. It can flag the issue back to you and ask whether to raise the cap.
What matters is that the agent does not have to guess what will succeed. The limits are visible. The reasoning is visible. Spending decisions stay observable on both sides.
Your agent is deploying a production pipeline and needs a persistent server. It calls request_purchase with an idempotency_key tied to this specific intent:
{
"merchant_url": "render.com",
"merchant_name": "Render",
"amount": 14.00,
"description": "Render web service — starter plan, 1 month",
"justification": "Deploying the production data pipeline; need a persistent server to keep it running",
"idempotency_key": "deploy-pipeline-render-2026-06-02"
}AgentPays approves it and issues a virtual card. But the network drops before the response arrives. The agent has no idea whether the request went through. The wrong move is to give up on the card. The risky move is to retry blindly and risk a duplicate purchase. The right move is to retry with the same key:
// Same call, same idempotency_key — just retry
AgentPays recognizes the key, finds the original request, and returns the same result:
{
"status": "approved",
"request_id": "req_d29b73ae",
"virtual_card": {
"last4": "5527",
"view_url": "https://agentpays.dev/card/7e4f1b9c2a",
"view_expires_at": "2026-06-02T14:35:00Z"
},
"message": "Purchase approved. A virtual card ending in 5527 has been issued."
}Same request_id, same card, no second issuance, no second fee. The key should be stable and unique per purchase intent — something like a hash of the task, a UUID generated when the intent is first formed, or a descriptive string like the one above. The important thing is that retries reuse it; a new key on every retry defeats the purpose.
When setting up your agent's system prompt, encourage clear justifications, full merchant URLs with subdomains, and a check_status poll for any pending_review response.