Stripe Verifier: how every number is computed

TL;DR — The verifier reads a Stripe account through a restricted, read-only key the seller creates for the deal. It issues only GET requests, computes every metric from raw Stripe objects (not the seller's spreadsheet), and documents each formula below, including what a read-only key cannot see. The key is used in memory for one request and never stored, logged, or sent anywhere except api.stripe.com.

A seller's churn number is a summary of data you cannot check. A CSV export is data the seller chose and can shape. The Stripe Verifier closes both gaps: you ask the seller for a restricted read-only key, and the metrics come from the same subscription objects Stripe itself bills on.

What the seller has to do

In Stripe: Developers → API keys → Restrictable keys → Create key. The key must start with rk_ (restricted). Grant it Read only on these resources:

ResourceUsed for
SubscriptionsMRR bridge, active vs claimed, concentration, discounts, annual share, failed payments
ChargesGross volume, failed-payment count (90 days)
RefundsRefund count and rate (12 months)
DisputesDispute count and rate (12 months)
EventsExpansion vs contraction snapshots (last ~30 days)

If the seller refuses to create a read-only key for a deal that is otherwise progressing, that refusal is itself diligence signal. The key can be deleted from the same dashboard screen the second the verification is done.

The security model, in plain language

How each number is computed

All money is computed in integer cents in the account's own currency. No FX conversion is applied; if an account bills in several currencies, the dominant one is reported and noted.

1. MRR and the monthly MRR bridge

Each subscription's MRR is the sum over its items of unit_amount × quantity, normalized to a month: yearly prices are divided by 12, weekly by 52/12, daily by 365/12. Metered usage-based prices have no fixed amount and are excluded from MRR (counted, and flagged in the notes).

For each of the last 12 months the bridge reports: new MRR (subscriptions created that month), churned MRR (subscriptions whose effective churn date falls in that month), and month-end MRR (everything paying at month end). Effective churn is canceled_at for immediate cancels, or the period end when a subscription was set to cancel_at_period_end. The last month runs to the moment of verification, not the end of the calendar month.

2. Active subscriptions vs claimed

Counted as paying right now: active, past_due, unpaid (past_due and unpaid are also broken out separately, with their MRR, under failed payments). Trialing subscriptions are reported separately and never counted as revenue — trials have not paid. Subscriptions already marked cancel_at_period_end are reported as scheduled churn with their MRR: revenue the seller's dashboard still shows that has a confirmed end date.

3. Refunds and disputes

Refunds and disputes from the last 12 months are summed over the gross volume of succeeded charges in the same window, each reported as a count, an amount, and a percentage of gross volume.

4. Discount and coupon share, the promo cliff

Discounted subscriptions are subscriptions carrying a discount object right now. The promo cliff is the MRR on discounted subscriptions whose discount ends within the next 90 days — the gap between the price the seller is showing you and the price customers will actually pay after close.

5. Annual-prepay share

Subscriptions on a yearly interval are summed as a share of total MRR (each normalized to monthly, so shares are comparable). Annual renewals falling in the next 90 days are reported with their MRR, for the same reason as the promo cliff: a mass of annual renewals right after close is a known way a "stable" MRR steps down.

6. Customer concentration

MRR is aggregated per customer ID; the report shows the top-10 customers' MRR and share, the top-10 combined share of MRR, and the number of paying customers. A top-10 share above roughly 50% means a handful of relationships decide whether the asset still works after close.

7. Failed payments

Counts of past_due and unpaid subscriptions with their combined MRR, their share of paying subscriptions, and the number of failed charges in the last 90 days. Involuntary churn from failed cards is the most common "hidden" churn category in seller-reported numbers.

8. Expansion vs contraction

Upgrade and downgrade MRR in the last ~30 days is computed from Stripe's customer.subscription.updated event snapshots: consecutive snapshots of the same subscription give a true price delta. This is the one place the verifier can see historical prices, because Stripe retains events for roughly 30 days.

What a read-only key cannot see (and how we handle it)

Try it

The endpoint is live and returns the full JSON report:

curl -X POST https://churnlens.site/api/verify-stripe \
  -H "Content-Type: application/json" \
  -d '{"key":"rk_test_...","months":12}'

A rk_test_ key works against Stripe test-mode data, which is the safe way to see it run before you ask a seller for anything. Every example number shown anywhere on this site is clearly labelled synthetic — no real business's data is displayed.

Cost

The verifier is free. It exists because computing these numbers yourself, from raw objects, is the entire product thesis of ChurnLens — the paid work is the interpretation (full report, human review) on top of numbers you can trust.

Verify a target before the wire

Restricted read-only key in, buyer-side metrics out. Free, no account, nothing stored.

Run the Verifier (or the demo)