## TL;DR

Renewal: extend access, reset usage counters, send the receipt.

## Steps

1. Match the invoice to your subscription via `data.object.subscription`, then to your user.
2. Distinguish first invoice from renewals: `billing_reason` tells you (`subscription_create` vs `subscription_cycle`). First payment: provision the account. Renewal: extend access, reset usage counters, send the receipt.
3. Dedupe by invoice id. Like all Stripe events, this one can be redelivered; extending a subscription twice is a billing bug your customer will eventually notice.
4. Return 200.

## When to use

You are seeing this: For subscription and recurring flows, this is the moment that proves money moved, the equivalent of payment\_intent.succeeded for one-off charges. Use this skill when you run into "Stripe event: invoice.payment_succeeded, this is when subscription money actually moves".

## When not to use

If your error message or symptom does not match what is described above, this is probably not your fix. Search for your exact error text instead of forcing this one to fit.

## Versions

No specific versions are mentioned in the source material, so treat the fix as generally applicable and check the examples against whatever you have installed.

## Why this happens

The original report does not dig into a root cause. It documents the symptom and the fix that resolved it.
