Sell AI credits and usage. Keep the margin.

Authorize every agent run and paid workflow before it creates cost. Reserve customer credits up front, then trace the decision through usage and the invoice.

free during early access · no card at signup

Settles to your own Stripe. The money never touches Unprice.

AGPL-3.0 open source · two calls to integrate · nothing to deploy

The reservationcustomer funds · before provider
Requestreservations.reserve
Price2,050 tokens × $0.002 = $4.10
Budget check$5.90

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

Reserve first. Settle actual usage after.follow the full path ↓
01The status quo

By invoice time, the agent already spent the credits.

Your Redis counter is not a budget. It records usage after the agent or workflow creates cost. When a customer disputes the invoice, engineering must reconstruct the charge from logs.

The DIY stackone paid action · traced
cron reset-usagelast success · 3d ago
POST /v1/run200 · work executed
INCR usage:acme-corp4,101 → 4,102
provider cost$0.48 · already spent
38 more log lines · unindexed
30 days later · invoice line$1,204.00
support · ticket #4812reply due · 24h

"Why were we charged $1,204? We set a $500 budget."

assignedengineering
plan versionunknown
budget checknever ran
ledgerno entry
evidencereconstructed by hand
02The money path

The authorization becomes invoice evidence.

An allow reserves customer credits before the agent runs. After the work completes, Unprice settles actual usage, captures the ledger movement, and writes the invoice line. A deny creates no work, ledger entry, invoice line, or charge.

The money path3 requests · one budget
Requestusage.consume

the paid action asks before it runs

Metertokens used · 2,050
Accessincluded in plan · yes
Pricing rule$0.002 / token · pro@v3
Budget check$10.00

does the balance cover this $4.10 request?

allow · within budget

accepted: true

cost $4.10 · covered by balance

Walletreserve −$4.10
Ledgercapture · balanced
Invoiceline explained
invoice line · explain$4.10

2,050 tokens × $0.002 · pro@v3

reserve → capture · balanced

Paymentyour own Stripe

the money never touches Unprice

deny · over budget

LIMIT_EXCEEDED

needs $4.10 · balance $1.80

Walletuntouched
Ledgerno entry
Invoiceno line
invoice line

no cost created · nothing to explain

reason → your app · limit exceeded

Paymentno charge

Every step is in the public SDK. Reserve variable-cost AI work, or consume known usage in one call. Use TypeScript, REST, or curl.

03The receipts

Read the proof.

Read the concurrency test, run the benchmark against your deployment, and inspect the money-path source. If 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.

AI chatbotreserve before generation · settle actual token usage on finishRead the integration
concurrency5 concurrent over-limit writes → 2 accepted, 3 rejectedRead the test
latencyk6 harness · run it against your own deploymentRun the benchmark
the money pathAGPL-3.0 · ledger, wallet, and decision in the openRead the source
04First integration

Reserve the customer's money before the model spends yours.

Reserve a maximum from the customer's credits before generateText runs. If the reservation fails, do not call the provider. After the run, settle actual token usage and release the rest.

reserve → generate → settle
1import { generateText } from "ai"
2import { Unprice } from "@unprice/api"
3
4const unprice = new Unprice({ token: process.env.UNPRICE_TOKEN })
5
6// 1. Reserve the most this model call may cost.
7const { result: reservation, error } = await unprice.reservations.reserve({
8 customerId,
9 maximumAmountMinor: 10, // $0.10 from customer credits
10 idempotencyKey: messageId,
11})
12
13// Stop here. The provider never runs without customer funding.
14if (error) {
15 return new Response("Customer budget unavailable", { status: 402 })
16}
17
18// 2. Spend only after the reservation succeeds.
19const generation = await generateText({
20 model,
21 prompt,
22 maxOutputTokens: 2_000,
23})
24
25// 3. Capture actual usage and release the unused amount.
26const settlement = await reservation.settle({
27 featureSlug: "ai-tokens",
28 eventSlug: "ai-completion",
29 id: messageId,
30 properties: {
31 input_tokens: generation.usage.inputTokens,
32 output_tokens: generation.usage.outputTokens,
33 },
34})
35
36if (settlement.error) throw settlement.error
37
38return Response.json({ text: generation.text })

