Guides

How to calculate AI margin per user from a revenue CSV (Paddle, Lemon Squeezy, spreadsheets)

In short: every billing system can export payments as CSV. If each row carries the same user ID your backend uses for AI calls, you can compute AI margin per user without wiring up a single webhook: net revenue per user minus AI cost per user, over the same period.

This is the fastest way to answer "which users cost more than they pay?" for apps on Paddle, Lemon Squeezy, Gumroad, an invoicing tool, or a hand-kept spreadsheet, and for history from before you connected anything else.

1. The columns you need

ColumnWhy
idThe payment or invoice ID. Makes re-imports safe: the same ID is never counted twice
user_idThe ID your backend sends with AI calls. Without it there is no join
typepurchase, renewal, refund, trial_started, cancellation or expiration
tsWhen it happened (a date is enough)
amount_usdWhat the customer paid, or the amount refunded
net_usd (optional)What you kept after tax and fees; or give tax_pct and fee_pct
period_end (optional)When the paid period ends, so you know who is still a paying user
id,user_id,type,ts,amount_usd,net_usd,product_id,period_end
in_001,user_42,purchase,2026-10-01,20,17.12,pro_monthly,2026-11-01
in_002,user_42,renewal,2026-11-01,20,17.12,pro_monthly,2026-12-01
re_001,user_7,refund,2026-10-12,20,20,pro_monthly,

2. Getting the export

3. Net revenue, refunds and currencies

4. Join with AI cost

margin(user) = Σ net_usd (payments − refunds) − Σ ai_cost   // same user, same period

AI cost per user comes from your backend: after each call, read the token counts and price them for the model (see the OpenAI and Anthropic guides). Use a period long enough to include each user's payment: monthly plans need at least 30 days, annual plans 90 days or more.

5. Keep it current

A CSV is a snapshot. Re-export each week or month and import the whole file again; with a stable id per row, rows already counted are skipped. When you outgrow that, send each payment from your backend as it happens with a revenue API, and keep CSV for backfills.

The shortcut

FiscaLLM takes this CSV as is. Upload it on the Setup page; common column names like customer, date and amount are recognised, bad rows are listed by line number, and re-uploading skips what is already there. Report AI usage with one line per call and you see margin per user, per plan and per trial, with alerts when someone starts losing you money.

It's free and open source (MIT) and can be self-hosted. Open the demo dashboard (sample data, no sign-up), read the CSV docs, or start free.

Questions

Do I need a webhook to track AI margin?

No. A CSV export with a user ID per row is enough to start. Webhooks only save you from re-exporting.

What if my export has no user ID?

Map the billing system's customer ID or email to your own user ID first, or report AI usage under the billing customer ID. Either way both sides need the same ID.

Can I mix CSV with Stripe or RevenueCat?

Yes, as long as each payment comes from one source. Sending the same payment twice under different IDs counts it twice.