Documentation

Connecting agents to Authoryze

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

Quick start

Authoryze gives your AI agents a safe way to pay for things. Agents request purchases through MCP tools. You approve them, set spending limits, and the agent retrieves a single-use virtual card for each approved purchase when it's ready to pay.

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 authoryze.ai.

2

Add a card to pay the Authoryze fee

Go to Payment Methods and add a card under Saved cards. This is a normal Stripe-collected card used only to charge Authoryze's 1.5% (or $0.50 minimum) transaction fee. It is never used to fund the agent's purchase.

3

Enroll a funding card with Basis Theory

Authoryze issues single-use virtual cards over Mastercard (Mastercard Agent Pay) and Visa (Visa Intelligent Commerce) through Basis Theory's agentic card network. On the same Payment Methods page, under Card for agent purchases, enter your card number, expiry, and CVC. The card data is tokenized directly by Basis Theory in your browser and never touches Authoryze's servers. You then complete a one-time verification (a one-time code plus a passkey, using Touch ID, Face ID, or a hardware security key) to activate the card as your agents' funding source.

You can use the same card for both the fee and agent funding, or use two different cards.

4

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 6.

If you'll connect via API key (Claude Code, Codex, custom frameworks), copy the API key now. It's shown once and never again.

5

(Optional) Set up automatic spending

On the agent's detail page, you can authorize an automatic-spending envelope: an amount cap (one-time or recurring) the agent can draw against without a per-purchase tap, also passkey-verified. Without an envelope, Basis Theory is still the funding rail, but a purchase over the auto-approve threshold routes to you for a one-off authorization sized to that exact amount.

Privacy.com is supported as a secondary, fallback rail. It is used automatically if Basis Theory cannot fund a purchase, or you can make it primary in Settings → Default payment method. To enable it, paste a Privacy.com API key under Settings → Privacy.com integration.

