Stripe Email Integration: Connect Billing Events to Email

There are three ways to turn Stripe billing events into email: switch on Stripe's own customer emails, use an email tool's Stripe integration, or run your own webhook endpoint that calls an email API. Pick Stripe's emails when failed-payment notices and receipts are all you need. Pick a tool with a Stripe integration when a marketer or founder should own the trial, onboarding and win-back sequences without code. Pick your own webhook when your app has to decide who gets what, or when your tool lacks an event you need. Most SaaS teams end up combining two routes, and that is where duplicate emails start.

The reader this page is for sells a subscription or a digital product through Stripe Billing and wants six things to produce email: a new subscription, a trial about to end, a failed payment, a paid invoice, a refund and a cancellation. Event names and behaviours come from Stripe's documentation, linked beside each claim; prices are from each vendor's public pages, read on 7 October 2026.

Pick a route before you pick a tool

Route Effort Fits What to check first
1. Stripe's customer emails and Billing automations Dashboard switches, no code Failed-payment notices, receipts, trial and renewal reminders Sandboxes send no customer emails by default; the email actions in Billing automations are limited to a team email and a cancellation email
2. An email tool's Stripe integration Install an app, paste a key, or paste a webhook URL, depending on the vendor Multi-step trial, onboarding and win-back sequences owned by non-developers The vendor's documented event list against your six events, and how a Stripe customer is matched to a contact
3. Your own webhook endpoint calling an email API Code you maintain: endpoint, queue, sender Teams where product state decides the message, or tools with gaps in event coverage Signature check on the raw body, an event-ID log, no reliance on event order, and who owns unsubscribes

A workable split: let Stripe own money-state messages that must go out whatever your tool does (receipts, failed-payment notices), and let a tool or your code own messages that depend on product behaviour (activation nudges, win-back).

What Stripe will email without any tool

Stripe's customer-emails page says you turn these on in the subscriptions and emails settings under Email notifications and customer management. It lists payment confirmations, failed-payment notices, trial-ending reminders, renewal reminders and expiring-card notices as emails that include a link where the customer can update a payment method, pointing either to a Stripe-hosted Customer Portal or to your own page. Details that matter when you plan around them:

  • Failed payments. With "Send emails when card payments fail" enabled, Stripe sends an email after each failed payment.
  • Trial ending. The switch is "Send a reminder email 7 days before a free trial ends". The trial-ending webhook event is a separate thing and defaults to 3 days before (see the event map below).
  • Renewals. Renewal reminders go only to subscriptions whose collection method is charge_automatically, on the number of days set under Upcoming renewal events.
  • Expiring cards. The email goes out one month before the default card expires.
  • Receipts. Stripe's receipts page says receipts exist for all successful payments and refunds, and that sending them automatically is a toggle under Settings, Business, Customer emails. For payments, nothing is sent if the payment fails.

The ceiling is the sequence. Stripe's Billing automations page lists six triggers (including "Subscription payment fails" and "Subscription is canceled") and, among the actions, "Send team email" and "Send subscription cancellation email", the latter with an optional survey link. It does not list an action for a custom multi-step customer sequence, which is the gap routes two and three fill. One interaction to know about: the same page says that when an automation runs for a trigger, it ignores your global settings for that case.

Retries are Stripe's job whichever route you choose. The Smart Retries page describes Smart Retries as choosing retry times with a model, a policy of a set number of tries inside 1 week to 2 months with a recommended default of 8 tries within 2 weeks, and a custom schedule of up to three retries. It also says Stripe does not retry when no payment method is available, on hard declines, or for India-issued cards. When recovery fails the subscription moves to canceled, unpaid, past due or paused, depending on your settings. On Stripe's pricing page the Billing section lists Smart Retries and recovery workflow automations, with a pay-as-you-go rate of 0.7% of Billing volume or a monthly plan from $620 on a one-year contract. No email tool does the retrying for you; a tool can only send the message.

Which Stripe event starts which sequence

The event names in this table are the ones in Stripe's subscription webhooks page. Day offsets and stop rules are suggestions for a monthly SaaS plan, not Stripe defaults, except where the table says Stripe sets the number.

