Answers · Stripe

How do I find Stripe subscriptions still active after a failed payment, or with expiring cards?

Ask the Subscriptions API for status=past_due and status=unpaid: those are subscriptions whose latest invoice failed or was never paid, and Stripe keeps creating invoices for them. Then expand each active subscription's default payment method and compare card.exp_month and card.exp_year with the current month. Finally, check that your app's access matches: a customer on an unpaid subscription should no longer have it.

One trap: active does not guarantee every invoice is paid. With Stripe's default "most recent invoice" status setting, older invoices can stay open while the subscription reads active.

Find subscriptions behind on payment

Use a restricted key with read access to Subscriptions and Invoices. Nothing here writes.

  1. Past due: the latest finalized invoice failed or wasn't attempted.

    curl -G https://api.stripe.com/v1/subscriptions \
      -u "$STRIPE_KEY:" -d status=past_due -d limit=100
  2. Unpaid: retries are over and the subscription stays in place without collecting. Stripe's guidance is to revoke access here.

    curl -G https://api.stripe.com/v1/subscriptions \
      -u "$STRIPE_KEY:" -d status=unpaid -d limit=100
  3. Open invoices, including ones sitting under subscriptions that read active:

    curl -G https://api.stripe.com/v1/invoices \
      -u "$STRIPE_KEY:" -d status=open -d limit=100

    Lists return at most 100 objects per page. If has_more is true, repeat with starting_after=<last id>.

Find cards about to expire

  1. Expand the default payment method on active subscriptions and print the expiry:

    curl -sG https://api.stripe.com/v1/subscriptions \
      -u "$STRIPE_KEY:" -d status=active -d limit=100 \
      -d "expand[]=data.default_payment_method" |
    jq -r '.data[] | [.id,
      .default_payment_method.card.exp_month,
      .default_payment_method.card.exp_year] | @tsv'

    An empty expiry means the subscription has no payment method of its own and charges the customer's default (invoice_settings.default_payment_method on the Customer), so check that one instead.

  2. In the Dashboard, under subscription and email settings, turn on "Send emails about expiring cards" (sent a month before the default card expires) and "Send emails when card payments fail". Both link to a page where the customer can update their card.

Then make access match payment

  • Check your failed-payment settings: after the final retry, a subscription is cancelled, marked unpaid, or left past_due. Know which one you chose.
  • If your app only revokes access on cancellation, unpaid customers keep using it for free. If it revokes on the first invoice.payment_failed, you cut off customers that Smart Retries might still have collected from.
  • Verify webhook signatures on the handler that does this. Access decisions shouldn't be driven by unsigned requests.

Stripe Leak Check · $29

Rather not run it by hand?

Stripe Leak Check covers this in one read-only scan you run on your own machine (16 checks in all): past-due subscriptions, failed invoices and retries, involuntary churn, cards about to expire, and access that doesn't match payment, each with the numbers and a Look up / Fix / Confirm checklist.

Checked against Stripe: How subscriptions work, Stripe: List subscriptions, Stripe: Automate customer emails on 2026-10-23. Only test apps and accounts you own or are allowed to test.