switch block in app/routes/webhook.ts.
Handled events
invoice.paid
invoice.paid
When it fires: Stripe successfully collects payment for an invoice. This occurs at the start of each billing period for active subscriptions, or immediately after a customer completes checkout.Triggered by: Automatic billing cycle or a customer completing payment.What to do: Provision or renew the customer’s access to your product. After this event, the subscription status is
active.Always confirm access using
invoice.paid rather than relying solely on the checkout session completion event. invoice.paid fires on every renewal, keeping long-lived subscriptions in sync.invoice.payment_failed
invoice.payment_failed
When it fires: A payment attempt fails because the card is declined, expired, or no valid payment method is on file. Stripe will retry according to your retry schedule.Triggered by: Automatic billing cycle — not a direct user action.What to do: Notify the customer that their payment failed and prompt them to update their payment method. After this event, the subscription status becomes
past_due.customer.subscription.deleted
customer.subscription.deleted
When it fires: A subscription is cancelled — either at the end of the billing period (scheduled cancellation) or immediately.Triggered by: A user-initiated cancellation request or automatic cancellation by Stripe after all payment retries fail. Use
event.request to tell them apart:event.request !== null— cancelled by an API request (user or your app)event.request === null— cancelled automatically by Stripe
Event summary
| Event | Subscription status after | Triggered by | Action |
|---|---|---|---|
invoice.paid | active | Automatic / checkout | Provision access |
invoice.payment_failed | past_due | Automatic | Notify customer |
customer.subscription.deleted | canceled | User request or automatic | Revoke access |