Stripe event Sequence Day offsets Stops when
customer.subscription.created Welcome and first-task nudges Day 0 welcome; day 2 first task; day 5 invite a teammate Your app reports the activation event (Stripe cannot know it), or customer.subscription.deleted arrives
customer.subscription.trial_will_end Trial-ending notice: what you will be charged and when Stripe sends the event 3 days before the trial ends by default; email on the event (day -3) and again on day -1 only if no payment method is on file The customer cancels, or adds a payment method
invoice.payment_failed Payment-problem notices with a link to update the card Day 0; day 3; day 7; day 12 final warning (the recommended retry default is 8 tries in 2 weeks, so the last notice lands inside the window) invoice.paid for that invoice, or the subscription becomes canceled, unpaid or paused
invoice.paid Payment received; "you are back on track" only if a failure was open Day 0, once Not a sequence; its job is to end the dunning one
charge.refunded Refund confirmation, then pause promotions Day 0 confirmation; day 3 optional feedback question Partial refund of an active subscription: do not cancel anything, check the amount first
customer.subscription.deleted Cancellation confirmation, exit question, win-back Day 0 confirmation; day 3 one-question survey; day 30 win-back offer A new customer.subscription.created for the same Stripe customer

Notes on the three events people get wrong

Trial ending. Stripe's page says customer.subscription.trial_will_end is sent 3 days before the trial period ends, and that if the trial is shorter than 3 days the event is triggered immediately. Its trials page adds that the interval comes from the Trial ending events setting in the Dashboard and that Stripe-hosted reminder emails go out 7 days before the trial ends. The subscription-webhooks page suggests using the event to verify the customer has a payment method and, optionally, to notify them of the charge. For conversion-focused copy rather than plumbing, see sequence tools for B2B trial conversion.

Payment failed. The page lists notifying the customer, enabling Smart Retries and updating the default payment method as the actions to take. The Smart Retries page adds that the attempt_count on the invoice.payment_failed event says how many attempts have been made, and that after a hard decline retries stay scheduled but only run once a new payment method appears. So on a hard decline, waiting for day 3 wastes time: send the "update your card" email on day 0.

Invoice paid. Stripe's page says to provision access when you receive invoice.paid and the subscription status is active, and elsewhere to retrieve the subscription and confirm it is active before extending access, because a paid invoice does not always move the subscription to active. Apply the same caution to the email: fetch the subscription before you send "your plan is live".

Route three: the webhook endpoint, with code that matches Stripe's docs

If you write the endpoint yourself, Stripe's webhook documentation asks for four things: accept POST requests with a JSON payload, verify the request using the payload, the Stripe-Signature header and the whsec_ signing secret, return a 2xx quickly before any complex logic, and leave the raw request body untouched because any manipulation makes verification fail. The Ruby handler below is Stripe's own "verify with official libraries" example from that page; only the event cases are changed to this page's six events, and the comments in the cases are the docs' advice (log event IDs, process through a queue).

require 'stripe'
require 'sinatra'

# If you are testing your webhook locally with the Stripe CLI you
# can find the endpoint's secret by running `stripe listen`
# Otherwise, find your endpoint's secret in your webhook settings in
# the Developer Dashboard
endpoint_secret = 'whsec_...'

# Using the Sinatra framework
set :port, 4242

post '/my/webhook/url' do
  payload = request.body.read
  sig_header = request.env['HTTP_STRIPE_SIGNATURE']
  event = nil

  begin
    event = Stripe::Webhook.construct_event(
      payload, sig_header, endpoint_secret
    )
  rescue JSON::ParserError => e
    # Invalid payload
    puts "Error parsing payload: #{e.message}"
    status 400
    return
  rescue Stripe::SignatureVerificationError => e
    # Invalid signature
    puts "Error verifying webhook signature: #{e.message}"
    status 400
    return
  end

  # Before acting: skip event.id values you have already processed,
  # then enqueue a job and return 200 right away.

  # Handle the event
  case event.type
  when 'customer.subscription.created'
    subscription = event.data.object # contains a Stripe::Subscription
  when 'customer.subscription.trial_will_end'
    subscription = event.data.object # contains a Stripe::Subscription
  when 'invoice.payment_failed'
    invoice = event.data.object # contains a Stripe::Invoice
  when 'invoice.paid'
    invoice = event.data.object # contains a Stripe::Invoice
  when 'charge.refunded'
    charge = event.data.object # contains a Stripe::Charge
  when 'customer.subscription.deleted'
    subscription = event.data.object # contains a Stripe::Subscription
  else
    puts "Unhandled event type: #{event.type}"
  end

  status 200
