Stripe checkout.session.expired: email people who left checkout
Stripe fires checkout.session.expired when somebody leaves a Checkout page unpaid. When it arrives, who you may email, and what to say.
The short answer
When somebody opens your Stripe Checkout page and leaves without paying, the session expires and Stripe sends an event called checkout.session.expired. You can follow it with a short email, but only to people who agreed to hear from you, and it should read like a person checking in rather than a reminder from a shop.
When Stripe sends it
A Checkout Session expires 24 hours after you create it, unless you set expires_at to something shorter (Stripe allows 30 minutes to 24 hours). When it expires unpaid, checkout.session.expired arrives. So the email goes out a day later by default, which suits most products: soon enough to remember, late enough not to feel watched.
Who you may email
This is the part to get right. Somebody who reached your checkout gave you an email address so they could pay, not so you could market to them. Stripe's own guide to recovering abandoned carts has you collect consent to promotional email on the checkout page first, with consent_collection, and email only the people who agreed. The session then carries what they chose in consent.promotions.
If you don't collect that consent, don't send the email. A sale isn't worth a spam complaint, and the rules where your customers live may say the same.
Your own webhook
- Create your Checkout Sessions with
consent_collection: { promotions: "auto" }, and withafter_expiration: { recovery: { enabled: true } }if you want Stripe to give you a link that reopens the same cart. - Add a webhook endpoint that listens for
checkout.session.expired, and check theStripe-Signatureon every request. - Return a 2xx fast and send the email after. Keep the event ids you have handled, because an event can arrive twice.
const event = stripe.webhooks.constructEvent(rawBody, signature, endpointSecret);
if (event.type === "checkout.session.expired") {
const session = event.data.object;
if (session.consent?.promotions === "opt_in" && session.customer_details?.email) {
// session.after_expiration?.recovery?.url reopens the same cart
// session.amount_total is what they were about to spend
}
}
With Kicklace
- Go to Settings → Connections → Stripe → Connect, and paste one restricted key. Kicklace adds its own webhook to your Stripe account and keeps the secret Stripe hands back.
- Stripe's
checkout.session.expirednow lands in Kicklace as a checkout left, with what they were about to spend, on the person with that email. - On your Lifecycle map, add a side road that starts from it, and write the email, or let Kicklace write it from your site.
- Switch it on only once you collect consent at checkout. First Kicklace shows who would have got it over the last 30 days.
Kicklace only reads Stripe. Payments from Stripe lists every event it hears, and the demo shows the map on your own site with no sign-up.
What the email should say
One short note, from you, that asks rather than pushes.
Subject: Anything I can help with?
Hi {{first_name}},
I saw you got as far as checkout for [your app] yesterday and didn't finish. If something got in the way, like a question about the plan or a payment that didn't work, reply to this email and I'll sort it out.
If you want to pick up where you left off: [link]
[Your name]
Send one. A second one about the same cart is where a check-in turns into chasing.
FAQ
Can I email somebody who abandoned checkout without consent?
Treat it as no. They gave you their address to pay, and Stripe's own recovery guide has you ask for consent first.
Does Stripe send an abandoned cart email itself?
Stripe gives you the event, the consent and a recovery link, and the email is yours to send.
What about people who never reached checkout?
That's somebody who signed up and stopped short of paying, a different email. See activation emails.
Free up to 1,000 contacts.