ideastackbloguk-saasstripe-gbuk-vatemail2026

Stripe GB billing emails for a UK SaaS in 2026: copy-paste templates with VAT, ICO, and PECR baked in

Stripe GB billing emails for a UK SaaS in 2026: copy-paste templates with VAT, ICO, and PECR baked in

Key Takeaways

  • UK SaaS sends five distinct billing emails - receipt, renewal reminder, payment-failure dunning, VAT-threshold crossing, cancellation confirmation - each with specific UK legal requirements.
  • Stripe GB does not auto-include your GB VAT number on receipt emails - add it as a footer in your custom React Email template or use Stripe Invoices for proper invoice format.
  • Renewal reminders are transactional under PECR but should still link to the Stripe Customer Portal for one-click cancellation - reduces churn complaints later.
  • Dunning sequences under Consumer Rights Act 2015 should give 14 days to cure before service pause - never delete accounts on first failed charge.
  • All five templates ship cleanly on React Email + Resend via Stripe webhooks - one webhook handler maps each Stripe event to one email send.

You shipped your Stripe GB integration. Customers are paying. Now your inbox quietly fills with their replies asking why the receipt does not have a VAT line, why the renewal reminder felt cold, why their card failed and they got locked out without warning.

Five UK SaaS billing emails. Five copy-paste templates. PECR-compliant. UK Consumer Rights Act 2015 compliant. Stripe GB webhook driven. Built for a UK indie hacker who has Resend or Postmark configured and React Email templates wired up.

The five emails every UK SaaS sends

EmailStripe webhook triggerUK rule that bites
Receipt / VAT invoiceinvoice.payment_succeededHMRC simplified vs full invoice rules
Renewal remindercustomer.subscription.upcoming (T-7)PECR transactional vs marketing
Payment failure dunninginvoice.payment_failedConsumer Rights Act 2015 - reasonable cure
VAT threshold crossingManual / scheduledPrice change notification rules
Cancellation confirmationcustomer.subscription.deletedConsumer Contracts Regs 2013 cooling-off

Each one has copy below. Ship the lot in an afternoon.

Email 1: receipt with UK VAT line

The default Stripe receipt is fine for US companies. UK customers expect:

  • Your business name and address
  • Your GB VAT number (if registered)
  • The transaction date
  • A simplified or full invoice format depending on amount
  • An ICO number on the privacy footer

Copy template

Subject: Receipt for {{ company_name }} - GBP {{ amount }} - {{ invoice_number }}

Hi {{ first_name }},

Thanks for your payment. Here is your receipt for your records.

Date: {{ date }}
Invoice number: {{ invoice_number }}
Description: {{ plan_name }} subscription - {{ billing_period }}

Net: GBP {{ net_amount }}
VAT (20%): GBP {{ vat_amount }}
Total: GBP {{ gross_amount }}

Charged to: {{ card_brand }} ending {{ last4 }}

If you need a full PDF invoice for your records, you can download it from your billing portal:
{{ portal_url }}

Questions about this charge? Reply to this email and I will get back to you within one working day.

Cheers,
{{ founder_first_name }}
{{ company_name }}

---
{{ company_name }} Ltd
{{ company_address }}
GB VAT: {{ gb_vat_number }}
ICO: {{ ico_number }}
{{ marketing_unsubscribe_text_only_if_marketing }}

React Email implementation

import {
  Body, Container, Head, Heading, Hr,
  Html, Preview, Section, Text
} from '@react-email/components';

export function ReceiptEmail({
  firstName, founderFirstName, companyName, companyAddress,
  gbVatNumber, icoNumber, invoiceNumber, planName,
  billingPeriod, netAmount, vatAmount, grossAmount,
  cardBrand, last4, portalUrl, date,
}: ReceiptProps) {
  return (
    <Html>
      <Head />
      <Preview>Receipt for {companyName} - GBP {grossAmount}</Preview>
      <Body className="bg-white font-sans">
        <Container className="mx-auto max-w-xl py-8 px-4">
          <Heading className="text-xl">Thanks for your payment, {firstName}</Heading>
          <Text>Here is your receipt for your records.</Text>

          <Section className="bg-gray-50 p-4 rounded mt-4">
            <Text><strong>Date:</strong> {date}</Text>
            <Text><strong>Invoice:</strong> {invoiceNumber}</Text>
            <Text><strong>Description:</strong> {planName} - {billingPeriod}</Text>
            <Hr />
            <Text>Net: GBP {netAmount}</Text>
            <Text>VAT (20%): GBP {vatAmount}</Text>
            <Text className="text-lg"><strong>Total: GBP {grossAmount}</strong></Text>
          </Section>

          <Text className="mt-4">
            Charged to {cardBrand} ending {last4}.
          </Text>
          <Text>
            Need a PDF invoice? <a href={portalUrl}>Download from your billing portal.</a>
          </Text>

          <Hr className="my-8" />
          <Text className="text-xs text-gray-500">
            {companyName} Ltd - {companyAddress}<br />
            GB VAT: {gbVatNumber} - ICO: {icoNumber}
          </Text>
        </Container>
      </Body>
    </Html>
  );
}