end

Stripe's page also explains how to run this locally: stripe listen --forward-to localhost:4242/webhook forwards events from your account to your machine and prints the signing secret, and stripe trigger fires a sample event. Rules from the same page that decide whether the email side works:

  • Log event IDs. The docs say endpoints might receive the same event more than once and suggest logging processed event IDs. They add that two separate Event objects are sometimes generated for the same thing, and that the ID of data.object together with event.type identifies those.
  • Add a second guard on the send. Resend's idempotency docs say the Node.js SDK takes an idempotencyKey as the second argument, keys are 1 to 256 characters, a format like <event-type>/<entity-id> works, and keys are kept for 24 hours. A 24-hour key against Stripe's three-day retry window is why the event log stays the primary guard.
  • Subscribe narrowly. Stripe advises registering only the event types your integration needs. Do not subscribe an email-only endpoint to invoice.created; the next pitfall section explains why.

For the sender, Resend's pricing page lists a free plan at 3,000 emails a month with a 100-a-day limit and Pro at $20 a month for 50,000 emails; Postmark's pricing page lists Basic at $15 a month starting at 10,000 emails. Either way your code owns the unsubscribe and consent handling for anything marketing-flavoured; the split between receipt-style and promotional mail is covered in transactional vs marketing email.

Eight email tools that document a Stripe connection, ranked

The ranking is for a SaaS owner on Stripe Billing who wants the six events above to start sequences. Each entry says only what the vendor's own page states; where a page is silent, the entry says so. The matrix summarises what each documents for the six events.

Tool Subscription created Trial ending Payment failed Paid Refund Canceled
Loops Listed Listed Listed Listed Not listed (disputes only) Listed
Encharge Trigger Trigger, days before, at or after Past Due trigger New Stripe Payment trigger Not in its trigger list Trigger
Customer.io Any event you point a webhook at; the docs walk through customer.created and mention invoice.payment_failed
ActiveCampaign Listed Listed Listed, contact-level only Listed as invoice.payment_succeeded Listed Listed
Userlist Page names no events; docs say payments and plan updates show in user activity
Kit Subscriptions supported Not mentioned Not mentioned Purchase entry point Not supported Paid count drops
MailerLite Integration is for selling through MailerLite pages; the page describes no event sync
Mailchimp Syncs customers and orders; the help page lists no subscription events

1. Loops: the cleanest documented event list for a small SaaS

Loops' Stripe page describes an app you install from Stripe: open Settings, Stripe, click Connect to Stripe, then choose which events Loops receives. Its supported list includes customer.subscription.created, .paused, .resumed, .trial_will_end and .deleted, plus invoice.paid, invoice.payment_failed, invoice.upcoming, checkout-session events and dispute events. In a workflow you pick the trigger "Event received", choose Stripe, then the event. Contacts are matched on the Stripe customer's email address, and a new contact is created if the address is not found; the page adds that only events containing an email address can be processed.

The gaps are specific: no charge.refunded in the list, and no event property names, so the page does not say whether an invoice amount or attempt count reaches your email. Loops' pricing page lists a free plan with up to 4,000 sends in any rolling 30 days to your 1,000 newest contacts, and a paid plan whose slider reads $48 at 4,788 subscribers and $99 at 9,998. It fits a founder-run SaaS that wants the app-install route and can live without a refund trigger. Side-by-side detail is in Loops vs Resend and Customer.io vs Loops.

2. Encharge: the most billing-specific trigger list

Encharge's Stripe triggers page lists 12 triggers that each add a person to a flow: Trial Started, Trial Ends, Trial Converted, Trial Expired, Subscription Activated, Subscription Past Due ("payment failed"), Subscription Reactivated, Scheduled Subscription Cancellation, Subscription Canceled, Subscription Expanded, Subscription Contracted and New Stripe Payment. Trial Ends can fire X days before, at, or after the trial's end. The page warns that it runs no matter the customer's paying status, so a customer who already converted still enters the flow; its workaround is a Check Condition step on subscription status right after the trigger.

