If you want to understand Stripe at a deep, almost medical level, you must understand invoices and payment intents. These two objects form the cardiovascular system of Stripe billing. Subscriptions, Checkout, and payment methods are important—but invoices and payment intents are the machinery that actually moves money through the system.
Without a clear mental model for how these two interact, developers often misinterpret errors, grant access too early, or chase down mysterious “payment failed” bugs that turn out to be completely predictable once you understand the underlying process.
This article is your calm, readable tour of Stripe’s billing engine, written in a way that even a screen reader can read aloud like a financial bedtime story.
In Stripe, money does not magically transfer from customer to business. A subscription does not charge on its own. A Checkout session does not finalize the billing state.
Instead, Stripe relies on invoices.
An invoice represents a financial obligation. It states:
It’s not just a PDF or an email receipt. It’s the actual brain of the billing system.
Invoices are created for:
Every meaningful action that involves charging a customer eventually turns into an invoice.
Here’s the true lifecycle, stripped of jargon:
Stripe is preparing the invoice. Nothing has been attempted yet.
Stripe says, “This invoice must now be paid.” A payment intent is created.
The charge succeeded. Money moved. Stripe is pleased.
Stripe attempted payment, but it failed. You have entered the realm of retries and bank mysteries.
The invoice is not going to be paid. You either gave up or cancelled it intentionally.
This lifecycle is critical for understanding how access control should be updated. Most developers ignore these states—and then wonder why customers have access when their card failed two weeks ago.
If invoices are the brain, payment intents are the hands.
A payment intent is:
A single invoice may reference a single payment intent, which can have multiple attempts depending on fallback or authentication.
requires_payment_methodrequires_confirmationrequires_actionprocessingsucceededcanceledMost billing bugs arise because developers assume a payment intent becomes succeeded immediately. In reality, it might require hours, retries, or customer intervention.
Stripe subscriptions do not charge customers directly.
They merely schedule invoices.
At every billing interval:
This is why you should never trust subscription status without confirming the invoice events.
Even non-financial events like upgrading mid-cycle depend on invoices.
For example:
Stripe prorates the remaining time and generates an immediate invoice for the difference.
Stripe modifies future invoices, and may produce prorated credits.
Stripe creates the first invoice and attempts payment.
The invoice is always the authoritative source of truth for whether money was collected, scheduled, or declined.
A common mistake:
“The subscription object says active, so the user gets access!”
Unfortunately, subscriptions can be “active” even when the invoice fails.
This usually happens during:
The correct approach is:
invoice.paid: grant accessinvoice.payment_failed: restrict accesscustomer.subscription.deleted: remove accessThis prevents the infamous “free premium plan” bug.
Stripe uses webhooks to announce the financial outcome of invoices and payment intents.
The most important events are:
invoice.paidinvoice.payment_failedpayment_intent.succeededpayment_intent.payment_failedinvoice.finalizedIf you ignore these webhooks—or process them incorrectly—your billing system will be permanently confused.
Let’s walk through what actually happens, step by step.
succeeded.paid.invoice.paid webhook.Only the last step is your responsibility.
Stripe handles the financial machinery.
Now the other scenario:
past_due.invoice.payment_failed.If the customer updates their card:
invoice.paid.Billing becomes predictable when you anchor everything on invoices and payment intents.
Invoices and payment intents are the beating heart of Stripe’s system. They are the definitive record of what the customer owes and whether money was successfully collected.
Once you understand:
Stripe becomes dramatically easier to reason about.
Most teams try to understand billing by staring at subscriptions.
Professionals understand billing by following the invoices.
If you grasp this principle, the rest of Stripe billing will fall neatly into place, and your system will become stable, predictable, and refreshingly uneventful—exactly what a billing system should be.