You built an app with Cursor, Lovable, Bolt, or Claude Code. It calls an AI model behind the scenes. People like it. Now you have to put a number on the pricing page, and you have no idea what that number should be.
It is tempting to guess, or to copy a competitor. With an AI SaaS that can get expensive, because every click on "Generate" costs you real money. On a flat "unlimited" plan, your most active users can cost more than they pay.
This guide walks you through it in 7 steps. You will end up with one clear plan, a price you can defend, and limits that protect you.
Two quick definitions before we start:
- Unit cost: what one action in your app costs you (for example, one AI generation).
- Margin: what is left from the price after your costs. If a user pays $19 and costs you $5, your margin is $14.
Step 1: Log the cost of every AI call, per user
You cannot price what you cannot see. Record how many tokens each request uses and who made it. (Tokens are the small chunks of text that AI providers bill you for.)
The providers already tell you in every response:
- OpenAI's Responses API returns
usage.input_tokensandusage.output_tokens. The older Chat Completions API calls themusage.prompt_tokensandusage.completion_tokens(OpenAI Help Center). - Anthropic's Messages API returns
usage.input_tokensandusage.output_tokens(Claude docs).
You just need to save those numbers. Paste this prompt into Cursor, Claude Code, or Lovable:
Add AI usage tracking to this app.
1. Create a table ai_usage with: id, user_id, feature (text), model (text),
input_tokens (int), output_tokens (int), created_at (timestamp, default now).
2. Find every place the app calls the OpenAI or Anthropic API (server-side only).
3. After each successful call, insert one row using the usage fields from the
API response. Do not estimate tokens; read them from the response.
4. Never call the AI API from the browser. If you find a client-side call,
move it to a server route or edge function first and tell me.
Show me the list of files you changed.
Once you have a week of data, this query shows your heaviest users:
select user_id,
count(*) as ai_calls,
sum(input_tokens) as input_tokens,
sum(output_tokens) as output_tokens
from ai_usage
where created_at > now() - interval '30 days'
group by user_id
order by output_tokens desc
limit 20;
No users yet? Use your own test sessions. Rough numbers beat none.
Step 2: Do the cost math for one action
Now turn tokens into dollars. Open your provider's pricing page (OpenAI, Anthropic). Prices are listed per 1 million tokens, and output tokens usually cost more than input tokens.
Here is a worked example. At the time of writing, OpenAI lists gpt-6.1-sol at $2.00 per 1M input tokens and $10.00 per 1M output tokens (short context). Say one "generate" action in your app averages 3,000 input tokens and 800 output tokens:
- Input: 3,000 / 1,000,000 x $2.00 = $0.006
- Output: 800 / 1,000,000 x $10.00 = $0.008
- Unit cost: about $0.014 per action
Now look at two kinds of users (example numbers, replace them with yours from Step 1):
| User type | Actions per month | AI cost per month |
|---|---|---|
| Light user | 50 | $0.70 |
| Heavy user | 1,000 | $14.00 |
Do not forget payment fees. Stripe's standard US pricing for domestic cards is 2.9% + 30 cents per successful transaction (Stripe pricing); rates vary by country and payment method. On a $19 plan, that is about $0.85 per month.
The average user tells you little. The heavy user decides whether a flat price is safe.
Step 3: Anchor the price to value, not to your costs
Costs give you a floor, not a price. For that, you need to know what your app replaces.
Stripe's guide to pricing AI products says good AI pricing starts with your "value metric", defined through lots of user conversations. In plain terms: what problem do you solve, and what does it cost people today?
Talk to 5 to 10 potential users. Use these questions:
- How do you handle this task today?
- How long does it take you each week?
- What do you pay for tools, freelancers, or extra hours to get it done?
- What would make this a no-brainer purchase for you?
- At what price would this start to feel expensive?
If your app turns a 3-hour weekly task into 20 minutes, $19 or $29 a month is small next to the time saved. If people use it once a month, a high monthly price will feel wrong.
A simple sanity check: your price should be well above your heavy-user cost from Step 2, and clearly below the cost of the old way of doing the job.
Step 4: Launch with one plan that includes a usage allowance
Stripe's guide lists the common AI pricing models: pay as you go, subscription with a usage allowance, subscription plus overage, credit burndown (prepaid credits), and subscription with replenishing credits.
For a first launch, keep it boring: one monthly plan with a clear monthly allowance. For example:
Pro - $19/month. Includes 300 generations per month. Resets every month.
Why this works for beginners:
- Buyers see one price and one limit.
- Your worst case is known. Using the Step 2 numbers, 300 generations cost you at most 300 x $0.014 = $4.20, plus about $0.85 in Stripe fees. That leaves about $13.95 of a $19 plan even for your heaviest user, before hosting and taxes.
- You can add a bigger plan later, based on real usage.
A note on free plans: with an AI app, every free user costs you money. Prefer a short trial with a small allowance (for example, 20 generations) over a free-forever tier on an expensive model.
You do not need metered billing on day one. Count usage in your own database and block at the limit. If you later want true usage-based billing, Stripe now points new usage-based integrations to Metronome, which is part of Stripe (Stripe docs).
Step 5: Add guardrails in your app and at your AI provider
A limit means nothing if the code does not enforce it. Stripe's guide recommends usage caps with alerts and rate limiting. Add two layers.
Layer 1: check the allowance before every AI call. Here is the idea in a few lines of TypeScript:
const MONTHLY_LIMIT = 300;
const used = await countAiCallsThisMonth(userId); // from ai_usage
if (used >= MONTHLY_LIMIT) {
return Response.json(
{ error: "limit_reached", message: "You have used all 300 generations this month." },
{ status: 402 }
);
}
// ...only now call the AI API
Or let your AI tool build it:
Before every AI API call on the server, count this user's rows in ai_usage
for the current calendar month. If the count is 300 or more, skip the AI
call and return a friendly "limit reached" message with a link to the
pricing page. Show the user "X of 300 generations used" in the dashboard.
Also add a simple per-user rate limit of 10 AI requests per minute.
Layer 2: set a hard spend limit at the provider. This is your safety net if a bug or abuse slips past your code.
-
OpenAI: in Project settings, go to Limits, set a monthly spend limit, and turn on "Enforce a hard limit". Requests over the limit fail with a
429error and the codeproject_spend_limit_exceeded. Enforcement is not instant, so spend can go slightly over (OpenAI docs). -
Anthropic: set a spend limit on the Billing page in the Claude Console, or per workspace (you cannot set limits on the Default Workspace). When you hit a limit you set, requests return HTTP 400 with
invalid_request_error(Claude rate limits docs, Workspaces docs).
Show a friendly "try again soon" message for these errors, not a blank screen.
Step 6: Write a pricing page that answers the scary questions
Answer what a nervous buyer wonders. Copy this template:
[Plan name] - $[price]/month
For: [who it is for, in one line]
Includes: [N] [actions] per month, resets on your billing date
What happens at the limit: [you can wait for reset / upgrade / buy a top-up]
Trial: [N] free [actions], no card required (or: card required)
Cancel anytime from your account page
Early user promise: your price stays the same as long as you stay subscribed
That last line is easy to keep with Stripe. You cannot change the amount of an existing Stripe price. Instead, you create a new price and archive the old one, and existing subscriptions on an archived price stay active until they are canceled (Stripe docs). So raising prices for new customers does not touch your early users unless you move them yourself.
Step 7: Review every month and change price for new users first
Your first price is a guess. Stripe's guide reports that, in its survey, the highest-growth companies were nearly three times as likely to report frequent pricing adjustments. It also describes Clay rolling out fundamental pricing changes to new users first.
Once a month, check:
- AI cost per user: is your heaviest user still profitable?
- How many users hit the limit? If many do, a bigger plan may be waiting to be built.
- Did people cancel over price or fit? Ask them.
Common mistakes to avoid
- Unlimited AI on a flat plan. Your best users become your most expensive users.
- Pricing from build cost. Price the problem you solve, not the hours you spent building.
- Three tiers on day one. You do not know yet which features belong in which tier.
- Free forever on an expensive model. Use a capped trial instead.
- Forgetting fees. Payment fees, taxes, and hosting come out of every charge.
- Hiding the limit. Show "X of 300 used" in the app so the limit never surprises anyone.
- No handling for provider errors. A spend-limit error should show a calm message, not crash the page.
Your 7-day pricing plan
-
Day 1: Add the
ai_usagetable and logging (Step 1). - Day 2: Calculate your unit cost and heavy-user cost (Step 2).
- Days 3-4: Talk to 5 potential users with the question list (Step 3).
- Day 5: Pick one plan and one allowance; set the allowance so your heavy-user cost still leaves healthy margin (Step 4).
- Day 6: Add the in-app limit check, rate limit, and provider hard spend limit (Step 5).
- Day 7: Publish the pricing page with the template, and set a monthly reminder to review (Steps 6-7).
Pricing is a small experiment you run every month. Start with one honest plan, protect yourself with limits, and let real usage tell you what to do next.
Top comments (0)