6

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://authoryze.ai/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.ai and Claude Desktop

  1. 1. Go to Customize → Connectors → click the + button → Add custom connector
  2. 2. Enter Authoryze as the name and https://authoryze.ai/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 Authoryze as the name and https://authoryze.ai/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": {
    "authoryze": {
      "url": "https://authoryze.ai/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, Authoryze 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 retrievable: true. No card data is returned here. Call retrieve_card once with this request_id, when you are ready to pay, to draw and receive the single-use card inline.
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. Poll check_status with this request_id until it resolves to approved, then call retrieve_card once.
failedA recoverable error before any card was issued (e.g. a missing payment method or issuer key). Includes reason, retryable: true, and an optional suggestion. Safe to retry by resubmitting with the same idempotency_key.
check_statusCheck the status of a purchase request. Read-only: never issues, draws, or reveals a card.

Input fields

request_idstringrequiredThe request_id returned by request_purchase

Possible responses

approvedIncludes a retrievable boolean. true means the single-use card has not been drawn yet. Call retrieve_card once when you are ready to pay. false means it was already retrieved and cannot be shown again (includes last4 for reference; start a new purchase if you need another card). No card data is ever returned by this tool.
deniedIncludes reason with the denial explanation.
pending_reviewStill awaiting a decision. Continue polling.
processingAn idempotency-keyed request is still being evaluated. Includes message. Keep polling; do not submit a new request.
failedThe purchase attempt failed before a card was issued. Includes reason and retryable: true, safe to retry by resubmitting the original request with the same idempotency_key.
retrieve_cardDraw the single-use card for an approved request: call exactly once

Draws and returns the single-use virtual card for an approved purchase request. Call this exactly once, only when you are ready to pay. The card number, expiry, and CVC are returned inline in the response and shown a single time. There is no re-draw. Drawing the card consumes the purchase's spending envelope, so do not call this speculatively or to poll status (use check_status for that).

Input fields

request_idstringrequiredThe request_id returned by request_purchase

Possible responses

approvedSuccess. Includes a card object with number, exp_month, exp_year, cvc, last4, and expires_at. This is the only time the full card details are ever returned. Store them immediately and complete the purchase.
already_retrievedThe card for this request was already drawn by an earlier call. Includes retrievable: false. It cannot be shown again; start a new purchase if you need another card.
not_approvedThe request is not in the approved state (still pending, denied, etc.), so there is nothing to draw yet. Poll check_status and wait for approved before calling this.
not_fundedThe request cannot be funded right now, for example a missing issuer key or funding envelope on the account. This is an account-configuration problem, not something the agent can retry around.
retrieve_failedThe draw attempt failed at the card issuer. Includes retryable: true when a retry is safe (no funds were consumed).
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

Authoryze 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.

Replayed or duplicate retrieve_card calls

An attacker or a buggy agent calls retrieve_card a second time on the same request, hoping to draw a second card or have the card shown again.

Card data persisting in agent memory and logs

The card is returned inline in a single MCP tool response. Once delivered, the number, expiry, and CVC can end up in long-lived agent context, transcript exports, tool-call traces, or third-party log sinks where they remain readable long after the original purchase.

How Authoryze mitigates each threat

Credential isolation

On the primary rail, the agent receives a network-tokenized, one-time-use Mastercard or Visa credential (Mastercard Agent Pay or Visa Intelligent Commerce) drawn from Basis Theory at the moment of purchase, not your real card. Your actual funding card lives behind a Basis Theory enrollment that you verify with a passkey, and is never sent to the agent or exposed through any MCP response. If a purchase is funded through the secondary Privacy.com rail instead, the same isolation applies: your Privacy.com API key stays server-side and 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 card (Mastercard or Visa on the primary rail, Mastercard on Privacy.com) 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.

Card data is never stored

The card number, expiry, and CVC are drawn from the issuer on demand, at the moment retrieve_card is called, and returned inline in that single response. Authoryze never writes the PAN, CVC, or expiry to our database, not even encrypted. The only thing we persist afterward is non-sensitive provenance: last 4 digits and a provider token, used for audit and to power check_status.

Draw-once enforcement

Drawing a card is an atomic, at-most-once claim on the purchase request. The first retrieve_card call wins the draw and gets the card; every call after that, whether a retry, a replay, or an attacker probing a leaked request_id, returns already_retrieved instead of issuing or re-showing a card.

Bounded blast radius

If the card details are captured after retrieval, the damage is capped at the single approved transaction amount at the approved merchant. The card itself has a short expiry window. 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 Authoryze 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. Authoryze 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 Authoryze defends” and “what is still your problem” matters more than marketing copy. Honest framing here:

The agent does see the single-use card

Authoryze does not hide all card data from the agent. retrieve_card returns the full card number, expiry, and CVC directly in its response so the agent can complete checkout. On the primary rail that card is a network-tokenized, one-time-use Mastercard or Visa credential (Mastercard Agent Pay or Visa Intelligent Commerce) issued through Basis Theory, not your real funding card. What we isolate is your real funding source (the enrolled card behind Basis Theory, your bank account, or your Privacy.com API key on the secondary rail), 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 card can persist in the agent's own context after delivery

Because the card is returned inline in the retrieve_card response, it becomes part of whatever holds that response: the agent's tool-call history, conversation transcript, exported logs, or any third-party logging the agent's host platform performs. We do not control retention there, and we cannot redact or expire it after the fact. This is the real residual exposure in the current design. It is bounded, not eliminated, by the properties above: the card is single-use, scoped to the one approved amount, has a short expiry, and can be drawn at most once per request, so a credential that leaks from agent-side logs is worth exactly one transaction at exactly one amount, not standing access to your funding source.

We rely on our card-issuance partners' underlying security

On the primary rail, card issuance, network tokenization, and authorization controls come from Basis Theory and the card networks it issues over: Mastercard Agent Pay and Visa Intelligent Commerce. A network-tokenized, one-time-use credential is not the same thing as a stored, reusable card number, but we are not asserting a formal PCI scope conclusion here, that determination belongs to a qualified assessor. Privacy.com is the secondary rail and a purchase funded through it inherits Privacy.com's issuing security instead. Either way, a failure in a partner's issuing stack would affect Authoryze customers like any other customer of that partner.

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 Authoryze:

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",
  "merchant_country_code": "US"
}

