Skip to content

Stripe Tax, and when you legally need to care

With Stripe you are the merchant of record, so sales tax and VAT are your liability. What Stripe Tax does and does not do, the thresholds that trigger obligations, and when a merchant of record is the better answer.

Stripe6 min readships at docs/solutions/stripe/stripe-tax-and-when-you-need-it.md

Tags: stripe · tax · vat · sales-tax · compliance · merchant-of-record

The uncomfortable fact first: when you charge with Stripe, you are the merchant of record. The contract is between you and the customer. Sales tax, VAT and GST are your obligation to calculate, collect, file and remit, in every jurisdiction where you have a tax obligation.

Stripe Tax makes that tractable. It does not make it someone else's problem. That distinction is the entire subject of this page, and it is the one thing to be clear about before you pick a payment provider.

Nothing here is legal or tax advice. It is the engineering shape of the problem and the questions to take to an accountant.

What Stripe Tax does

  • Calculates the correct rate at checkout, from the customer's location, your registered locations and the product's tax category.
  • Collects it as part of the payment, as a separate line on the invoice.
  • Monitors thresholds and tells you when your activity in a jurisdiction is approaching the point where you must register.
  • Produces filing reports, and through Stripe Tax's filing service (in supported jurisdictions) can file and remit for you.

It costs roughly 0.5% per taxed transaction on the pay-as-you-go plan, on top of processing fees.

What Stripe Tax does not do

  • Register you. You must register with each tax authority yourself and add the registration in the dashboard. Until you do, Stripe Tax collects nothing for that jurisdiction. Correctly, because collecting tax you are not registered to collect is itself a problem.
  • Take on liability. If the calculation is wrong because the product tax category was wrong, the shortfall is yours.
  • Decide where you have nexus. That is a legal question about your business.
  • Backdate. It cannot collect tax you should have collected last year.

Turning it on

const session = await stripe.checkout.sessions.create({
  mode: "subscription",
  customer: customerId,
  line_items: [{ price: priceId, quantity: 1 }],
  automatic_tax: { enabled: automaticTaxEnabled() },  // STRIPE_AUTOMATIC_TAX
  // Tax needs an address; let Checkout save the one the customer types
  // back onto the customer record so renewals stay correct.
  customer_update: { address: "auto", name: "auto" },
  // B2B in the EU: a valid VAT id shifts the liability to the buyer.
  tax_id_collection: { enabled: true },
  billing_address_collection: "auto",
});

That is exactly what the Stripe adapter's createCheckout in this project does (src/lib/billing/provider.ts), for subscriptions and one-time payments alike, except that the calculation is off until you switch it on, with STRIPE_AUTOMATIC_TAX=true in the environment. That is not caution about tax; it is that Stripe rejects a Checkout Session with automatic tax on an account that has not activated Stripe Tax and registered an origin address. Shipping it on would mean the first buy button in a freshly generated repo fails. (It would fail gracefully, on /billing with "Stripe could not start the checkout", but nobody could pay.) Turn it on as soon as you have done the two dashboard steps, and bun run verify will fail loudly if the flag and the account ever disagree.

Everything else in the snippet (customer_update, tax_id_collection, billing_address_collection) is on from the first line of code, because those are free to send and are what makes the renewal invoice calculable later.

Three details matter:

customer_update: { address: "auto" } is not optional. Without it the address the customer enters at checkout is attached to the session and not to the customer, so the renewal invoice a month later has no address and tax calculation fails.

Product tax categories. Each Stripe product needs one (txcd_10103000 for SaaS, and a long list of others). The default is a generic category that is wrong in enough jurisdictions to matter. Set it per product in the dashboard.

Prices are tax-exclusive by default. In the EU and UK, consumers expect the displayed price to include VAT. If you display tax-inclusive prices, set the price's tax_behavior to inclusive, and know that your net revenue per customer then varies by country.

When do you actually need it?

The honest sequencing for a small SaaS:

Your home jurisdiction, from the first sale. You are registered there, or should be. Turn Stripe Tax on before you take money.

Everywhere else, at the threshold. Obligations are usually triggered by economic activity, not by having a single customer:

  • US: each state sets its own economic nexus threshold; $100,000 in sales or 200 transactions in a state per year are common figures, and they vary. Several states tax SaaS, several do not.
  • EU: for B2C digital services sold from outside the EU there is effectively no threshold: the first sale creates an obligation, handled through the non-Union OSS scheme. For intra-EU cross-border B2C there is a €10,000 annual threshold. B2B with a valid VAT id is reverse-charged to the buyer.
  • UK: VAT registration threshold applies to UK-established businesses; non-established businesses have no threshold for digital services.
  • Everywhere else: varies enormously. Canada, Australia, Norway, Japan, Switzerland, India and many others have digital-services rules with their own thresholds.

Stripe Tax's threshold monitoring exists precisely because tracking this by hand across 40 jurisdictions is not a thing a founder can do. Turn it on early even if you register nowhere yet. The monitoring is the value.

The alternative: a merchant of record

Paddle, Lemon Squeezy, Polar and Dodo (the last two are alternatives in this registry) sell your product as the seller. They take the tax liability, the registrations and the filings. You receive a payout.

The trade:

Stripe + Stripe TaxMerchant of record
Tax liabilityyourstheirs
Registrations and filingsyours (or Stripe's filing service)theirs
Rate~2.9% + 30c, +0.5% taxtypically 5%+ all-in
Control over checkout, invoices, dunningcompletelimited
Customer relationshipyourstheirs on the receipt

The rule of thumb: at low revenue, a merchant of record is cheaper than an accountant plus your time. At higher revenue, the percentage becomes a real number and Stripe plus a tax professional wins. The crossover is different for every business, but "I do not want to think about VAT" is a legitimate and common reason to start with a merchant of record and migrate later.

Migrating later is real work: subscriptions do not transfer between processors, so it means asking every customer to re-enter a card. Factor that in.

Getting the data right

Whatever you choose, your database should keep enough to answer an auditor:

  • The invoice id for every payment, and the tax amount as a separate figure.
  • The customer's country and, where collected, their tax id.
  • Which jurisdiction the tax was attributed to.

Stripe holds all of this, and Stripe's reports are the authoritative source. Do not build a parallel tax ledger. What you want locally is the identifiers that let you find the Stripe record fast.

What to do this week

  1. Add your origin address and home registration at https://dashboard.stripe.com/settings/tax, then set STRIPE_AUTOMATIC_TAX=true. customer_update: { address: "auto" } is already on in this project's checkout and needs nothing from you.
  2. Set a product tax category on every product.
  3. Add your home jurisdiction's registration in the dashboard.
  4. Let threshold monitoring run, and put a calendar reminder to look at it quarterly.
  5. Ask an accountant, once, where you have obligations today. It is a cheap conversation and the answer changes what you build.