The idea
A small web app that connects to Stripe, buckets every charge by the customer's tax jurisdiction, and tracks that running total against the registration threshold for each one. When a jurisdiction reaches 60% of its threshold, it emails you. When you cross, it tells you the registration deadline and what you owe from which date. It does not file anything and does not calculate tax on checkout — it answers one question: where am I about to become legally obligated to register.
Why build this
Every US state that taxes SaaS has an economic nexus threshold — typically $100,000 in sales or 200 transactions in a rolling twelve months, but the numbers, the lookback window, and whether transaction count even counts vary state by state. The EU has a €10,000 pan-EU distance selling threshold before OSS registration bites. The UK, Canada, Australia, Japan, and India each have their own. Nobody is watching these for you.
The full tax platforms — Avalara, Stripe Tax, Anrok — solve this, but they solve it by taking over your checkout and charging accordingly. A solo founder doing $200k ARR does not want to rewrite billing to find out whether they should have registered in Texas eight months ago. They want a read-only tool that watches and warns. That gap between "spreadsheet I update twice a year" and "enterprise tax engine" is where this lives, and it is wide.
The timing works because thresholds keep moving. Several states dropped their transaction-count test in the last few years, and more are revising the dollar figure. A tool whose whole value is a maintained rules table gets more valuable every time a legislature acts.
Stack sketch
- Ingest: Stripe API via a read-only restricted key, plus
charge.succeededandinvoice.paidwebhooks for incremental updates. Backfill with thecharges.listcursor. - Jurisdiction resolution: customer billing address first, then Stripe's
tax_idsand card country as fallbacks. For US addresses, resolve to state and, where relevant, local district — the Census Bureau geocoder handles the free tier, Smarty for anything ambiguous. - Rules data: a versioned YAML file per jurisdiction — threshold amount, transaction count test, lookback window (rolling twelve months vs. previous calendar year), effective date. Keep it in git, publish it publicly, let people file PRs when a rule changes.
- App: Next.js on the front, Postgres behind it, a nightly job that recomputes rolling totals per jurisdiction.
- Alerts: Resend for email, plus a Slack incoming webhook.
Scope for v1
- Stripe only. No Paddle, no Lemon Squeezy, no Shopify.
- US states and the EU OSS threshold. Nothing else.
- Rolling twelve-month and calendar-year windows, both computed from charge date.
- One alert at 60% of a threshold, one at 90%, one on crossing.
- Deliberately out: filing, tax calculation, rate lookup, exemption certificates, historical liability estimates, anything that requires an accountant's judgment.
Where it could go
The natural second step is more revenue sources. Paddle and Lemon Squeezy act as merchant of record and absorb the obligation, so those customers need the opposite view — proof they are covered. Adding non-MoR sources like Shopify, direct PayPal, and wire payments recorded in QuickBooks gives you a complete jurisdiction picture rather than a Stripe-shaped one.
Past that, the rules table is the real asset. Publish it as a versioned JSON feed with a changelog and it becomes something other tools depend on — a free tier that seeds adoption while the dashboard stays paid. A third path is going the other direction into accounting firms, who currently track this for a dozen clients in a shared spreadsheet and would pay per client seat for something that just watches.
Watch out for
This edges close to giving tax advice, so every surface needs to say what it is — a monitor, not a determination — and the rules table needs a visible last-verified date per jurisdiction. Stale threshold data that someone trusted is worse than no tool at all.