# Subscription Statuses and Webhooks — Stripe Payments

Source: https://www.skillbyai.com/en/stripe-payments/s-lifecycle

> Trialing, active, past_due and canceled.

## Statuses that drive access

Key subscription statuses: **incomplete** (the first payment has not succeeded yet), **trialing** (in a free trial), **active** (paid and in good standing), **past_due** (a renewal payment failed and Stripe is retrying according to your retry settings), **unpaid** or **canceled** (depending on your settings once retries are exhausted, or after cancellation), and **paused**. Your app should grant access from the status stored in your database and update it from webhooks: `customer.subscription.created`, `customer.subscription.updated` and `customer.subscription.deleted` for state, `invoice.paid` to confirm renewals, `invoice.payment_failed` to warn the customer, and `customer.subscription.trial_will_end`, sent a few days before a trial ends.

## Syncing subscription state

A webhook handler fragment.

```javascript
switch (event.type) {
  case 'customer.subscription.created':
  case 'customer.subscription.updated':
  case 'customer.subscription.deleted': {
    const sub = event.data.object;
    await db.subscriptions.upsert({
      stripeSubscriptionId: sub.id,
      stripeCustomerId: sub.customer,
      status: sub.status,              // trialing, active, past_due, canceled, ...
      cancelAtPeriodEnd: sub.cancel_at_period_end,
    });
    break;
  }
  case 'invoice.payment_failed':
    await emailUpdatePaymentMethod(event.data.object.customer);
    break;
}

// access check elsewhere in the app
const hasAccess = ['active', 'trialing'].includes(subscription.status);

```

## Decide your past_due policy

Choose whether past_due users keep access during retries (friendlier) or lose it immediately (stricter), and configure retries and dunning emails in the Dashboard; check the docs for your account's options.

**Quiz:** A renewal payment fails and Stripe is retrying. What status does the subscription usually have?

- [ ] active
- [ ] trialing
- [ ] incomplete_expired
- [x] past_due

*Answer:* past_due. past_due signals a failed renewal under retry.
