# Issuing for agents Learn how to issue cards for agents. Issuing for agents lets you issue virtual cards that agents can use to make purchases autonomously, with spend controls, real-time authorization decisioning, and full transaction visibility. Before your agent makes a purchase, you can decide what it can spend, where, and how much. Cards are backed by financial accounts and issued using Stripe Issuing APIs. ## Issuing for agents products You can use Issuing for agents with the following Issuing products: | Product | Description | Request access | | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | | Cards for your own business | Use Issuing to give each agent its own virtual card with per-agent spend limits, merchant category controls, and custom authorization rules. Common use cases include buying inventory to resell, covering operational expenses, and making purchases to fulfill a service. | [Apply in the Stripe Dashboard](https://dashboard.stripe.com/issuing/overview) | | Cards for your platform | If you’re a platform, such as a fintech, vertical SaaS, or marketplace, you can use Issuing to let agents spend on behalf of the businesses or consumers on your platform. Issue commercial cards for business customers managing expenses, or consumer cards for individuals making personal purchases. Your cardholders configure their own spend limits, merchant category restrictions, and authorization rules. You retain transaction-level visibility across all cards that your platform issues. | [Contact Stripe](https://stripe.com/contact/embedded-finance) | ## Issuing for agents capabilities | Capability | Description | | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Single-use cards](https://docs.stripe.com/issuing/controls/lifecycle-controls.md) | Issue virtual cards scoped to a single task or session. Cards are automatically invalidated after use. | | [Real-time authorizations](https://docs.stripe.com/issuing/controls/real-time-authorizations.md) | Approve or decline every transaction using webhooks. Make authorization decisions based on a business’s details and the card’s metadata. You own the authorization integration. | | [Spend controls](https://docs.stripe.com/issuing/controls/spending-controls.md#limit-a-cardholders-monthly-spend-across-all-of-their-cards) | Set limits on how much and how often consumers can spend, and which merchant categories are allowed. You can set controls at the card or cardholder level. | | [Full transaction visibility](https://docs.stripe.com/issuing/purchases/transactions.md) | Track every transaction including captures, refunds, partial captures, over-captures, and force captures, and reconcile them back to the originating card and purchase using metadata. | | [Advanced fraud signals](https://docs.stripe.com/issuing/controls/advanced-fraud-tools.md#get-started-with-advanced-fraud-tooling) | Get machine learning-generated risk scores on every authorization, including fraud risk, merchant dispute risk, and card testing detections. Opt in within the Stripe Dashboard. | ## Virtual cards Virtual cards are the most common card type for agentic use cases. They exist only as a card number, expiration date, and CVC, with no physical card representation. When you issue one, an agent can start making purchases immediately. Because they’re digital, you can limit the card’s functionality to a single business, a single transaction, or a specific amount before the agent uses it. First, use this call to issue a virtual card scoped to a specific merchant category and spend limit: ```curl curl https://api.stripe.com/v1/issuing/cards \ -u "{{SECRET_KEY}}:" \ -d "cardholder"="ich_123" \ -d "currency"="usd" \ -d "type"="virtual" \ -d "status"="active" \ -d "spending_controls[allowed_categories][]"="computer_software_stores" \ -d "spending_controls[spending_limits][0][amount]"=50000 \ -d "spending_controls[spending_limits][0][interval]"="monthly" ``` Next, retrieve the card number and CVC, and pass them to your agent at checkout: ```curl curl -G https://api.stripe.com/v1/issuing/cards/ic_123 \ -u "{{SECRET_KEY}}:" \ -d "expand[]"=number \ -d "expand[]"=cvc ``` The response includes the card credentials your agent needs to complete a purchase: ```json { "id": "ic_123", "number": "4242424242424242", "cvc": "123", "exp_month": 12, "exp_year": 2027, "status": "active" } ``` ## Single-use cards For one-off purchases such as a supplier payment, a fulfillment order, or a customer transaction, you can issue a card that automatically cancels after a single authorization clears. This means even if the card credentials are exposed after the purchase, they can’t be used again. Use metadata to tie each card back to the specific task, order, or agent that triggered it. First, use this method to issue a card that cancels itself after one successful charge equal to a specific amount: ```curl curl https://api.stripe.com/v1/issuing/cards \ -u "{{SECRET_KEY}}:" \ -d "cardholder"="ich_123" \ -d "currency"="usd" \ -d "type"="virtual" \ -d "status"="active" \ -d "lifecycle_controls[cancel_after][payment_count]"=1 \ -d "spending_controls[spending_limits][0][amount]"=7500 \ -d "spending_controls[spending_limits][0][interval]"="per_authorization" \ -d "metadata[agent_id]"="agent_fulfillment_01" \ -d "metadata[customer_order_id]"="order_8821" \ -d "metadata[supplier]"="supplier_logistics_co" ``` Next, retrieve the card credentials and pass them to your agent at checkout: ```curl curl -G https://api.stripe.com/v1/issuing/cards/ic_123 \ -u "{{SECRET_KEY}}:" \ -d "expand[]"=number \ -d "expand[]"=cvc ``` ## Spend controls Before an agent ever makes a purchase, you can define what it’s allowed to spend, where, and how often. These controls are set at card creation and can be updated at any time. You can tighten them when a task changes scope, loosen them when more budget is approved, or remove them for trusted agents with broad mandates. Merchant category controls restrict the card to specific types of businesses. For example, a travel booking agent should only be able to charge airlines and hotels, and not restaurants or retail stores: ```curl curl https://api.stripe.com/v1/issuing/cards \ -u "{{SECRET_KEY}}:" \ -d "cardholder"="ich_123" \ -d "currency"="usd" \ -d "type"="virtual" \ -d "status"="active" \ -d "spending_controls[allowed_categories][]"="airlines_air_carriers" \ -d "spending_controls[allowed_categories][]"="hotels_motels_and_resorts" ``` Spend limits set how much the card can be charged, either per transaction or over a rolling period: ```curl curl https://api.stripe.com/v1/issuing/cards/ic_123 \ -u "{{SECRET_KEY}}:" \ -d "spending_controls[spending_limits][0][amount]"=100000 \ -d "spending_controls[spending_limits][0][interval]"="monthly" \ -d "spending_controls[spending_limits][1][amount]"=10000 \ -d "spending_controls[spending_limits][1][interval]"="per_authorization" ``` ## Real-time authorization After you pass a card to an agent, every purchase attempt triggers a real-time authorization request before the charge goes through. This lets you approve or decline the transaction based on your spending rules, fraud signals, merchant category restrictions, or context about what the agent is told to do. First, listen for `issuing_authorization.request` events. Each event contains the business, amount, and any metadata you attached to the card when you issued it. There is a 2 second default timeout to respond before Stripe falls back to the card’s default rules: ```json { "type": "issuing_authorization.request", "data": { "object": { "id": "iauth_123", "amount": 9900, "merchant_data": { "name": "Acme Supplies", "category_code": "5045", "city": "San Francisco", "country": "US" }, "card": { "metadata": { "agent_id": "agent_fulfillment_01", "customer_order_id": "order_8821", "allowed_merchant": "supplier_acme" } } } } } ``` Next, use the authorization payload to run any checks your business requires before approving. Common patterns include: - **Business match**: Verify the business name or category matches the agent’s task - **Amount confirmation**: Confirm the charge is within the expected budget for the order or task - **Velocity check**: Flag if the agent has attempted an unusual number of transactions in a short window - **Fraud signals**: Cross-reference the business’s country, IP, or category against known fraud patterns If the transaction looks legitimate, approve it. If anything looks off, decline it and flag with the agent or a human reviewer. You can use Stripe advanced fraud tools in your decision making process. Stripe evaluates every authorization for fraud signals and produces a risk score you can factor into your approval logic: ```json { "type": "issuing_authorization.request", "data": { "object": { "id": "iauth_123", "amount": 9900, "fraud_challenges": [], "network_risk_score": 23, "merchant_data": { "name": "Acme Supplies", "category_code": "5045" }, "verification_data": { "address_line1_check": "match", "postal_code_check": "match", "cvc_check": "match" } } } } ``` A low risk score alongside passing address and CVC checks is a signal to approve. A high risk score, especially combined with a mismatched address or an unfamiliar business country, is a signal to decline and investigate before letting the agent proceed. ## Monitor the agent’s transactions Every transaction your agent makes is traceable. Use Stripe webhooks and transaction data to track spend, catch anomalies, reconcile purchases, and dispute overcharges automatically, without manual oversight. ### Detect unusual spending Agents can continuously scan transaction history to detect unusual purchases, such as charges from unfamiliar businesses, transactions that exceed typical amounts, or activity outside expected hours. When an agent detects a suspicious transaction, it can automatically freeze the card or flag it for review. First, pull recent transactions for a cardholder to give your agent a window of activity to review: ```curl curl -G https://api.stripe.com/v1/issuing/transactions \ -u "{{SECRET_KEY}}:" \ -d "cardholder"="ich_123" \ -d "limit"=100 ``` Next, pass the transaction list to your agent. Flag any transaction where the merchant category falls outside what’s expected, or where the amount is significantly higher than the cardholder’s historical average: ```json { "transactions": [ { "amount": 42000, "merchant_data": { "category_code": "5999", "name": "Unknown Merchant" }, "card": { "metadata": { "agent_id": "agent_finance_01", "cost_center": "engineering" } } } ] } ``` If the agent flags a transaction, freeze the card immediately while the issue is investigated: ```curl curl https://api.stripe.com/v1/issuing/cards/ic_123 \ -u "{{SECRET_KEY}}:" \ -d "status"="inactive" ``` ### Track spending against budgets Every card can carry a spend limit, a monthly maximum, a per-transaction maximum, or both. Agents can monitor how much of that budget has been used in real time and take action before a limit is reached by alerting the cardholder, requesting a budget increase, or blocking new purchases until the next period resets. First, subscribe to `issuing_authorization.created` to capture each purchase as it’s approved: ```json { "type": "issuing_authorization.created", "data": { "object": { "amount": 15000, "card": { "spending_controls": { "spending_limits": [{ "amount": 50000, "interval": "monthly" }] }, "metadata": { "agent_id": "agent_finance_01" } } } } } ``` As authorizations come in, add them up against the card’s monthly limit. When spend crosses a threshold (for example, 80%), notify the cardholder or adjust the limit: ```curl curl https://api.stripe.com/v1/issuing/cards/ic_123 \ -u "{{SECRET_KEY}}:" \ -d "spending_controls[spending_limits][0][amount]"=40000 \ -d "spending_controls[spending_limits][0][interval]"="monthly" ``` ### Reconcile purchases automatically After a purchase settles, usually within 1-2 days of the original authorization, Stripe creates a transaction record with the final amount and business details. Agents can use this to automatically match charges to the tasks or orders that triggered them, flag discrepancies where the settled amount differs from what was authorized, and keep your books up to date without manual intervention. First, subscribe to `issuing_transaction.created` to receive a notification each time a charge fully settles: ```json { "type": "issuing_transaction.created", "data": { "object": { "amount": 7500, "merchant_data": { "name": "Logistics Co", "category_code": "4215" }, "card": { "metadata": { "customer_order_id": "order_8821", "agent_id": "agent_fulfillment_01" } } } } } ``` Use the metadata on the transaction to match it back to the originating order or task in your system. If the settled amount differs from what was originally authorized, flag it for review: ```curl curl https://api.stripe.com/v1/issuing/transactions \ -u "{{SECRET_KEY}}:" \ -d "cardholder"="ich_123" \ -d "created[gte]"=1672531200 ``` ### Catch and dispute overcharges When a card is used, Stripe first creates an authorization for the expected amount. When the charge fully settles, Stripe creates a transaction, and the two amounts don’t always match. A restaurant might add a tip, a supplier might ship a partial order but charge in full, or a business might process the wrong amount. Agents can automatically compare what was authorized against what was charged, and file a dispute on your behalf if there is a mismatch. When a transaction settles, retrieve the original authorization to compare amounts: ```curl curl https://api.stripe.com/v1/issuing/authorizations/iauth_123 \ -u "{{SECRET_KEY}}:" ``` Your agent compares the authorized amount against the settled transaction amount. If the difference exceeds a threshold you define, it flags the transaction and initiates a dispute: ```json { "authorization_amount": 7500, "transaction_amount": 9200, "delta": 1700, "card": { "metadata": { "customer_order_id": "order_8821", "agent_id": "agent_fulfillment_01" } } } ``` You can also file a dispute directly against the transaction: ```curl curl https://api.stripe.com/v1/issuing/disputes \ -u "{{SECRET_KEY}}:" \ -d "transaction"="ipi_123" \ -d "evidence[reason]"="canceled" \ -d "evidence[incorrect_amount][dispute_amount]"=7500 \ -d "evidence[incorrect_amount][original_transaction]"="ipi_123" ``` Next, subscribe to `issuing_dispute.updated` to track the status of open disputes and notify the cardholder when a dispute is resolved and funds are recovered: ```json { "type": "issuing_dispute.updated", "data": { "object": { "status": "won", "amount": 1700, "transaction": "ipi_123" } } } ``` ## See also - [Issuing for your business](https://docs.stripe.com/issuing/for-your-business.md) - [Issuing for your platform](https://docs.stripe.com/issuing.md) - [Agentic spending for personal expenses](http://link.com/agents)