← all sprint docs

📱 APP REVENUE TRUTH — how we know what the App Store and Play actually paid us

CANONICAL. Settled 6 August 2026, measured against both stores' own reports. Supersedes every earlier statement about app proceeds, the iOS ratio, and the "app cash is ~15% overstated" warning. Any fleet or agent about to read, quote, model or act on an app revenue number — growth, CMO, CEO, CFO, analytics, attribution, CXO — reads this first.


§0 · The one-paragraph version

Both sides of the app calculation are NET. App Store Connect's "Total Estimated Proceeds" is net of Apple's cut, and RevenueCat's App Store revenue is also net. That is why the iOS calibration ratio sits near 1.0 — it is two net figures agreeing, not a defect. The long-standing warning that "app cash may be ~15% overstated (~$350–500/mo of phantom money)" is REFUTED. Nothing had to be given back. Google Play is the opposite: RevenueCat reports Play gross, so its ratio correctly sits near 0.73. Both stores now pull themselves — no human reads a dashboard again.


§1 · The two commands. Nobody types a store figure by hand.

# Apple — App Store Connect API, /v1/financeReports
tools/finance/venv/bin/python tools/finance/asc_finance_reports.py 2026-07 --write
tools/finance/venv/bin/python tools/finance/asc_finance_reports.py --since 2026-01

# Google Play — the bulk-reports bucket, earnings/
tools/finance/venv/bin/python tools/finance/play_earnings_reports.py --write

Both write NET into tools/finance/data_app_proceeds.json, which is what kpi_15k_sync.py calibrates the $15K app rail on. Never hand-edit that file.

Access (all in place, verified 6 Aug 2026): Apple needs ASC_KEY_ID / ASC_ISSUER_ID / ASC_KEY_PATH + ASC_VENDOR_NUMBER=87822406 in .env.local (the vendor number is UI-only — no Apple endpoint returns it; Aga supplied it). Play uses the read-only service account ~/.config/tma/play-aso-reader.json against gs://pubsite_prod_rev_07845367963248148244.


§2 · The evidence — why we say NET, rather than assume it

GBP May 2026 Jun Jul
Apple gross (customer paid) 3,448.95 2,828.54 2,977.45
Apple net (Extended Partner Share) 2,678.85 2,246.71 2,365.68
what data_app_proceeds.json already held 2,684.01 2,355.05 (was null)

The stored May figure is 0.19% from net and 28% from gross. That settles it.

Cross-checked from the other direction: RevenueCat App Store revenue reads $3,844 May · $3,085 Jun · $3,089 Jul — within 2–7% of Apple net and a consistent 17–23% BELOW Apple gross, three months running. So RevenueCat is reporting net too, despite RevenueCat's own documentation implying its default revenue is gross.

Google Play, measured the same way: May £115.78 and June £378.37 matched Google's earnings report to the penny. July did not — the file held £318.24, the true net payout is £730.65, out by £412.41, because it had been typed on 16 July, mid-month. Google's fee is exactly 15.0% of charge in every month measured.


§3 · 🔴 Five traps. Every one of these has already produced a wrong number.

  1. filter[reportDate] on Apple is a FISCAL period, not a calendar month. 2026-06 returns 1–28 March 2026. fiscal index = calendar month + 3 (roll the year past 12). Periods run 4 or 5 weeks and never align to calendar edges — read the Start/End dates off the report, never trust the label.
  2. Apple refunds carry a negative Quantity AND an already-negative Customer Price. Multiplying them flips refunds positive so they add to gross. Extend by abs(qty). This produced a nonsense EUR 0.29 ratio before it was caught.
  3. Play's NET is the sum of EVERY row, because Google fee / Tax / * refund rows are already signed negative. Summing only Charge gives GROSS and overstates by 15%.
  4. Never "fix" the iOS ratio to 0.85 on the belief that RevenueCat is gross. It is not. That change would understate app cash by 15%.
  5. Never type a store figure mid-month. That is precisely what produced the £412 July Play error and the bogus 0.3184 ratio. Run the command after month close instead.

Sanity check on any Apple month: net/gross = 0.85 ÷ (1 + local VAT). US/CA/HK/IL land on exactly 0.850 (Small Business Program, no VAT in the listed price); UK/EU ≈0.708 (20%); Norway/Denmark 0.680 (25%); UAE 0.810 (5%). If a country deviates, the parse is wrong.


§4 · 🔴 What genuinely CANNOT be done — say this, don't imply someone forgot

Neither store holds revenue back to 2024. The Play bucket's earliest earnings report is 202605. Its acquisition/ and stats/ prefixes go back to March 2018, but those are buyer counts and installs — not money. So "pull the store exports back to 2024 to bound the old funnel era" cannot be satisfied from store data at all. That ambition needs a different source (bank or Stripe history), and any plan that still lists it as a store task is wrong.


§5 · What this changed, and where


§6 · Provenance

Every figure here was read from the stores' own reports on 6 August 2026 — App Store Connect API /v1/financeReports and the Play bulk-reports bucket — cross-checked against the live RevenueCat v2 charts API. Nothing in this document is modelled or inherited. FX is spot (GBP base) at the time of pull; the gross/net gap is 15–30%, far outside FX noise.

Related: memory reference_asc_api_analytics_2026-07-30 (credentials + endpoint detail) · tools/finance/asc_finance_reports.py · tools/finance/play_earnings_reports.py · tools/finance/kpi_15k_sync.py · tools/finance/data_app_proceeds.json