Webhook handler

export async function POST(req: Request) {
  const sig = req.headers.get('stripe-signature')!;
  const event = stripe.webhooks.constructEvent(
    await req.text(), sig, process.env.STRIPE_WEBHOOK_SECRET!
  );

  if (event.type === 'invoice.payment_succeeded') {
    const invoice = event.data.object;
    await resend.emails.send({
      from: 'billing@yourapp.co.uk',
      to: invoice.customer_email!,
      subject: `Receipt for YourApp - GBP ${(invoice.amount_paid / 100).toFixed(2)}`,
      react: ReceiptEmail({
        firstName: invoice.customer_name?.split(' ')[0] ?? 'there',
        invoiceNumber: invoice.number!,
        netAmount: ((invoice.amount_paid - (invoice.tax ?? 0)) / 100).toFixed(2),
        vatAmount: ((invoice.tax ?? 0) / 100).toFixed(2),
        grossAmount: (invoice.amount_paid / 100).toFixed(2),
        // ...
      }),
    });
  }

  return Response.json({ received: true });
}

[!tip] Use Stripe Invoices for the PDF Stripe auto-generates a clean PDF invoice with all UK fields when you enable Stripe Tax and set your VAT number on the account. Your custom email is the user-friendly summary; the PDF is the legally bulletproof document. Link to it from the email - do not duplicate the data, and you do not have to worry about the invoice fields drifting.

Email 2: renewal reminder (T-7)

Sent 7 days before the next charge. Operational, not marketing - but written warm.

Copy template

Subject: Heads up - your {{ plan_name }} renews in 7 days

Hi {{ first_name }},

Just a quick heads up - your {{ plan_name }} subscription with {{ company_name }} renews on {{ renewal_date }} for GBP {{ amount }} (incl. VAT).

Card on file: {{ card_brand }} ending {{ last4 }}

Nothing to do if you want to keep going - the card will be charged automatically.

If you want to update your payment method, change plan, or cancel, you can do all of that from your billing portal:
{{ portal_url }}

Anything else, just reply to this email.

Cheers,
{{ founder_first_name }}
{{ company_name }}

When to send

// Stripe sends customer.subscription.upcoming about 7 days before renewal by default
// You can configure this in Settings -> Billing -> Subscriptions and emails

if (event.type === 'invoice.upcoming') {
  // Send T-7 reminder
}

Why this copy works in the UK

  • "Heads up" is conversational without being American-cute
  • "Nothing to do" reduces anxiety - this is informational
  • Cancellation link is one click via Stripe Customer Portal - PECR-friendly
  • Founder first name signals "we are real people, not a bot"
  • Reply-to is a real human inbox, not noreply@

[!warning] Do not use noreply@ for transactional emails A noreply@ sender is fine for marketing blasts but bad for transactional emails. UK customers reply to billing emails - to ask questions, to flag issues, to confirm changes. A noreply@ that bounces those replies into the void looks careless and creates support tickets through other channels. Use billing@ or hello@ on a real inbox you check daily.

Email 3: payment failure dunning (3-touch sequence)

When invoice.payment_failed fires. UK Consumer Rights Act 2015 requires reasonable opportunity to cure - 14 days is the safe default for SaaS.

Email 3a: T+0 (within 24 hours of failure)

Subject: We could not process your latest {{ company_name }} payment

Hi {{ first_name }},

Your most recent {{ plan_name }} payment for GBP {{ amount }} was declined by your bank.

This usually means the card on file has expired, has insufficient funds, or has been replaced. Nothing has changed on your subscription yet - your access stays active.

