Documentation

Connecting agents to AgentPays

Everything you need to give your AI agent a payment capability.

Quick start

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.

Setup

1

Create an account

Sign up at agentpays.dev.

2

Connect your Privacy.com account

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.

3

Create an agent

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.

4

Connect your AI assistant using one of the methods below

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 configuration

MCP endpoint: https://agentpays.dev/api/mcp

OAuth connection

Recommended

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.

json
{
  "mcpServers": {
    "agentpays": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://agentpays.dev/api/mcp"
      ]
    }
  }
}

Claude.ai

  1. 1. Go to Customize → Connectors → click the + button → Add custom connector
  2. 2. Enter AgentPays as the name and https://agentpays.dev/api/mcp as the URL
  3. 3. Click Add and complete the sign-in flow when prompted

ChatGPT

  1. 1. Go to Settings → Apps → Create App
  2. 2. Enter AgentPays as the name and https://agentpays.dev/api/mcp as the URL
  3. 3. Complete the OAuth flow

API key connection

For Claude Code, Codex, or custom agent frameworks. Requires an API key from the agent's settings page.

json
{
  "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.

Available tools

request_purchaseSubmit a purchase request

Input 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 currency
descriptionstringrequiredWhat is being purchased
justificationstringrequiredWhy this purchase is needed. Used for human review and auto-approval decisions
merchant_namestringHuman-readable merchant name (e.g. "AWS", "GitHub"). Descriptive only, not used for allow/deny decisions.
currencystringISO 4217 currency code, defaults to USD
category_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

approvedIncludes 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.
deniedIncludes reason explaining why the request was rejected (limit exceeded, merchant blocked, etc.) and an optional suggestion for how to proceed.
pending_reviewThe request exceeds the auto-approve threshold and is waiting for human review. Includes request_id and estimated_wait. Use check_status to poll for a decision.
check_statusCheck the status of a pending purchase request

Input fields

request_idstringrequiredThe request_id returned by request_purchase

Possible responses

approvedSame as request_purchase. Includes the card's last4, a secure view_url for retrieving full details, and card_expires_at.
deniedIncludes reason with the denial explanation.
pending_reviewStill awaiting a decision. Continue polling.
get_spending_summaryGet current spending vs. configured limits

No 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 today
daily_limitThe configured daily cap
daily_remainingRemaining headroom for today
daily_resets_atTimestamp when the daily window resets

Weekly 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 week
weekly_limitThe configured weekly cap
weekly_remainingRemaining headroom for this week
weekly_resets_atTimestamp when the weekly window resets

Monthly fields

Only present if a monthly limit is configured. Same shape, scoped to the monthly window.

monthly_spentSpend so far this month
monthly_limitThe configured monthly cap
monthly_remainingRemaining headroom for this month
monthly_resets_atTimestamp when the monthly window resets

Total budget fields

Only present if a total budget is configured for the agent.

total_budget_spentLifetime spend
total_budgetThe configured total budget
total_remainingRemaining headroom against the total budget

user_aggregate

Only present if the user has configured cross-agent caps.

An object containing up to three sub-objects: 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.

Security

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.

Threat model

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.

How AgentPays mitigates each threat

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.

What we do not claim

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.

Example usage

Example 1: An agent buying SaaS credits

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:

json
{
  "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:

json
{
  "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.

Example 2: A purchase that needs your approval

Same agent, but this time it wants to renew a GitHub Copilot seat. The amount is above the agent's auto-approve threshold:

json
{
  "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:

json
{
  "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:

json
{
  "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.

Example 3: Checking limits before a large purchase

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:

json
{}

AgentPays responds with what is available, both for this agent and for the account overall:

json
{
  "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.

Example 4: Retrying safely with an idempotency key

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:

json
{
  "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:

json
{
  "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.

Ready to connect your first agent?

Get started free

Questions or issues? Contact kevin@agentpays.dev