Authorize agent spend before the provider call.
Reserve against the customer's budget, run the work, then settle what it actually cost and release the rest. A denied run makes zero provider calls and still leaves a receipt that says why.
free during early access · no card at signup
Settles to your own Stripe. The money never touches Unprice.
AGPL-3.0 open source · EU-hosted · two calls to integrate · nothing to deploy
does the balance cover this $4.10 request?
allow · within budget
allowed: true
cost $4.10 · covered by balance
deny · over budget
LIMIT_EXCEEDED
needs $4.10 · balance $1.80
The provider was already paid before anything checked.
Your Redis counter is not a budget. It records the spend after the provider call already made it. When a customer disputes the invoice, engineering reconstructs the charge from logs.
"Why were we charged $1,204? We set a $500 budget."
The authorization becomes the receipt.
An allow reserves against the customer's budget before the agent runs. After the work completes, Unprice settles actual usage, captures the ledger movement, and writes the invoice line. A deny makes zero provider calls: no work, no ledger entry, no invoice line, no charge.
the agent run asks before it spends
does the balance cover this $4.10 request?
allow · within budget
accepted: true
cost $4.10 · covered by balance
2,050 tokens × $0.002 · pro@v3
reserve → capture · balanced
the money never touches Unprice
deny · over budget
LIMIT_EXCEEDED
needs $4.10 · balance $1.80
zero provider calls · no cost to explain
reason → your app · limit exceeded
Every step is in the public SDK. Reserve for variable-cost agent work, or authorize known usage in one call. Use TypeScript, REST, or curl.
Read the proof.
Read the concurrency test, run the benchmark against your deployment, and inspect the authorization source. If a deny leaks a provider call or the ledger does not balance, the source and tests will show it.
A recorded walkthrough is coming. Until it does, the receipts below are the ones you can check yourself. You do not need an account or a demo call.
Reserve the customer's budget before the model spends yours.
Reserve a ceiling against the customer's budget before generateText runs. If the reservation is denied, the provider is never called. After the run, settle actual token usage and release the rest.
1import { generateText } from "ai"2import { Unprice } from "@unprice/api"34const unprice = new Unprice({ token: process.env.UNPRICE_TOKEN })56// 1. Reserve the most this model call may cost.7const { result: reservation, error } = await unprice.reservations.reserve({8 customerId,9 maximumAmountMinor: 10, // $0.10 ceiling, held against the customer's budget10 idempotencyKey: messageId,11})1213// Hard deny. Return here and the provider is never called.14if (error) {15 return new Response("Customer budget unavailable", { status: 402 })16}17if (!reservation.allowed) {18 return new Response("Customer budget unavailable", { status: 402 })19}2021// 2. Spend only after the reservation succeeds.22const generation = await generateText({23 model,24 prompt,25 maxOutputTokens: 2_000,26})2728// 3. Capture actual usage and release the unused amount.29const settlement = await reservation.settle({30 featureSlug: "ai-output-tokens",31 eventSlug: "completions",32 id: messageId,33 properties: {34 inputTokens: generation.usage.inputTokens,35 outputTokens: generation.usage.outputTokens,36 },37})3839if (settlement.error) throw settlement.error4041return Response.json({ text: generation.text })
Use the smallest operation that matches the work. A reservation fits variable-cost agent calls. These two paths cover simpler cases.
- 01
Reserve
Authorize the maximum cost against the customer's budget before the provider call.
customerfunds the workheld$0.10 maximumdeniedno provider call - 02
Run
Start the agent only after Unprice confirms the reservation.
provideryour model accountlimit2,000 output tokensexecutoryour application - 03
Settle
Report actual token usage. Unprice captures what the run cost, releases the rest, and closes the reservation.
capturedactual usagereleasedunused holdevidenceusage → invoice
Asked before you integrate.
Unprice is for products where one customer request can start an agent run or paid workflow that spends real money before anyone checks. If your product only charges per seat, Stripe Billing is enough. If you want one aggregate cap on your model-provider bill rather than a budget per customer, use an AI gateway.
Stripe today · not tax, accounting, or revenue recognition
- Why not just Stripe?
- Stripe captures payment after the work is done, so it cannot stop the work. Keep it. Unprice runs earlier: it authorizes the spend before the provider call, then hands Stripe an invoice line that can be explained. The full argument
- Why not an AI gateway?
- A gateway sits inside the provider call and caps your total provider bill. Unprice sits before it and authorizes one run against one customer's budget. A denied run never reaches the gateway. Some products want both.
- Why not Redis?
- You can build the reservation in Redis. A Lua script that holds an amount and releases the remainder is about fifty lines, and it will be correct. The reservation was never the hard part. The trail is: which plan version was in force, what rate applied, which grant the hold came from, how the settled amount became a ledger entry that balances, and which invoice line it landed on. That is what gets rebuilt by hand every time support asks why a customer was charged. Unprice keeps it on one path, with the reservation attached. Read the source
- Where does this run?
- On the hosted cloud: install the SDK, call the API, nothing to deploy. It runs in EU regions, and per-customer state — wallet reservations, run budgets, idempotency keys — is pinned to Cloudflare's EU jurisdiction, so it is never placed outside it. To run Unprice yourself, deploy the open-source runtime to your own Cloudflare account, and your data lives wherever you put it. Either way, payments settle in your own Stripe account.
- Does Unprice hold the money?
- No. Your app asks before paid work runs and gets an allow or deny with evidence. Stripe captures payment in your own account or through Stripe Connect, and the built-in Sandbox provider lets you test the path without a processor. Unprice records the decision, the ledger movement, and the receipt. The money never touches Unprice.
- What does a deny look like to my user?
- Whatever you decide to show. A deny is a business result, not an outage: the call returns 200 with allowed set to false and a machine-readable reason such as LIMIT_EXCEEDED. Your app can explain the limit and offer an upgrade.
- How much latency does the check add?
- One request, ahead of a provider call that costs orders of magnitude more. A warm check is a cached read plus one Durable Object read. Invoicing, analytics, and ledger work run off the request path. Latency depends on where your traffic runs, so the repo ships a k6 harness — point it at your deployment and read the percentiles. Run the benchmark
- What if Unprice is down?
- The check returns an explicit error and your code picks the fallback: fail open and log it, or fail closed for expensive actions. Caches can serve stale answers while they revalidate, and shadow mode blocks nothing during adoption.
Put one agent action on a budget in one afternoon.
Bring the agent run or paid workflow that burns margin when a customer triggers it. That is the only prerequisite. Read the argument in the manifesto.
one plan version · one customer signup · one reserved agent run
Test the reservation with Unprice's built-in Sandbox before it touches production. If the result does not match your model, remove it. No provider traffic, payment processor, or contract changed.
I am taking ten design partners and I onboard each one myself. Email me your action and I'll reply with the first step, even if no slot is left.
Seb, founder of Unprice · [email protected]