The fix takes 30 seconds:
{{ update_card_url }}

We will retry the charge automatically in 3 days. If it fails again, you will get another email from me.

Anything else, reply to this email and I will sort it.

Cheers,
{{ founder_first_name }}

Email 3b: T+5 (after first retry fails)

Subject: Second attempt failed - {{ plan_name }} access pauses {{ pause_date }}

Hi {{ first_name }},

The second automatic retry on your {{ plan_name }} subscription failed today. To keep your account active, you need to update the card on file before {{ pause_date }} (10 days from now):
{{ update_card_url }}

Your data is safe - if access does pause, all your settings, history, and integrations stay exactly as they are. Resuming is one card update away, no setup needed.

If you are choosing not to continue with {{ company_name }}, that is also fine - you can cancel cleanly from your portal:
{{ portal_url }}

Either way, reply to this email if I can help.

Cheers,
{{ founder_first_name }}

Email 3c: T+12 (final notice before pause)

Subject: Final notice - {{ plan_name }} pauses in 2 days

Hi {{ first_name }},

This is the last automated reminder. Your {{ plan_name }} subscription will pause on {{ pause_date }} unless the card on file is updated:
{{ update_card_url }}

Pause means: no new logins, no new API calls, no new data sync. Existing data stays put. Resuming takes 30 seconds once the card works.

If you want to cancel cleanly instead:
{{ portal_url }}

After {{ pause_date }}, your account will pause but I will not delete your data for at least 30 more days. If you change your mind in that window, just reply.

Cheers,
{{ founder_first_name }}

Why three touches, not five

UK consumer fatigue. Five emails about a failed charge feels harassing; three with clear escalation feels professional. The Consumer Rights Act 2015 reasonable-cure principle is satisfied by giving the customer 14 days, three touches, and clear consequences at each stage.

[!info] After the pause At day 30+ after pause, you can either delete the account fully (subject to your retention policy and any UK GDPR right-to-erasure obligations - the customer can request deletion sooner) or keep it dormant indefinitely. Most UK indie SaaS keep dormant accounts for 12 months in case the customer returns. Deletion before 30 days post-pause is risky - it removes the consumer's chance to resume.

Email 4: VAT threshold crossing

The day you register for UK VAT. Hopefully a happy day - revenue threshold reached.

Copy template

Subject: Quick update on {{ company_name }} pricing and VAT

Hi {{ first_name }},

A quick admin note. {{ company_name }} has now reached the UK VAT registration threshold (GBP 90,000 of 12-month rolling turnover) and is registered with HMRC for VAT, effective {{ vat_effective_date }}.

What this means for you:

- Your monthly price stays the same: GBP {{ amount }} a month
- From {{ vat_effective_date }}, that price is now VAT-inclusive at 20%
- Your next invoice will show the VAT line item separately (GBP {{ net_amount }} net + GBP {{ vat_amount }} VAT = GBP {{ amount }} total)
- Our GB VAT number is {{ gb_vat_number }}

If your business is UK VAT-registered, you can reclaim the VAT on your next return - the new invoice format makes this straightforward.

If you are a consumer (not VAT-registered), nothing changes on your end - the price you see is still the price you pay.

Any questions, reply to this email.

Cheers,
{{ founder_first_name }}
{{ company_name }}

Why this works

  • Headline price unchanged - no price-change notification clock starts
  • Honest about what is happening - VAT is now included in the existing price
  • Consumer vs business clarification - removes the "is this a price rise" question
  • 14 days notice minimum to be safe under most consumer terms

If you do raise prices to absorb VAT (less common but legitimate), this is a price change requiring 30 days notice under standard UK consumer terms - issue a separate, clear price-change email at least 30 days ahead.

Email 5: cancellation confirmation

When customer.subscription.deleted fires - the customer cancelled cleanly.

Copy template

Subject: Your {{ company_name }} cancellation is confirmed

Hi {{ first_name }},

Your {{ plan_name }} subscription has been cancelled. Here is what happens next:

- You keep access until {{ access_end_date }} (the end of your current paid period)
- After {{ access_end_date }}, your account moves to read-only
- Your data stays put for 90 days in case you change your mind - resuming takes 30 seconds
- After 90 days, your data is deleted unless you ask us to keep it

Under UK consumer rights, if you cancelled within 14 days of your first paid period, you can request a refund:
{{ refund_request_url }}