The overview article says you connect with a restricted API key (read access to charges, customers, events, checkout sessions, invoices, prices and subscriptions, write access for webhook endpoints), can import existing customers or skip that, and can connect a Stripe test-mode key first and swap in a live key afterwards. The trigger list has no refund entry. Encharge's pricing page lists Growth at $99 a month for up to 2,000 subscribers ($79 billed yearly), $179 at 5,000 and $249 at 10,000. It suits SaaS teams that want trial-aware triggers without webhook plumbing and have the budget for the 2,000-subscriber minimum.

3. Customer.io: maximum control, you map the fields

Customer.io's Stripe tutorial is webhook-based. You create an automation with a Webhook trigger, copy its URL, and add it in Stripe under Developers, Webhooks. The tutorial picks customer.created, matches the person by data.email and sets their ID to the Stripe customer ID, noting that most Stripe webhooks identify people by Stripe customer ID. It says the process adapts to dunning emails on invoice.payment_failed but does not walk through that case or document how invoice fields map into messages. That is both the appeal and the cost: you decide the payload handling yourself.

Customer.io's pricing page lists Essentials at $100 a month for 5,000 profiles and $145 for 10,000, with additional profiles at $0.009 each. Its billing docs say a profile counts for the month if it exists at any point in the period, even if later deleted, which matters when trial signups create many short-lived profiles. Fits teams with a product-event stream who want Stripe as one input among several; Userlist vs Customer.io covers the account-level alternative.

4. ActiveCampaign: broad event table, contact-level data

ActiveCampaign's help article lists the webhook events it syncs, among them charge.refunded, customer.subscription.created, customer.subscription.trial_will_end, customer.subscription.deleted, invoice.upcoming and invoice.payment_failed. Setup asks for your Stripe secret key, a resource (Charge, Customer, Subscription, Invoice or Checkout Session) and field mapping to existing ActiveCampaign fields; email is required and no new fields are created. Two limits for this page's purpose: Invoice events create or update contacts only, with no separate payment-failed tag, and payment-status filtering is supported only for the Subscription resource. Failed-payment sequences therefore need careful setup.

ActiveCampaign's pricing page shows annual-billing prices at 1,000 contacts of $15 for Starter, which caps automations at 5 actions, and $49 for Plus. If waits and condition checks count toward that cap, a four-email dunning flow will not fit on Starter, so confirm that in a trial before choosing it. Plus lists unlimited actions. It fits teams that also want a CRM and sales follow-up behind the billing data.

5. Userlist: account-aware, but verify the event list first

Userlist's billing integrations page lists Stripe beside Chargebee but names no events, fields or plan restriction. Its managing-users docs say payments and plan updates appear in a user's activity when the Stripe integration is set up, and warn that manual edits to integration-managed properties may be overwritten at the next sync. Its Failed Payment Recovery template is three messages (a first notice, an action-required note, a cancellation warning) but the page names no trigger event, no Stripe and no exit rule, so those are yours to build.

Userlist's pricing page lists Basic at $149 a month for up to 10,000 users, $10 per additional 1,000, and Professional at $349 for up to 10,000; its billing docs cap messages at 5 times tracked users, with a 500,000 floor. Fits B2B products where accounts, not individuals, are the unit; ask support for the event list before committing.

6. Kit: purchase-based, for digital products and creator subscriptions

Kit's Stripe article has you install the Stripe app from Apps, authorize it, then paste a Kit-provided webhook URL into Stripe's Developers, Webhooks area. In a Visual Automation you choose the Purchase entry point with Stripe as the integration, and add buyers to sequences or tags. It says subscriptions are supported, a canceled subscriber drops out of the paid count, and it "does NOT currently support refunds". Failed payments are not mentioned and the article does not say how buyers are matched to subscribers. The article also tells you to select all events for the webhook, which Stripe's docs advise against for your own endpoints, so check what Kit needs.

