Guides

How to track AI cost per customer against Stripe revenue

In short: AI margin per customer is what the customer paid you through Stripe, minus tax and Stripe's fee, minus what their AI usage cost. Stripe knows the first half, your AI provider knows the second, and nothing joins them unless both use the same customer ID.

A flat $20 plan can hide a customer who costs you $60 a month in tokens. Averages won't show it; per-customer numbers will. This guide shows how to build that join, and the traps that make the numbers wrong.

1. Put your user ID on the Stripe subscription

Your backend knows your user ID when it calls the AI provider. Stripe knows a cus_… customer ID. Pick one and use it on both sides. The simplest way is to write your user ID into Stripe metadata when you create the checkout session or subscription:

await stripe.checkout.sessions.create({
  mode: "subscription",
  line_items: [{ price: "price_pro", quantity: 1 }],
  subscription_data: { metadata: { user_id: user.id } },
  customer_email: user.email,
  // …
});

Now every invoice for that subscription carries user_id in its subscription details, and you can attribute it without a lookup table. If you can't change checkout, store the cus_… ID on your user record and report AI usage under that instead.

2. Listen to the Stripe events that move revenue

Stripe eventWhat it means for margin
invoice.paidMoney in. billing_reason tells a first payment from a renewal
customer.subscription.created (trialing)A trial starts: AI cost begins, revenue is $0
customer.subscription.updatedAuto-renew switched off when cancel_at_period_end turns true
customer.subscription.deletedAccess ended: no more revenue, cost may continue
charge.refundedMoney back out. amount_refunded is a running total, so count only the new part

Verify the Stripe-Signature header on every request, and de-duplicate on the event ID: Stripe retries deliveries, sometimes hours later.

3. Use net revenue, not the invoice total

net = amount_paid − tax − (amount_paid × 2.9% + $0.30)   // Stripe's standard US card fee

On a $20 invoice that is about $19.12 before tax, and less if you collect sales tax or VAT. The exact fee is on the balance transaction; the standard rate is close enough for margin unless you have negotiated pricing or many international cards.

4. Record AI cost under the same ID

After each AI call, read the token counts from the response and price them for the model used. Cached input, cache writes and long prompts are priced differently, so use the provider's full price table. Store cost per user per day; that is all the join needs. The OpenAI and Anthropic guides cover the details.

5. Backfill past invoices

A webhook only sees events from the day you add it. Customers who paid last month look like free users until they renew. Backfill once through the API with a restricted key that can only read:

6. Traps that make the numbers wrong

The shortcut

FiscaLLM does all of the above. Paste one webhook URL from the Setup page, then paste a read-only restricted key to import the last 12 months; the key is used once and never stored, and invoices are counted once whether they arrive by webhook or import. Report AI usage with one line per call, and you get margin per customer, per plan and per trial cohort, with alerts when a customer starts losing you money.

meter.trackOpenAI(res, { userId, feature: "chat" });   // userId = metadata.user_id on the subscription
// Setup → Connect Stripe (webhook) → Import the last 12 months (restricted key)

It's free and open source (MIT), and you can self-host it so your revenue data never leaves your servers. The Stripe connector is in beta and USD only. Open the demo dashboard (sample data, no sign-up), read the Stripe docs, or start free. Not on Stripe? See margin from a revenue CSV or RevenueCat.

Questions

Does Stripe show AI cost per customer?

No. Stripe records what customers pay and, with usage-based billing, what you report to it, but it doesn't know what each customer cost you at OpenAI or Anthropic. That has to come from your backend and be joined by customer ID.

Should I use Stripe usage-based billing instead?

Usage billing passes cost on to the customer; it doesn't tell you your margin. Most AI apps keep a flat plan and need to see which customers the flat price doesn't cover.

Is a restricted key safe to share with a tool?

A restricted key with only Read access can't move money or change anything. Give it the fewest permissions the job needs, and delete it once the import is done.