Skip to content
FeaturesPricingAffiliateBlogHelpAboutContact
Get StartedSign In
Back to Blog
industry2026-05-2312 min read

My subscription renewed today, I meant to cancel — no 7-day warning, invoice.upcoming handler missing (PR #651 VII F5)

Niamh (41) runs Brunel Coffee Bar 24-cover specialty coffee + brunch spot in Bristol Stokes Croft. 3 months ago upgraded to thMenu Diamond for Hotel Room Service for planned upstairs short-stays. Conversion didn t happen yet. Multiple times meant to downgrade to Platinum (save £40/month), forgot. Today bank Apple Wallet buzzed "£99 — THMENU." Niamh emailed support: "Why no renewal reminder?" Support 2 wrong theories busted (Niamh missed it, spam folder). Third theory correct: thMenu didn t send 7-day reminders — invoice.upcoming switch case MISSING. Webhook handler apps/web-admin/src/app/api/stripe/webhook/route.ts switch event.type had checkout.session.completed + customer.subscription.updated + customer.subscription.deleted + invoice.paid + charge.dispute.created, but invoice.upcoming + paused/resumed + payment_action_required + payment_failed missing. invoice.upcoming fell to default branch silent 200 OK → Stripe Dashboard showed "delivered" → no downstream automation. Pattern: webhook handler from 2024 against Stripe API surface at that time. Customer Portal added features (pause/resume, pending plan change, invoice.upcoming) afterwards. Handler incremental updates didn t pick them up automatically. **PR #651 batch VII F5** two-layer fix: (1) switch case invoice.upcoming branch — InvoiceUpcomingSchema parse + Supabase user mapping + sendInvoiceUpcomingReminder. (2) Resend locale-aware template (EN + TR + DE + FR + IT + ES) — subject "Brunel Coffee Bar — your subscription renews in 7 days at £99 [Manage Subscription]" + idempotency column user_profiles.invoice_upcoming_email_sent_at prevents duplicate reminders if Stripe re-delivers. Niamh £40 credit + downgrade scheduled. A month later first invoice.upcoming email arrived; she acknowledged, kept Platinum, smooth renewal. Pattern: Stripe webhook handlers must explicitly handle every event type in modern Customer Portal lifecycle — customer.subscription.created/updated/deleted + paused/resumed + trial_will_end + pending_update_applied/expired + invoice.upcoming + invoice.payment_action_required + invoice.payment_failed + charge.dispute.created + radar.early_fraud_warning.created + payment_intent.payment_failed. Default branch should emit "unhandled_event" warning to Sentry, not silent 200 OK — surfaces coverage gaps loudly.

th

thMenu Team

thmenu.com

Found this helpful? Share it.