Use the smallest operation that matches the work. A reservation fits variable-cost AI calls. These two paths cover simpler cases.

usage.consumeknown cost · authorize and consume in one atomic call
access.checkshadow only · read-only and reserves nothing
This is the same reservation pattern used by the working open-source AI chatbot.Read the chatbot integration
  1. 01

    Reserve

    Hold the maximum cost against the customer's credits before calling the model provider.

    customerfunds the work
    held$0.10 maximum
    deniedno provider call
  2. 02

    Run

    Start the agent only after Unprice confirms the reservation.

    provideryour model account
    limit2,000 output tokens
    executoryour application
  3. 03

    Settle

    Report actual token usage. Unprice captures the funded amount and closes the reservation.

    capturedactual usage
    releasedunused hold
    evidenceusage → invoice
05The questions

Asked before you integrate.

Unprice is for AI products whose customers buy credits, trigger agent runs, or start paid workflows. If your product only charges per seat, Stripe Billing is enough. If you need to cap your model-provider bill instead of customer spend, use an AI gateway.

Stripe today · hosted or your own Cloudflare account · not tax, accounting, or revenue recognition

Why not just Stripe?
Keep Stripe for payment capture. Unprice handles the customer money path before and around the invoice. It connects plan versions, entitlements, budgets, credits, ledger captures, and evidence. The full argument
Do I need Cloudflare?
Not to use the hosted cloud. Install the SDK and call the API. You have nothing to deploy. To run Unprice yourself, deploy the open-source runtime to your Cloudflare account. It uses Workers, Durable Objects, and Queues to keep per-customer state near the request path. In both cases, payments settle to your own Stripe account.
Why not an AI gateway?
They control a different bill. A gateway caps what you spend with providers such as OpenAI or Anthropic. Unprice caps what your customer can spend with you and connects that decision to plan versions, credits, and invoice evidence. Use a gateway for your provider bill. Use Unprice for your customer's budget. Some products need both.
Why not a Redis counter?
For a single limit it is genuinely fine. It stops being fine when the counter has to agree with money: under concurrency a race lets over-budget work through, and the counter can tell you usage was high but not which budget was checked, which credits were reserved, why a request was denied, or how accepted usage became an invoice line. Unprice keeps the check, the reservation, and the explanation on one path.
Does Unprice touch the money?
No. Your app asks Unprice before paid work runs and receives an allow or deny with evidence. Stripe captures production payments in your account or through Stripe Connect. The built-in Sandbox provider lets you test the path without a payment processor. Unprice records the decision, ledger movement, and evidence. It never sits in your funds flow.
What does my customer see when a request is denied?
Whatever your app decides to show. A denial is a business result, not an outage or HTTP error. The call returns 200 with allowed set to false and a machine-readable reason such as LIMIT_EXCEEDED, plan expired, or no entitlement. Your app can explain the limit and offer an upgrade. Unprice records the denial and its evidence.
What does the check add to my request latency?
One authorization request. A warm check uses a cached read and one Durable Object read. Invoicing, analytics, and ledger work run outside the request path. Latency depends on where your traffic runs, so the repo includes a k6 harness. Point it at your deployment and read the percentiles. Run the benchmark
What happens if Unprice is down?
The check returns an explicit error. Your code controls the fallback. You can fail open and log the error, or fail closed for expensive actions. Caches can serve stale answers while they revalidate. Shadow mode blocks nothing, so it does not stop work during adoption.
Is it safe enough for money logic?
Do not adopt it all at once. Read the source, run one request path in shadow, prove it on Sandbox, then enforce only when the evidence matches. Read the source
06The offer

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

Sandbox first

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]