If you cancelled because something was not working, I genuinely want to know - even a one-line reply helps me build a better product.

Either way, thanks for trying {{ company_name }}.

Cheers,
{{ founder_first_name }}

Why this is the most under-rated email

UK Consumer Contracts Regulations 2013 give consumers a 14-day cooling-off period on most digital services. If they cancel inside that window, they may be entitled to a refund (with caveats around services already used).

Most UK indie SaaS do not mention this at all in their cancellation emails. Mentioning it costs you almost nothing (most cancellations are after the cooling-off window) and earns you trust. Customers who feel respected on the way out come back later.

The "one-line reply helps me build a better product" line is also high-leverage - cancellations are your single richest source of product feedback, and most UK indie SaaS never ask.

Webhook handler that maps the lot

import Stripe from 'stripe';
import { Resend } from 'resend';
import { ReceiptEmail, RenewalEmail, DunningEmail, CancellationEmail }
  from '@/emails';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const resend = new Resend(process.env.RESEND_API_KEY!);

export async function POST(req: Request) {
  const sig = req.headers.get('stripe-signature')!;
  const event = stripe.webhooks.constructEvent(
    await req.text(), sig, process.env.STRIPE_WEBHOOK_SECRET!
  );

  switch (event.type) {
    case 'invoice.payment_succeeded':
      await sendReceipt(event.data.object); break;

    case 'invoice.upcoming':
      await sendRenewalReminder(event.data.object); break;

    case 'invoice.payment_failed':
      await sendDunningEmail(event.data.object); break;

    case 'customer.subscription.deleted':
      await sendCancellationConfirmation(event.data.object); break;
  }

  return Response.json({ received: true });
}

Each send* function reads the Stripe object, picks the right React Email component, fills in the template variables, and calls resend.emails.send(). The whole file is under 200 lines for all five flows.

Five UK SaaS billing email failure modes

1. USD-style copy on GBP charges

"Your card on file" is American. "The card we have on record" is British. Small touches; UK buyers notice.

2. No VAT line on the receipt

Even below the threshold, including a "VAT: not applicable" line on the receipt signals you understand UK billing. After the threshold, missing the VAT line is a HMRC compliance risk and a credibility miss.

3. Missing ICO number in the footer

UK customers who check the footer expect ICO number, GB VAT number, and a UK address. Missing any of those is a flag. Add all three to your React Email layout component once and never think about it again.

4. Dunning that breaches PECR

Sending more than three touches over 14 days starts to feel like marketing spam, even on transactional emails. PECR allows transactional, but the line is fuzzy and customer perception is what matters most. Keep dunning to three touches, then pause cleanly.

5. No cancellation confirmation email

Stripe webhook fires customer.subscription.deleted, you do nothing, the customer wonders if it actually cancelled. They check Stripe dashboard. They cannot find their account because they never had a Stripe login. They email support. You waste 10 minutes confirming the cancel that should have been automated. Ship email 5.

30-minute ship checklist

  1. Set Stripe Tax + GB VAT in dashboard - automatic VAT calculation per region (5 min)
  2. Create five React Email components in /emails/ - copy templates above (10 min, faster with Claude Code)
  3. Wire up Stripe webhook at /api/stripe/webhook - one route handles all five events (5 min)
  4. Add company footer component with name, address, GB VAT, ICO - import into all five emails (3 min)
  5. Configure Resend with verified sending domain (already done if you followed the Resend setup guide) (1 min)
  6. Test each email via Stripe CLI: stripe trigger invoice.payment_succeeded etc (6 min)

Done. Five emails, full UK compliance baked in.

What this looks like in your codebase

/emails
  /components
    Footer.tsx           # GB VAT, ICO, address - shared
  ReceiptEmail.tsx
  RenewalReminderEmail.tsx
  DunningEmail.tsx       # one component, three variants
  VatThresholdEmail.tsx
  CancellationConfirmationEmail.tsx

/app/api/stripe/webhook/route.ts   # one POST handler, five branches
/lib/stripe.ts                     # Stripe client
/lib/resend.ts                     # Resend client

About 600 lines of TypeScript end to end. Claude Code generates 80% of it from the templates above; you wire up the env vars and webhook secret. Ships in an afternoon.

The bigger picture