Kit's pricing page lists a free plan up to 10,000 subscribers without sequences or Visual Automations; Creator, which has them, is $33 a month at 1,000 subscribers on yearly billing, $75 at 5,000 and $116 at 10,000. Fits a creator selling a course or paid newsletter; not a trial-and-dunning SaaS flow.

7. MailerLite: sells through Stripe, no documented event sync

MailerLite's Stripe page describes selling digital products and subscription services such as paid newsletters through purchase blocks on landing pages and websites, one-time or recurring, with recurring purchases accepting only cards. It does not state that the native integration syncs existing Stripe customers or triggers automations, so it does not help a business whose checkout and Billing already live elsewhere. MailerLite's pricing page lists Comfort at $19 a month at 1,000 subscribers, $49 at 5,000 and $89 at 10,000 on monthly billing. Fits only if you sell through MailerLite.

8. Mailchimp: customers and orders, paid add-on, consent options

Mailchimp's help page says the integration syncs Stripe customers and orders to Mailchimp and is a paid integration billed through Data Mapper for Mailchimp, with the plan picked during setup and no price on the page. Its marketing-permission step offers double opt-in, transactional (synced as non-subscribed contacts) or subscribed (they receive marketing email automatically). The page lists no subscription or failed-payment events. Mailchimp's pricing page lists Standard from $20 a month at 500 contacts, $100 for 2,501 to 5,000 and $135 for 5,001 to 10,000, before the add-on. Fits a store or audience already on Mailchimp.

What each route costs at 1,000, 5,000 and 10,000 contacts

Assumptions: "contacts" means everyone in the tool, customers plus trial users; tool plans are the cheapest one that can run a multi-step sequence; billing basis is named per row. Route three is priced on sends, using a planning assumption of 2 billing emails per customer per month, so 2,000, 10,000 and 20,000 emails at the three sizes.

Option 1,000 5,000 10,000
Loops (monthly) Free plan $48 (read at 4,788 subscribers) $99 (read at 9,998)
Encharge Growth (monthly) $99 (smallest tier, up to 2,000) $179 $249
Customer.io Essentials (monthly) $100 (starting price covers 5,000 profiles) $100 $145
ActiveCampaign Plus (annual billing) $49 $145 $189
Userlist Basic $149 (covers up to 10,000 users) $149 $149
Kit Creator (yearly billing) $33 $75 $116
MailerLite Comfort (monthly) $19 $49 $89
Resend, your webhook (2 emails per customer) Free plan: 2,000 emails fit under 3,000 Pro $20: 10,000 fit under 50,000 Pro $20: 20,000 fit under 50,000
Postmark, your webhook (same volumes) $15 Basic (10,000-email stop) $15 Basic (10,000 sits on the stop) $55 Basic (next stop is 50,000)

Arithmetic worth checking. Customer.io: $100 for 5,000 profiles plus 5,000 extra profiles at $0.009 each gives $100 + (5,000 × $0.009) = $145, matching its 10,000-profile readout. Resend free: 2,000 emails over 30 days is about 67 a day, under the 100-a-day cap. Postmark's pricing page shows slider stops at 10,000 and 50,000 emails, so 20,000 emails is priced at the 50,000 stop rather than interpolated. Route three also costs developer time, which no row captures.

A sanity check against revenue, assuming your plan costs 29 dollars a month: Loops at 10,000 contacts is 99 divided by 29, about 3.4, so four recovered renewals a month cover it; ActiveCampaign Plus at 10,000 is 189 divided by 29, about 6.5, so seven. Stripe's own fees apply on top of every route: its pricing page lists 2.9% + 30¢ per successful domestic card transaction and the Billing rates above.

Six ways Stripe email setups go wrong

Duplicate deliveries turn into duplicate emails

Stripe's webhook docs say an endpoint can receive the same event more than once, and that Stripe retries live-mode events for up to three days with exponential back-off. Log processed event IDs before sending, and key the send on the event or invoice ID. A vendor's native integration should handle this for you, but the docs for the tools above do not say how, so a test with a replayed event is cheap insurance. Replays are easy to trigger: the same page says the Dashboard's Resend button works for up to 15 days after an event is created, and the CLI's stripe events resend for up to 30 days, and that a manual resend does not cancel Stripe's automatic retries.

Events arrive out of order

