Allowances
On-chain spending authorizations with a hard cap, for metered and one-time billing.
An Allowance authorizes a service (the grantee) to spend from an agent’s wallet (the granter), up to a hard total cap. Where a subscription runs on a fixed cycle, an allowance has none: the grantee draws whenever usage warrants, and the cap is the only limit.
Allowance structure
interface Allowance {
id: string; // On-chain allowance id
granter: Address; // Agent wallet authorizing the spend
grantee: Address; // Service or facilitator permitted to spend
token: Address; // Token contract address (e.g. USDG)
maxAmount: number; // Total spend cap, in token base units
spent: number; // Accumulated spend so far
expiresAt?: number; // Optional Unix timestamp
}
Allowances versus subscriptions
A subscription collects a fixed amount on a fixed schedule. An allowance trades that regularity for flexibility: the agent sets the total cap once, and the grantee draws against it in any number of deductions, at any pace, until the cap is exhausted or the allowance expires.
That shape suits three patterns:
- Metered billing. Services priced per API call, per token, or per unit of compute. The agent caps its total exposure; the service draws down as usage accumulates.
- One-time purchases. An agent authorizes a maximum for a single operation, with no subscription lifecycle involved.
- Overage billing. When a plan charges metered overage above its included quota, the overage settles through an allowance that runs alongside the subscription.
Creating an allowance
const allowance = await agent.createAllowance({
grantee: "0x4298e8aa4048cf8d437f9a90266a7e8c436a7bba", // provider wallet
token: "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168", // USDG
maxAmount: 10_000_000, // 10 USDG total cap
expiresAt: Date.now() / 1000 + 86400, // expires in 24 hours
});
console.log(allowance.id); // on-chain allowance id
console.log(allowance.maxAmount); // 10_000_000
console.log(allowance.spent); // 0
Drawing against an allowance
Providers deduct from an allowance with deductAllowance:
const result = await scribefinance.deductAllowance({
allowanceId: allowance.id,
amount: 500_000, // 0.50 USDG for this request
});
console.log(result.remaining); // remaining balance
Any deduction that would exceed maxAmount fails with an AllowanceExhausted error. The cap is enforced by the on-chain contract itself: Scribe Finance has no mechanism for letting a service spend past it.
Checking an allowance
const status = await agent.getAllowance({ allowanceId: allowance.id });
console.log(status.spent); // amount spent so far
console.log(status.remaining); // maxAmount - spent
console.log(status.expired); // boolean
Expiry
After the expiresAt timestamp, deductions stop. The unspent balance requires no reclaiming: it never left the agent’s wallet in the first place. An allowance is an authorization to spend, not an escrow; tokens move only at the moment of each draw.
Revoking an allowance
An agent can revoke an allowance at any point before expiry:
await agent.revokeAllowance({ allowanceId: allowance.id });
Revocation is written to the chain and is effective immediately. Deductions already signed and in flight still settle; everything after the revocation is refused.
Pairing allowances with subscriptions
For a plan with metered overage, agent.subscribe() creates the subscription record and a companion allowance record in a single transaction. The base fee flows through the subscription; usage above quota flows through the allowance. Both surface in the Dashboard and in webhook events.
The agent sets its overage ceiling at subscribe time with maxOveragePerCycle:
const sub = await agent.subscribe({
planId: plan.id,
maxOveragePerCycle: 20_000_000, // authorize up to 20 USDG in overage per month
});