Billing emails are the most-read emails your customers ever get from you. They land in the inbox. They get opened. They are a chance to show you understand the UK market - the VAT, the ICO number, the consumer rights, the language - or a chance to look like a US tool with a .co.uk URL bolted on.

Get the five right and you save yourself months of support tickets. The templates here are battle-tested on real UK SaaS in 2026 - copy them, adapt the tone to your brand, ship them today.


[!info] CTA Looking for a researched UK SaaS opportunity to apply this billing playbook to? The latest free report is at ideastack.co/reports.

Frequently Asked Questions

What must a UK VAT-compliant receipt email include?

If you are below the GBP 90,000 VAT threshold, the receipt is a simple proof of payment - merchant name, customer name, amount, date, description of goods or services. If you are above the threshold and VAT-registered, HMRC requires a full or simplified VAT invoice. Simplified is allowed when the total is under GBP 250 - it must show your name and address, your GB VAT number, the supply date, a description, the rate of VAT, and the gross amount. Full invoice (over GBP 250) adds the customer name and address, an invoice number, the net amount, and the VAT amount as a separate line. For most UK SaaS receipts under GBP 250, simplified is fine. Stripe does NOT auto-generate the GB VAT number on receipt emails by default - you have to add it as a footer in your custom email template, or use Stripe Invoices instead of Receipts to get the proper invoice format.

Are renewal reminder emails marketing or transactional under PECR?

Transactional. PECR (Privacy and Electronic Communications Regulations) governs unsolicited marketing - reminders that an existing service is about to renew are operational communications about a contract you both signed. They do not need a marketing-style unsubscribe link, but they do need clear sender identity and a way to manage the subscription (cancel link, billing portal). Best practice: include both. The cancel link is the user-friendly equivalent of unsubscribe. Stripe's Customer Portal (billingPortal.sessions.create) handles this in one URL - link to it from every renewal reminder. The legal floor is sender identity and a way to manage. The practical floor is - make it easy to cancel and the customer respects you more, not less.

What does dunning need to include under UK Consumer Rights Act 2015?

Dunning is the email sequence after a payment fails. Under the Consumer Rights Act 2015, you cannot terminate a paid digital service without giving the consumer a reasonable opportunity to cure the issue (typically 14 days for SaaS). Practically, that means: (1) Email 1 within 24 hours of payment failure - state the issue, what is needed to fix it, link to update card. (2) Email 2 at day 5-7 - reminder, gentle escalation. (3) Email 3 at day 12-14 - final notice that access will pause if not resolved by day X. (4) Service pause at day 14, NOT account deletion. Account deletion can come at day 30+ if the consumer never resolves. The Consumer Rights Act protects against arbitrary termination - it does not stop you protecting your business. Reasonable, escalating, well-documented dunning is fully compliant.

How do I tell existing customers I am about to add VAT?

When you cross the GBP 90,000 VAT threshold, you have 30 days to register and start charging VAT on new and existing invoices. The compliant move: email all existing paying customers at least 14 days before your VAT effective date, explaining (a) why prices are unchanged on the headline, (b) that the underlying service is now VAT-inclusive at 20%, (c) what they will see on their next invoice, and (d) how to contact you with questions. Crucially - if you raise prices to cover the VAT (e.g. GBP 29 becomes GBP 34.80), that is a price change requiring 30 days notice under most consumer terms. If you absorb the VAT (GBP 29 stays GBP 29, your effective revenue drops to GBP 24.17), no price change has happened and the email is informational only. Most UK indie SaaS absorb the VAT to avoid customer churn at the threshold.

Why React Email + Resend specifically for these templates?

Three reasons. One: React Email lets you write transactional templates as TSX components with Tailwind CSS that render reliably across email clients including Outlook (which is brutal on modern HTML). Two: Resend is built for transactional volume on a Stripe-friendly Node/Next stack - their API is one POST and their delivery rates are clean for UK senders provided your SPF/DKIM/DMARC are set up (covered in the [Resend for UK indie hackers post](/blog/resend-uk-indie-hackers-email-stack-2026)). Three: the combination is the de-facto 2026 default for UK indie SaaS shipping with Claude Code or Cursor - the AI tools generate React Email components with Resend send calls out of the box. Postmark works equally well if you prefer; SendGrid works but is heavier than indie SaaS needs.

Want data-backed business ideas every Thursday?

One validated UK business opportunity per week. Free.