Authorize customer spend before paid work runs.

Sell credits and usage-based plans without eating over-budget customer work. Unprice is the open-source customer money path for usage-based SaaS.

License
AGPL-3.0 open source
Access
Free during early access
Payments
Your Stripe account
Custody
Funds stay with you
The money path
RequestPOST /v1/consume

the paid action asks before it runs

Plan versionpro@v3
Pricing rule$0.002 / token
Metertokens_used
Entitlementaccess.check · ok

Budget check

is this spend commercially allowed?

$4.10

remaining

allow · within budget

200

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

pro@v3 · $0.002/token

reserve → capture · balanced

deny · over budget

429

Walletuntouched
Ledgerno entry
Invoiceno line
invoice line

no cost created · nothing to explain

Every step in this path is a method in the public SDK. Run the check in shadow beside the logic you already run — TypeScript, REST, or curl.

01The status quo

By invoice time, the paid work already ran.

A customer triggers the expensive action. Your counter notices later; your invoice explains it weeks later. Blocked-too-late cost is margin you already spent — and when the customer disputes it, engineering turns into invoice support.

A Redis counter is not a budget: it cannot prove which plan version applied, which credits were reserved, or why a request was denied.

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
entitlement checknever ran
budget checknever ran
credits reservednone
ledger entryno entry
evidencereconstructed by hand
02The decision, live

Watch paid work stop before it creates cost.

Click a paid action against the plan. Each request is allowed, flagged, or denied before the work runs — and the same decision explains the invoice line later.

Pro planacme-corp · pro@v3
base fee$19.00 / mo
metered spend$0.00
Accepted spend
0 paid actions accepted
$19.00
Receipt view
no request yet

awaiting the first request

call
plan version
pricing rule
guardrail
remaining
work
accepted charge
ledger
invoice line
decision = pending
reason = no_request_sent
next = click a paid action on the plan
The demo curates the response — every fact on the receipt is a field the API returns.Read the docs
03First integration

The first integration is two calls.

Define one plan version, then sign up one customer against it — customers.signUp runs once, at your own signup, and returns the customerId you store. After that, access.check guards the paid action on every request, next to the code you already trust. Nothing has to block production traffic on day one.

signUp → check
1import { Unprice } from "@unprice/api"
2
3const unprice = new Unprice({
4 token: process.env.UNPRICE_TOKEN,
5 baseUrl: "https://api.unprice.dev",
6})
7
8// Once, at your own signup: subscribe the customer to a
9// plan. Unprice provisions the subscription and its
10// entitlements, then returns the id you store.
11const { result: signup } = await unprice.customers.signUp({
12 name: "Acme Inc.",
13 email: "[email protected]",
14 planSlug: "pro",
15 externalId: "user_123", // your id for this customer
16 successUrl: "https://your-app.com/welcome",
17 cancelUrl: "https://your-app.com/pricing",
18})
19
20// Every request after that: check before the paid
21// action runs.
22const { result, error } = await unprice.access.check({
23 customerId: signup.customerId,
24 featureSlug: "tokens",
25})
26
27if (error) {
28 console.error(error.message)
29 return
30}
31
32if (!result.allowed) {
33 // Denied in the request path — no cost was ever created.
34 throw new Error("Denied before paid usage ran")
35}
36
37// Allowed: run the paid action. The same decision
38// explains the invoice line later.
Both calls shown; the plan version comes from the dashboard. The rest of the money path — usage.consume, budgeted runs, invoice evidence — lives in the docs.Explore the request-path SDK
04Adoption path

Try it without touching your current logic.

Nothing blocks traffic until the evidence convinces you. When the shadow decision matches reality, switch access.check to usage.consume and enforcement is one line, not a migration.

  1. 01

    Shadow

    Run the decision beside the logic you already trust. Compare answers in without changing behavior.

    runsaccess.check
    mutatesnothing · read-only
    blocksnothing
  2. 02

    Sandbox

    Prove the path before a dollar moves. Model customers, plan versions, budgets, credits, etc.

    processornone · built-in Sandbox
    customerssimulated
    evidencereal · inspectable
  3. 03

    Your own Stripe

    Go live in your own account. Unprice owns the money path; your provider still captures the payment.

    funds flowyours · always
    captureyour Stripe account
    unpricenever in the middle

Why not just Stripe?

Keep Stripe for payment capture. Unprice owns the customer money path before and around the invoice: plan versions, entitlements, budgets, credits, ledger captures, and evidence.

Does Unprice touch the money?

No. Your app asks Unprice before paid work runs and gets an allow or deny with evidence attached. Your payment provider captures the payment — Stripe today, in your own account. Unprice owns the decision, the ledger, and the evidence; it never sits in your funds flow.

Why not an AI gateway?

Gateways cap provider spend. Unprice governs what your customer is allowed to spend and connects that decision to invoice evidence.

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.

Do I need Cloudflare?

Today, yes. The runtime deploys to your own Cloudflare account — Workers, Durable Objects, Queues — because the spend decision needs fast per-customer state where requests run. Your account, your data, your keys.

05The offer

The pricing is as explainable as yours will be.

The core is AGPL-3.0 and free to run in your own Cloudflare account. The hosted cloud is free during early access, with no card at signup. Payments settle to your own Stripe account either way — Unprice never sits in your funds flow.

The money path is yours to read, fork, and run — it cannot be acquired out from under you. The full argument is in the manifesto.

one plan version · one customer signup · one shadow check

one afternoon · free during early access · no card

The walk-away guarantee

Adopt in shadow: sign up one test customer, then run one read-only access.check beside the logic you already trust, blocking nothing. If the decisions never match your reality, delete that line and walk away — nothing in your stack changed, no card on file, no contract to exit. The only trace left is the one test customer inside Unprice. Enforce only when the evidence convinces you.

Not sure where to start?

Tell me the action that burns margin when a customer runs it — an LLM call, a workflow, an API job — and what stops it today, if anything. I'll reply personally with a concrete first step: where to put the check, what to run in shadow beside what you already have, and whether to block each request or cap the whole job.

— Seb, founder of Unprice

Email what runs[email protected] · replies personally