Stripe says it does not guarantee the order of delivery and gives the example of a new subscription generating customer.subscription.created, invoice.created, invoice.paid and charge.created. It also says not to use the created timestamp to order events because distinct events can share a second. A welcome flow that waits for "paid" can therefore see the paid event before the created event. Fetch the object from the API when the state matters.

A slow endpoint can delay invoices

The subscription-webhooks page says that if Stripe fails to receive a successful response to invoice.created, finalizing all invoices with automatic collection is delayed for up to 72 hours, and that this covers every endpoint on your account, including a third-party service having trouble. ActiveCampaign's article lists invoice.created among the events it syncs. Open Workbench's webhook list and check which of your endpoints, native or custom, subscribe to it; an email-only endpoint should not.

Test mode and live mode are different worlds

Stripe's webhook docs say that if one endpoint serves both test and live keys, its signing secret differs for each. Its testing page says sandboxes do not email customers by default, and that API objects in one environment are not accessible from the other. Retry behaviour differs too: live events retry for up to three days, sandbox events three times over a few hours. Vendors differ: Encharge documents a test-mode key, ActiveCampaign's setup asks for the live secret key, and Loops' page says nothing on test mode.

The Stripe customer's email is not your user's identity

Loops matches contacts by the Stripe customer's email and creates a new contact when it does not find the address, so a customer who pays with a billing address differing from their signup address becomes a second contact with the wrong history. Customer.io's tutorial stores the Stripe customer ID as the person's ID, which survives an email change. For your own endpoint, Stripe's metadata API field lets you carry your own user ID on customers and invoices, and its automations page filters on customer and invoice metadata.

Double dunning from Stripe and your tool

Stripe emails after each failed payment when that setting is on. At the recommended default of 8 tries within 2 weeks, a card that fails every time can produce about eight Stripe emails; add a four-email sequence from your tool on invoice.payment_failed and the customer could receive about twelve in a fortnight. Choose one owner: either Stripe sends the per-failure notice and your tool adds only the day-12 final warning and the win-back, or you switch the Stripe email off and your tool runs the whole sequence. Receipts follow the same logic, since Stripe's receipt toggle already sends one on every successful payment; do not rebuild it unless you need different copy. For the broader timing question see post-purchase education sequences for SaaS.

Frequently asked questions

Does Stripe send emails to my customers by itself?

Yes, if you switch the emails on. Stripe's customer-emails page lists failed-payment emails (sent after each failed payment), a trial-ending reminder 7 days before a free trial ends, renewal reminders, expiring-card notices one month ahead, and payment confirmations. Receipts for successful payments and refunds are a separate switch under Settings, Business, Customer emails. In a sandbox Stripe does not email customers by default, so test with an address on your verified domain or a team member's address.

Which Stripe events should start an email sequence?

For subscription businesses the working set is customer.subscription.created, customer.subscription.trial_will_end, invoice.payment_failed, invoice.paid, charge.refunded and customer.subscription.deleted. Stripe's subscription-webhooks page describes each of them, including that trial_will_end is sent 3 days before a trial ends by default. Subscribe an endpoint only to the events you use; Stripe's webhook docs advise against listening to everything.

Does my email tool retry failed payments?

No. Retries are a Stripe Billing feature: Stripe's Smart Retries page describes retry timing, with a recommended default of 8 tries within 2 weeks, and what happens to the subscription when retries run out. An email tool or your own code can send dunning emails when invoice.payment_failed arrives, but the charge attempts themselves stay inside Stripe. Decide whether Stripe or your tool sends the emails so customers do not get both.

Do I still need my own webhook if my email tool has a Stripe integration?

Only for the gaps. Loops lists a fixed set of Stripe events that does not include charge.refunded, and Kit's help article says it does not support refunds, so a refund-triggered email needs another path such as Stripe's own refund receipts or a small endpoint of your own. Check the vendor's event list against the six events on this page before you decide.

How do I stop duplicate emails when Stripe delivers an event twice?

Stripe's webhook docs say an endpoint can receive the same event more than once and recommend logging the event IDs you have processed and skipping repeats. Stripe retries undelivered live-mode events for up to three days, while Resend keeps idempotency keys for 24 hours, so a key on the email send is a second guard rather than a replacement for your own event log.