Authorize agent spend before the provider call.
Unprice checks your customer's budget before each agent run. If the budget can't cover it, the run never starts.
free during early access · no card at signup
Payments go to your own Stripe account. Unprice never holds the money.
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
Your provider gets paid before anything checks the budget.
Your Redis counter is not a budget. It counts spend only after it happens.
"Why were we charged $1,204? We set a $500 budget."
One check, from request to invoice.
If the check allows a request, Unprice holds the cost, the agent runs, and the actual usage goes on the invoice. If it denies the request, nothing runs and nothing is charged.
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
Reserve when the cost varies, like an agent run. Use one call when you know the cost up front.
Read the proof.
Don't take our diagram on trust. Read the tests, run the benchmark, and read the source.
There's no walkthrough video yet. You can check everything below without an account.
Reserve the customer's budget before the model spends yours.
Reserve before generateText runs, then settle the actual usage. If Unprice denies the reservation, your code never calls the provider.
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 })
Two calls cover simpler cases.
- 01
Reserve
Hold the maximum cost before the provider call.
customerfunds the workheld$0.10 maximumdeniedno provider call - 02
Run
Start the agent once the hold succeeds.
provideryour model accountlimit2,000 output tokensexecutoryour application - 03
Settle
Report the actual usage. Unprice releases the rest.
capturedactual usagereleasedunused holdevidenceusage → invoice
Questions before you integrate.
Unprice is for products where one customer request can trigger paid AI work. If you only charge per seat, use Stripe Billing. If you want one cap on your whole provider bill, use an AI gateway.
payments through Stripe today · no tax, accounting, or revenue recognition
- Why not just Stripe?
- Keep Stripe. It charges after the work runs, so it can't stop the work. Unprice checks the spend before the work runs. The full argument
- Why not an AI gateway?
- A gateway caps your total provider bill. Unprice caps each customer's budget before the call reaches the gateway. Some products use both.
- Why not Redis?
- You can build the hold in Redis in about fifty lines. The hard part is the record behind each charge: the plan version, the rate, the ledger entry, and the invoice line. Unprice keeps that record for every charge. Read the source
- Where does this run?
- On the hosted cloud there is nothing to deploy, and billing state stays in Cloudflare's EU jurisdiction. Budget state is the exception and can live outside the EU. You can also run Unprice in your own Cloudflare account.
- Does Unprice hold the money?
- No. Payments go through your own Stripe account. Unprice records the decision, the ledger entry, and the invoice line.
- What does a deny look like to my user?
- Whatever you choose. A deny returns 200 with allowed set to false and a reason such as LIMIT_EXCEEDED, so your app can offer an upgrade.
- How much latency does the check add?
- One request, before a provider call that costs far more. Ledger and invoice work run afterward. Run the k6 benchmark against your deployment to see real numbers. Run the benchmark
- What if Unprice is down?
- Your code decides. Fail open and log it, or fail closed for expensive actions.
Put one agent action on a budget in one afternoon.
Bring one agent run that costs you money. The reasoning is in the manifesto.
one plan version · one customer signup · one reserved agent run
Try it in Unprice's built-in Sandbox first. If it doesn't fit, remove it. Nothing else changes.
I'm onboarding ten design partners myself. Email me the action you want to budget, and I'll reply with the first step.
Seb, founder of Unprice · [email protected]