The amount is under the agent's auto-approve threshold, so Authoryze approves it. No card is issued yet, the response just confirms the card is ready to be drawn:

json
{
  "status": "approved",
  "request_id": "req_7f3c9a21",
  "retrievable": true,
  "message": "Approved. Call retrieve_card once with this request_id, when ready to pay, to get the single-use card. The card is shown only once and drawing it consumes the spending envelope."
}

The agent calls retrieve_card once, right when it's ready to check out, with the same request_id:

json
{
  "status": "approved",
  "request_id": "req_7f3c9a21",
  "card": {
    "number": "5413339000018061",
    "exp_month": 9,
    "exp_year": 2027,
    "cvc": "842",
    "last4": "8061",
    "expires_at": "2027-09-30T00:00:00Z"
  },
  "message": "Single-use card details below. They are shown only once. Store them now and complete the purchase. The card is scoped to this one transaction."
}

The card number, expiry, and CVC come back inline, shown this one time. The agent uses them immediately at Cloudflare's checkout. The card is good for exactly one authorization, drawing it already consumed the spending envelope, so a second call to retrieve_card for the same request returns already_retrieved instead of the card again. 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",
  "merchant_country_code": "US"
}

Authoryze 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 check_status in the meantime, which is read-only and never reveals a card on its own:

json
{
  "status": "approved",
  "request_id": "req_b18d40f5",
  "retrievable": true,
  "message": "Approved. Call retrieve_card once with this request_id when ready to pay to get the single-use card. The card is shown only once, and drawing it consumes the spending envelope."
}

Now that retrievable is true, the agent calls retrieve_card once to draw the card:

json
{
  "status": "approved",
  "request_id": "req_b18d40f5",
  "card": {
    "number": "5413339000028213",
    "exp_month": 11,
    "exp_year": 2027,
    "cvc": "519",
    "last4": "8213",
    "expires_at": "2027-11-30T00:00:00Z"
  },
  "message": "Single-use card details below. They are shown only once. Store them now and complete the purchase. The card is scoped to this one transaction."
}

The GitHub renewal goes through with the inline card details. 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
{}

Authoryze 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-07-01T00:00:00Z",
  "user_aggregate": {
    "daily": {
      "spent": 17.00,
      "limit": 30.00,
      "remaining": 13.00,
      "resets_at": "2026-07-01T00:00:00Z"
    },
    "weekly": {
      "spent": 17.00,
      "limit": 100.00,
      "remaining": 83.00,
      "resets_at": "2026-07-05T00:00:00Z"
    }
  }
}

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",
  "merchant_country_code": "US",
  "idempotency_key": "deploy-pipeline-render-2026-06-02"
}

Authoryze approves it. 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. 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

Authoryze recognizes the key, finds the original request, and returns the same result instead of approving a second time:

json
{
  "status": "approved",
  "request_id": "req_d29b73ae",
  "duplicate_of": "req_d29b73ae",
  "retrievable": true,
  "message": "Duplicate request: this purchase was already approved as request req_d29b73ae (same idempotency_key). No new card was issued and you were not charged again. Call retrieve_card once with request_id req_d29b73ae when ready to pay to get the single-use card. This idempotency_key was already used for request req_d29b73ae; if you intended a genuinely new, separate purchase, resubmit with a different idempotency_key."
}

Same request_id, retrievable: true, no second issuance, no second fee. The agent still needs one retrieve_card call against that request_id to get the card, exactly as in the earlier examples. 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, a check_status poll for any pending_review response, and a single retrieve_card call (only when actually ready to pay) once a request is retrievable.

Ready to connect your first agent?

Get started free

Questions or issues? Contact kevin@authoryze.ai

Connect your AI agent via MCP | Authoryze Docs