Rightshold™ Sign up

Answers · agent payments

How do I restrict an AI agent to an allowlist of merchant domains and categories?

Last updated

TL;DR: A spend cap limits how much an agent can spend. An allowlist limits where it can spend. Put both on the agent's credential with set_spend_policy: allowed_domains (exact domains, or *.example.com to include subdomains) and allowed_categories (short labels such as data_api or cloud_compute). Every proposed purchase then goes through authorize_spend. A merchant that isn't on the list gets a signed deny with merchant_not_allowed. A category that isn't on the list, or a purchase sent with no category, gets category_not_allowed. The per-purchase and daily caps still apply on top, so an allowlisted merchant can still be denied with over_per_transaction_cap or over_daily_cap. An empty list means no restriction, so set both lists on purpose. This page is about the merchant allowlist itself. Card MCC controls, cap-only policies and mid-task revoke are covered on separate pages. Merchants check the allow receipt free with verify_spend_authorization, and ledger_verify keeps every policy version and decision checkable.

What should I check, step by step?

1. List the merchants the agent really needs (API vendors, cloud providers, one marketplace) and the kinds of purchase it makes. Start narrow. It is easier to add a domain after a deny than to explain a purchase you never meant to allow.

  1. Write allowed_domains as exact hostnames (api.example.com) or wildcards (*.example.com, which also matches example.com). Rightshold lowercases entries, strips a leading www. and the scheme, and accepts up to 100 domains.
  2. Write allowed_categories as your own short labels (data_api, cloud_compute, saas_seat), up to 100. The agent must send the same label as category on every authorize_spend call. If categories are set and the category is missing or not on the list, the answer is category_not_allowed.
  3. Remember that an empty allowed_domains or allowed_categories list means no restriction for that field. Setting both lists is what turns the allowlist on.
  4. Keep caps on top: currency, per_tx_max_minor and daily_max_minor are still checked for allowlisted merchants. set_spend_policy needs at least one cap, so an allowlist can't be used as an unlimited pass.
  5. Make authorize_spend the step before every payment and pass the real merchant_domain. A signed deny lists every failing reason at once (for example merchant_not_allowed and over_daily_cap), so the agent and the owner can see exactly what to fix.
  6. Have merchants (or your own payment step) check the allow receipt with verify_spend_authorization and accept it only before valid_until (15 minutes). On card rails, mirror the same list with Stripe Issuing allowed_categories (merchant category codes) so both layers agree.
  7. Change the list only by recording a new policy version. Add a domain through a human approval if it widens spend, and test it: a listed domain allows, an unlisted one returns merchant_not_allowed, and a wrong category returns category_not_allowed.

What is the difference between a merchant allowlist and a spend cap for an AI agent?

A per-purchase or daily cap still lets the agent pay any merchant until the money runs out. A prompt-injected or confused agent can stay under the cap and still send money to a site you never chose. An allowlist turns this around: every merchant and category is denied unless you named it.

How do allowed_domains and allowed_categories restrict where an AI agent can spend?

set_spend_policy stores currency, per_tx_max_minor, daily_max_minor, allowed_domains, allowed_categories and an optional expires_at on the agent's credential. A new call records a new version that replaces the old one from the moment it is recorded, and old versions stay on the ledger.

Do spend caps and card MCC controls still apply when an AI agent uses a merchant allowlist?

Caps still apply to allowlisted merchants. With a 10.00 per-purchase cap, a 25.00 order to an allowed domain returns over_per_transaction_cap, and the daily total still counts toward over_daily_cap.

How do I ask Rightshold about this (free, no key)?

Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code, then ask: “Restrict my purchasing agent to api.example.com and any subdomain of cloud.example.net, only for data_api and cloud_compute purchases, with a 10.00 USD per-purchase cap and 50.00 USD per day. Then tell me what authorize_spend returns for a merchant that isn't on the list.”

One-click setup

{
  "tool": "set_spend_policy",
  "arguments": {
    "credential_id": "crd_YOUR_AGENT_CREDENTIAL",
    "currency": "USD",
    "per_tx_max_minor": 1000,
    "daily_max_minor": 5000,
    "allowed_domains": [
      "api.example.com",
      "*.cloud.example.net"
    ],
    "allowed_categories": [
      "data_api",
      "cloud_compute"
    ]
  }
}

Rightshold records spending policies and signs allow/deny decisions on a hash-chained ledger. It never holds, moves or settles money. Making the agent call authorize_spend before paying, and making merchants or card controls refuse what was denied, are steps you run around those records. Category labels are yours to define and are not card-network MCCs. Not financial or legal advice.

What are the sources?

Related

Not legal advice. JSON · Markdown · All answers

Get a free API key in one call

No card and no email needed. 100 free credits; the license and policy checks stay free without a key.

curl -s -X POST https://www.rightshold.com/v1/accounts/signup -H "Content-Type: application/json" -d '{"accept_terms":true}'
export RIGHTSHOLD_API_KEY=rs_...   # the api_key from the reply (shown once)
curl -s https://www.rightshold.com/v1/licenses/check -H "Authorization: Bearer $RIGHTSHOLD_API_KEY" \
  -H "Content-Type: application/json" -d '{"license":"MIT","intended_use":{"commercial_use":true}}'