STELLAR//ALLOWANCE

Give the agent an allowance. Keep the wallet.

A wallet holds the money and can spend all of it, and the key that spends it sits in the agent’s environment, where anything the agent reads can reach it. So the money sits in a Soroban contract instead, and the agent holds a key that can only ask.

The agent
0.00USDC
asked 10 times, holds nothing
The allowance
5.00USDC
8 paid · 1 off the list · 1 over the cap
The seller
0.08USDC
was paid 8 times

What this isan address, a contract, three rules

I want to give my machine an agent account, an allowance, and permission to just take care of stuff.

DHH

This is a concrete version of it. Three rules, enforced by the chain rather than by the agent’s own good behavior, so nothing routes around them: not the agent, not its dependencies, not me.

None of it is a new payment protocol. x402 defines the handshake and a public facilitator settles it, which is what makes a one-cent API call payable at all: card fees cost more than the call. The only change is which address pays.

The cap below is testnet-small on purpose. A cap is a number, and the same contract holds 500 USDC a day as readily as it holds 0.025.

One run2026-09-09 20:57 UTC

owner
Fund an ownerfriendbot
10,000.00 XLMfunded
owner
Add the USDC trustline
added
owner
Swap 100 XLM for USDCtestnet DEX, strict send
170.8823 USDCswapped
owner
Deploy the allowanceallowlist: the seller · cap 0.025 USDC per 24h · the agent's key GBJX…7ANP holds 0.000 · CAYUAQDEAV
5.000 USDC indeployed
agent
Pay the sellersettled by OpenZeppelin · the payer is the contract · 6ad5edea18
0.010 USDCsettled
agent
Prompt-injected to pay a strangernot on the allowlist. Refused at simulation; nothing left the contract.
0.010 USDCrefused · allowlist
agent
Pay the seller again0.020 now in the window · 5fccf7ecec
0.010 USDCsettled
agent
Pay the seller a third time0.030 would exceed the 0.025 cap. Refused; nothing left the contract.
0.010 USDCrefused · window
testnet · about a minute · no wallet

Then, in the agenttwo values, four lines

npm i @stellar-allowance/sdk
import { Allowance } from '@stellar-allowance/sdk';

const { fetch } = new Allowance();
const response = await fetch('https://api.example.com/paid');

The two values are the allowance’s address and the agent’s key, and creating one hands you both. There is no account to open and no service to point at: the library reads the pair out of the environment and pays through the contract.

Open the dashboardFreighter on testnet · you set the rules