{
  "question": "How do I test my AI agent's spending limits before I give it real money?",
  "slug": "how-to-test-an-ai-agents-spending-limits-before-giving-it-real-money",
  "url": "https://www.rightshold.com/answers/how-to-test-an-ai-agents-spending-limits-before-giving-it-real-money",
  "short_answer": "Test every limit from the outside, the way a misbehaving agent would hit it, using fake money on each rail. For cards, Stripe Issuing has a sandbox: issue a virtual card with spending_controls, fund the test Issuing balance, and use the test helpers to create authorizations, increment them and create force captures, so you see what gets declined and what slips through. For x402, point the agent at Base Sepolia (eip155:84532) and fund its wallet with test USDC from Circle's faucet or the CDP faucet. For the policy layer, open a Rightshold sandbox account (sign up with sandbox: true for rs_test_ keys) and run set_spend_policy and authorize_spend against your agent's real purchase shapes. Write the cases down as a test matrix: under the cap, exactly at it, one cent over, a run of small purchases that crosses the daily cap, a merchant or category outside the allowlist, a different currency, a retried purchase, purchases right after a pause or revoke, and purchases across the reset time. Every case needs an expected allow or deny, and one case that should allow, so you know the test can fail.",
  "checklist": [
    "List every way the agent can spend: card numbers, x402 or other wallet payments, paid API keys, and tools that buy on its behalf. Each rail gets its own test, because each enforces limits in a different place.",
    "Cards: in a Stripe sandbox, issue a virtual card with the same spending_controls you plan for production (for example a per_authorization limit, a daily limit and allowed_categories). Fund the test Issuing balance first; test funds aren't real and only work for simulated purchases.",
    "Create test authorizations with POST /v1/test_helpers/issuing/authorizations, setting amount and merchant_data.category to match each case. Check which are approved and which are declined, and read the decline reason on the authorization.",
    "Test what limits can't stop: increment an approved authorization (POST /v1/test_helpers/issuing/authorizations/{id}/increment) and create a force capture (POST /v1/test_helpers/issuing/transactions/create_force_capture). Stripe's spending-controls docs warn that tips and fees posted later can push spend past a limit, so reconcile captured transactions, not just authorizations.",
    "x402: run the agent with a testnet client (the CDP x402 client's development environment uses Base Sepolia) and fund the wallet with test USDC from faucet.circle.com or the CDP faucet. Have a test server quote prices under, at and over your per-request cap, and an upto price whose ceiling is over the cap.",
    "Policy layer: sign up for a Rightshold sandbox account (POST /v1/accounts/signup with sandbox: true gives rs_test_ keys), issue a test agent credential, set_spend_policy with your real caps, then call authorize_spend for each case and assert the decision and reasons.",
    "Include the edge cases: an amount exactly at the cap (should allow), one minor unit over (should deny), several small purchases that cross daily_max_minor, a subdomain or look-alike merchant, a missing category, and a different currency. Each needs an expected answer written down before you run it.",
    "Test retries and resets: retry a purchase and check you don't approve or pay it twice; pause or revoke mid-run and check the next purchase is refused; run cases just before and after the daily reset (Rightshold's daily total resets at 00:00 UTC; Stripe's date-based intervals also start at midnight UTC).",
    "Keep one case that must allow and one that must deny in CI, so a test that always passes or always fails gets noticed.",
    "Move to live money in steps: small caps first, alerts on, and the same matrix re-run with live keys at amounts you can afford to lose."
  ],
  "sections": [
    {
      "heading": "Why test with fake money first",
      "points": [
        "Spend limits fail quietly. A cap set in the wrong currency unit (dollars instead of cents), an allowlist that is empty and so allows everything, or a retry that pays twice all look fine until real money moves. The only way to know a limit works is to aim purchases at it and watch it refuse them.",
        "Each rail has its own sandbox. Stripe Issuing's sandbox lets you issue cards and simulate purchases that only work inside your Stripe account. Base Sepolia is a testnet with free test USDC. A Rightshold sandbox account issues rs_test_ keys behind a hard boundary from live work, and none of its work counts toward the public record."
      ]
    },
    {
      "heading": "The test matrix",
      "points": [
        "Write the matrix as data: purchase amount in minor units, currency, merchant domain or merchant category, time, and the expected decision and reason. Run the same rows against every rail the agent can use.",
        "Rows that catch the common bugs: at the cap and one unit over, a run of small purchases that crosses the daily cap, merchant and category outside the allowlist, a currency the policy doesn't cover, a retry of the same purchase, the first purchase after a pause or revoke, and purchases on either side of the reset time.",
        "In Rightshold's spend policy only allowed purchases count toward the daily total, and each authorize_spend call is its own decision. Authorize once per purchase and reuse that receipt when a payment retries; calling authorize_spend again for the same purchase counts the amount again. Make that a test row too."
      ]
    },
    {
      "heading": "What card limits don't catch",
      "points": [
        "Stripe says spending controls run before real-time authorizations and can decline a purchase before your webhook sees it, and that later tips and fees can push spending past a limit. Test helpers let you simulate both: increment an approved authorization, and create a force capture that never had an authorization.",
        "So compare captured transactions with the caps, not just the approve or decline decision, and alert on any captured amount larger than what was authorized."
      ]
    }
  ],
  "checks": [],
  "ask_rightshold": {
    "start": "https://www.rightshold.com/start?ref=seo",
    "mcp_endpoint": "https://www.rightshold.com/mcp",
    "ask": "In my Rightshold sandbox account, check this test purchase against my agent's spending policy: $25.01 at api.example.com in the data category, where the per-transaction cap is $25. I expect a deny with over_per_transaction_cap.",
    "mcp_call": {
      "tool": "authorize_spend",
      "arguments": {
        "credential_id": "crd_YOUR_TEST_AGENT_CREDENTIAL",
        "amount_minor": 2501,
        "currency": "USD",
        "merchant_domain": "api.example.com",
        "category": "data",
        "reference": "test-matrix-row-3"
      }
    },
    "also": [
      "Use a sandbox account: POST /v1/accounts/signup with sandbox: true gives rs_test_ keys, and sandbox work never counts toward the public record. Sandbox and live keys can't be mixed.",
      "set_spend_policy (owner key) sets the caps you are testing: per_tx_max_minor and daily_max_minor in cents, allowed_domains, allowed_categories and an optional expires_at. Remember that empty allowlists mean no restriction.",
      "Each authorize_spend answer is a signed allow or deny with reasons (over_per_transaction_cap, over_daily_cap, merchant_not_allowed, category_not_allowed, currency_not_allowed, policy_expired, credential_revoked). verify_spend_authorization checks a receipt for free."
    ],
    "scope": "Rightshold records spending policies and signed allow or deny decisions. It never holds or moves money and doesn't run your Stripe sandbox, wallet or test suite. Card networks, Stripe and x402 facilitators enforce their own rules, so a passing Rightshold test doesn't prove those rails will decline the same purchase. Test each rail. Not financial advice."
  },
  "sources": [
    {
      "title": "Stripe: Test your Issuing integration (sandbox, test funds, authorization test helpers)",
      "url": "https://docs.stripe.com/issuing/testing"
    },
    {
      "title": "Stripe: Issuing spending controls (spending limits, intervals, tips and fees can exceed a limit)",
      "url": "https://docs.stripe.com/issuing/controls/spending-controls"
    },
    {
      "title": "Stripe API: Increment a test-mode authorization",
      "url": "https://docs.stripe.com/api/issuing/authorizations/test_mode_increment"
    },
    {
      "title": "Stripe API: Create a test-mode force capture",
      "url": "https://docs.stripe.com/api/issuing/transactions/test_mode_create_force_capture"
    },
    {
      "title": "Coinbase CDP: x402 quickstart for buyers (Base testnet, test USDC)",
      "url": "https://docs.cdp.coinbase.com/x402/quickstart-for-buyers"
    },
    {
      "title": "Coinbase CDP: x402 network support (Base Sepolia eip155:84532)",
      "url": "https://docs.cdp.coinbase.com/x402/network-support"
    },
    {
      "title": "Circle: Testnet faucet (USDC on Base Sepolia)",
      "url": "https://faucet.circle.com/"
    }
  ],
  "related": [
    {
      "title": "Giving an AI agent a virtual card with a spending limit",
      "url": "https://www.rightshold.com/answers/how-to-give-an-ai-agent-a-virtual-card-with-a-spending-limit"
    },
    {
      "title": "Per-request and per-run spend caps for x402 agent payments",
      "url": "https://www.rightshold.com/answers/how-to-set-per-request-and-per-run-spend-caps-for-x402-agent-payments"
    },
    {
      "title": "Stopping an AI agent from paying twice when it retries",
      "url": "https://www.rightshold.com/answers/how-to-stop-an-ai-agent-from-paying-twice-when-it-retries"
    },
    {
      "title": "Enforcing AI agent payment caps at the execution boundary",
      "url": "https://www.rightshold.com/answers/how-to-enforce-ai-agent-payment-caps-at-the-execution-boundary-not-in-the-prompt"
    }
  ],
  "computed_from": "Curated guidance; license verdicts computed from Rightshold's license profiles at render time. Not legal advice.",
  "updated": "2026-11-09"
}