ExplainerOctober 31, 2026·16 min read

Stripe Invoice Statuses Explained: draft, open, paid, void and uncollectible (2026)

Sinh Yang

Sinh Yang

Founder of Revova

Five Stripe invoice statuses: draft leads to open, which leads to paid, void or uncollectible, with a loop on open for failed payments

A Stripe invoice has exactly five statuses: draft, open, paid, void and uncollectible. A subscription charge creates a draft, Stripe finalizes it to open, and a successful payment makes it paid. The surprise for most developers is what is missing: there is no "failed" status. When a payment fails, the invoice simply stays open, and the subscription is what changes.

That one fact explains most of the confusion around failed payments in Stripe. A dashboard that says an invoice is "Past due" or "Retrying" is showing a label, not a status. A webhook handler that waits for an invoice to turn failed will wait forever. And a bookkeeper who marks an invoice uncollectible may not know the customer can still pay it. This guide goes through each status using Stripe's invoicing and subscription documentation (read on 31 October 2026), shows the transitions and events, explains what a failure does and does not change, and ends with rules for using invoice status in recovery. It is the companion to our guide to subscription statuses: subscriptions describe the relationship, invoices describe the money.

Key takeaways

  • Stripe invoices have five statuses: draft, open, paid, void, uncollectible. Failed is not one of them; a failed charge leaves the invoice open.
  • "Past due" and "Retrying" are Dashboard badges on open invoices. The subscription is the object that becomes past_due.
  • Void cancels an invoice for good. Uncollectible writes it off but can still be paid later.
  • Drive access from the subscription and invoice.paid, drive recovery from the open invoice, and stop recovery the moment it is paid.
5
Invoice statuses: draft, open, paid, void, uncollectible
≈ 1 hour
How long a renewal invoice sits in draft before Stripe finalizes it
72 hours
Longest finalization delay when your webhooks do not respond

What are the five Stripe invoice statuses?

Every invoice, whether created by a subscription or by hand, is in exactly one of these statuses, and the status decides what you are allowed to do next.

StatusWhat it meansWhat you can do
draftNot ready to use. Every invoice starts hereEdit almost anything; finalize it to make it open; delete it unless it belongs to a subscription
openFinalized and awaiting paymentSend it, edit only a few fields, mark it paid, void or uncollectible; Stripe may charge it automatically
paidPayment receivedTreat as final in practice; Stripe lists detaching payments as the way back to open
voidCanceled. Still viewable by invoice numberNothing. It is terminal
uncollectibleCustomer unlikely to pay; typically treated as bad debtMove to void or paid

Stripe describes paid as a terminal status in one place and lists unapplying payments as a way to turn a paid invoice back into open in another. In day-to-day billing treat paid as final; if you ever see an invoice reopen, a payment was detached from it by someone with Dashboard or API access.

A handwritten merchant invoice from a market dated 1901 listing items and prices in a column with a total at the bottom
An invoice in its simplest form: a list of what is owed and a total. Stripe adds a status to every one. Photo: California Market invoice, Seattle, 19 August 1901 (MOHAI), public domain, via Wikimedia Commons.

How does an invoice move from draft to paid?

For a subscription renewal the path is mechanical, and knowing the timing helps you debug it. When the billing period ends Stripe creates the invoice and you receive an invoice.created event with the status draft. Stripe leaves it in draft for about an hour, which gives your code a window to add invoice items, then finalizes it, which sets the status to open, and attempts to charge the default payment method. If the charge works, the invoice becomes paid and you get invoice.paid.

Invoice lifecycle: draft, finalized to open, then paid on success; on failure the invoice stays open, retries run, and it ends as paid, void or uncollectible
Invoice statuses and the events between them. The failure loop sits inside open: there is no failed status.

Two timing details cause real incidents. First, the attempted field is false until one hour after invoice.created, so a dashboard that shows "unpaid" for every open invoice will alarm customers in the first hour of every renewal. Second, Stripe waits for a successful response to invoice.created from every webhook endpoint before it attempts payment; if no endpoint answers properly, finalization of invoices on automatic collection is delayed for up to 72 hours, and Stripe retries the webhook for up to three days with exponential back-off in live mode. A broken endpoint can postpone your revenue, not just your notifications. We cover how to catch that in why missed webhooks quietly cost revenue.

What happens to an invoice when the payment fails?

Nothing happens to its status. The invoice stays open, paid is false, and Stripe sends invoice.payment_failed, along with an invoice.updated event. What changes is the bookkeeping fields. attempt_count goes up (any attempt counts as the first and afterwards only automatic retries increment it), next_payment_attempt holds the date of the next scheduled try, and the Dashboard may decorate the open invoice with a Past due or Retrying badge.

Stripe's own description of attempt_count includes a detail worth knowing: if a failure returns a non-retryable code, the invoice can no longer be retried until a new payment method is obtained. Retries stay scheduled and the count keeps rising, but they run only after a new method arrives. That is why a customer who updates a card unlocks the retries again; see how this plays out in letting customers update a failed payment method, and in how Smart Retries decides when to try again.

Invoice status versus subscription status after a failure

Failure does not move the invoice, but it does move the subscription: the latest invoice failing makes the subscription past_due. When retries end, your failed-payment setting chooses between cancel, unpaid and leaving it past_due. If you pick unpaid, Stripe stops collecting but keeps creating invoices, which stay in draft. A pile of draft invoices on an unpaid subscription is expected, not a bug. See the subscription statuses guide for the other half.

What do "Past due" and "Retrying" mean in the Dashboard?

They are display badges on an invoice whose status is open. Stripe's documentation says so directly: in the Dashboard an open invoice can show a different badge, such as Past due or Retrying, and in some cases hovering over it gives an explanatory tooltip. A non-subscription invoice with a payment that has been initiated but is still pending shows a Pending badge in the list, while its detail page still says Open. None of this appears in the API as a status. If you build your own admin screen and want the same labels, derive them from the fields: an open invoice with a past due date, or with a next payment attempt scheduled, or with an attempt in flight.

This matters when a support person tells you "the invoice is failed" and your query for status equals failed returns nothing. The question to ask instead is: which open invoices have attempt_count above zero and paid false? That is the working definition of a failed payment in Stripe, and it is the one recovery tools use.

Does the collection method change the lifecycle?

Yes, in what happens after an invoice is finalized. Each invoice has a collection_method of either charge_automatically or send_invoice, and the two behave differently when a payment is due:

charge_automaticallysend_invoice
After finalizationStripe charges the default payment method on fileStripe emails the invoice with payment instructions (if finalized-invoice emails are on)
If payment failsInvoice stays open; retries run on your Smart Retries or custom schedule; invoice.payment_failed firesThe invoice stays open until paid; reminders can be sent before, on or after the due date
What makes a subscription past_dueThe latest invoice failing or not being attemptedThe invoice passing its due date unpaid
Hosted update link in Stripe emailsIncluded when you use the link to a Stripe-hosted pageNot included for subscriptions set to manually send an invoice
Typical customersSelf-serve SaaS paying by cardLarger accounts that pay by bank transfer or purchase order

If you run a mix, your failed-payment tooling has to treat the two differently. Dunning for a card is about a charge that bounced; dunning for a send-invoice customer is a conventional payables reminder, with a due date and a payment link. Stripe's automatic reminders for unpaid invoices work off a schedule you set relative to the due date, and Stripe skips a reminder if a payment is already processing, to avoid confusing the customer.

The hosted invoice page

Finalizing an invoice also creates a unique URL where someone can pay it, plus a link to download a PDF. That hosted invoice page is the quickest recovery path for a single invoice: the customer sees the amount, enters or selects a payment method, and the invoice moves to paid. It remains available after you void an invoice, but then displays a message that the invoice has been voided. If you only need to recover one open invoice, a recovery email can link straight to the hosted page. If the real problem is a dead default card, a link to the portal flow in our customer portal guide fixes future invoices as well.

How do you debug a customer who says they paid but is still flagged?

Work from the invoice outwards. Support tickets like this are almost always one of five things, and the invoice object answers most of them in a couple of minutes:

  1. Read the invoice status and amount_remaining. If the status is paid, the money arrived and your own database is stale. Check that your handler for invoice.paid ran and returned a success code.
  2. If the invoice is still open, read attempt_count and next_payment_attempt. A positive count with a future attempt date means Stripe is waiting for its schedule; the customer's payment may have gone to a different invoice.
  3. Check for several open invoices. A customer can fix this month's invoice and still have last month's open. Which one determines status depends on your most recent invoice or all invoices setting, described in the subscription guide.
  4. Check which payment method was tried. If the invoice used a subscription-level default and the customer updated the customer-level one, the retry will keep failing on the old card.
  5. Check the webhook delivery log. If Stripe could not reach your endpoint, your database never heard about the payment. Replay the event after you fix the endpoint.

That checklist is also a good template for an internal runbook. Write it down once, and the next "I paid but it still says overdue" ticket takes five minutes instead of fifty.

Reproduce it safely before you touch live data

You rarely need to wait a month to watch a renewal fail. In a Stripe sandbox, create a customer with a test card that is declined on charge, attach it to a subscription, and advance time with a test clock (the invoice object even carries a test_clock field so you can tell which invoices belong to one). Walk the invoice through draft, open and a failed attempt, and watch which events arrive and in what order. Then repeat with a card that succeeds, so you see the paid path too. An afternoon of this teaches more about the lifecycle than any diagram, and it gives you fixtures for the tests that keep your webhook handler honest.

Which webhook fires for which transition?

Stripe's transition table pairs each API action with the event it emits and the resulting status. Add the automatic events from the subscription webhook guide and you have the full map:

What happenedEvent you receiveInvoice status afterwards
Renewal invoice createdinvoice.createddraft
Draft finalizedinvoice.finalizedopen
Finalization fails (for example a tax location is missing)invoice.finalization_faileddraft
Payment succeedsinvoice.paid (and invoice.payment_succeeded if a PaymentIntent paid it)paid
Payment failsinvoice.payment_failed, invoice.updatedopen
Customer must authenticate (3D Secure)invoice.payment_action_requiredopen
Invoice sent to the customerinvoice.sentopen
Marked uncollectibleinvoice.marked_uncollectibleuncollectible
Voidedinvoice.voidedvoid
Draft deletedinvoice.deleted(deleted)
A few days before renewalinvoice.upcomingno invoice yet

Authentication failures belong in their own bucket: the PaymentIntent needs action, not a retry. Read SCA and 3D Secure explained if you see many invoice.payment_action_required events. For every event, verify the webhook signature on the raw body before you act on it, and make handlers idempotent, because Stripe can deliver an event more than once.

When should an invoice be marked uncollectible?

When you have concluded that you will not be paid but you want the debt on record. Stripe's example is a customer who has declared bankruptcy after you delivered $1,000 of service: you write the invoice off as unlikely to be paid, mark it uncollectible and keep the amount for your bad-debt accounting. There is a Dashboard route (Change invoice status, then Uncollectible) and an API endpoint that emits invoice.marked_uncollectible. You can also tell Stripe to mark a past-due invoice uncollectible automatically after 30, 60 or 90 days, or leave it past due.

The point most people miss is that uncollectible is reversible in one direction. The transition table lists the pay endpoint as valid on an uncollectible invoice: if the attempt succeeds the invoice goes to paid and you receive invoice.paid; if it fails the invoice stays uncollectible and you receive invoice.payment_failed. You can also move it to void. So a write-off does not close the door on a customer who returns with a working card.

Void or uncollectible? A quick test

Ask whether the invoice should have existed. If it was issued in error, a duplicate, or the wrong amount, void it (and issue a credit note or a corrected invoice if your jurisdiction requires one). If it was a valid charge and the customer simply is not paying, mark it uncollectible so the debt stays visible, and keep the option of a later payment.
A 1936 electricity bill with a diagonal PAID stamp over the amount due and meter readings in a table
A bill with a PAID stamp, the paper ancestor of the paid status. Photo: Auric, Maritime Electric Co. bill (1 September 1936), CC BY-SA 3.0, via Wikimedia Commons.

What does voiding an invoice do, and what does it do to the subscription?

Voiding cancels an invoice permanently while keeping a paper trail. The invoice can still be looked up by number, its hosted page still loads with a message that it was voided, and it counts as zero value for reporting. You can only void an open or uncollectible invoice, and the status is terminal. Stripe also warns that regulations in your jurisdiction may require a credit note or a replacement invoice instead of a void, and recommends legal advice for your business.

For subscription invoices, voiding can change the subscription's status, which is where surprises come from. Stripe documents these rules:

  • Voiding the first invoice: if the subscription is incomplete, it becomes incomplete_expired; if it is past_due, it becomes active; if it is active, it does not change.
  • Voiding the most recent invoice of an active subscription (not the first): Stripe walks back from the newest invoice to the oldest until a condition is met. A paid or uncollectible invoice makes the subscription active. An automatic-collection invoice whose dunning stopped because of retry limits sets the status to canceled, unpaid or past_due according to your settings. A send-invoice invoice past its due date sets it to past_due. With no match, the subscription becomes active.

The practical consequence: voiding the failing invoice of a past_due subscription is a quick way to put the customer back into good standing, and a quick way to give a month away by accident. If you want to forgive one charge but keep billing, void deliberately and check the status that results.

Paid means the amount due has been settled, and the event to trust is invoice.paid. Stripe says you can provision access to your product when you receive it and the subscription status is active. Do not key access on invoice.payment_succeeded, because that event appears only when an invoice-related PaymentIntent is created and completes successfully. An invoice can become paid without one: when it relates to a trial or free subscription, when the amount due is covered by the customer's credit balance or is below the minimum charge, or when you mark it paid out of band. In those cases you receive invoice.paid and no invoice.payment_succeeded.

Out-of-band payment is a useful escape hatch for recovery too. A customer who sends a bank transfer after a dunning email can be marked paid in the Dashboard (Change invoice status, then Paid) or with the paid_out_of_band parameter on the pay endpoint, which closes the invoice without a charge.

A 1944 telegraph company receipt with a circular postmark, rubber stamps and handwritten amounts
A receipt with rubber stamps: proof of payment has always been about a trustworthy record. Photo: Eastern Telegraph Company receipt (1944), public domain, via Wikimedia Commons.

Why do draft invoices matter for failed payments?

Because a draft is the one status you can still change, and because subscription drafts accumulate in two situations. The first is the one-hour renewal window: Stripe creates the invoice, waits, then finalizes. If your code adds an invoice item in that window (usage charges or a one-off fee), the item rides on the same charge. The second is an unpaid subscription: when your failed-payment setting is "mark the subscription unpaid," Stripe keeps generating invoices that stay in draft and are not charged. A subscription-linked draft cannot be deleted, so cleaning up means deciding what happens to the subscription, not deleting invoices one by one.

If you use a recovery tool, the drafts are noise: nothing is owed yet and no email should be sent about them. The email belongs to the open invoice that actually failed.

One more way an invoice can get stuck in draft is a failed finalization. When Stripe cannot finalize an invoice, for example because Stripe Tax needs a customer location it does not have, it sends invoice.finalization_failed, and no payment can be collected until the cause is fixed. The customer has not failed to pay; they have never been asked. Handle that event as a notification to your own team, or to the customer if the fix is theirs to make, and keep it out of your dunning counts.

What rules should your app follow?

A short rule set avoids most incidents. Treat it as a starting point and adjust it to your product:

  1. Never wait for a "failed" invoice status. Subscribe to invoice.payment_failed, and read attempt_count and next_payment_attempt from the open invoice.
  2. Drive access from the subscription plus invoice.paid. Notify on past_due, revoke on canceled or unpaid, as in our subscription status rules.
  3. Check the invoice status again before every recovery email. A customer may have paid on the hosted page between two scheduled sends. If the status is paid, stop the sequence.
  4. Ignore drafts for recovery. Only open invoices with a failed attempt are candidates.
  5. Use void for mistakes and uncollectible for bad debt. And remember that voiding can flip the subscription.
  6. Keep a log of status changes you make by hand. The status transitions object on the invoice records timestamps, and your own notes should say why.

Revova's follow-up job works this way: before it sends each scheduled email it fetches the invoice from Stripe and, if the status is already paid, it stops the sequence instead of sending another message, which also catches customers who pay on the hosted page without triggering a failure event. For the email links it uses the invoice's hosted page URL. The same check is easy to add to a homemade flow.

Want a recovery sequence that stops the moment an invoice is paid? Revova starts from Stripe's failed-payment event and checks the invoice before every send. Starter is $29/mo, Pro is $79/mo, with a 14-day free trial and no card.
$29–79/mo · free trialStart free →

How do invoice statuses show up in reporting?

Different statuses count differently, and the differences explain many "the numbers do not match" threads. Voided invoices are treated as zero-value for reporting. Uncollectible invoices keep the amount owed visible for bad-debt accounting. Open invoices on subscriptions in past_due still count toward MRR in Stripe Billing analytics, because MRR includes active and past_due subscriptions. Only when the subscription becomes canceled or unpaid does the customer drop out of MRR and into churn. That is why a spike in failed payments does not show up in your MRR chart until a retry window later. For the measurement side, read how to calculate churn rate, including the involuntary part.

If an invoice amount was wrong, do not edit or void it just to fix reporting. After finalization, Stripe recommends a credit note to adjust the amount owed: you can issue one against an open, paid or uncollectible invoice for an overcharge, undelivered goods or a negotiated discount, and the original invoice stays intact for compliance.

What about old open invoices nobody chased?

Many accounts carry a long tail of open or uncollectible invoices from before any recovery was set up. A failed payment from eight months ago is not necessarily dead: the customer may still be reachable and the debt may still be real. An invoice marked uncollectible can still be paid, and a polite email with a payment link costs almost nothing. Our guide to historical payment recovery covers how to find those invoices and decide which are worth contacting, and how to recover failed Stripe payments covers the ongoing process. Before you chase an old failure, check whether it was a hard decline, which only a new payment method can fix; the difference is in soft versus hard declines.


Frequently asked questions

What are the Stripe invoice statuses?

There are five: draft, open, paid, void and uncollectible. A new invoice starts as draft and can be edited. Finalizing it makes it open, meaning it is awaiting payment. A successful payment makes it paid. An unpaid open invoice can be marked void (canceled) or uncollectible (written off as unlikely to be paid). There is no failed status: an invoice whose payment fails simply stays open.

What is the difference between void and uncollectible in Stripe?

Void means the invoice is canceled and no longer payable; it is treated as zero-value for reporting and the status is terminal. Uncollectible means you have given up expecting payment but still want to track the amount as bad debt, and the invoice can still be moved to paid or void later. Use void when the invoice should not have existed, and uncollectible when it was valid but the customer is unlikely to pay.

Does a failed payment change an invoice’s status in Stripe?

No. When an automatic payment attempt fails, the invoice stays open with a paid value of false, Stripe sends invoice.payment_failed, and the attempt count goes up. The Dashboard may show an open invoice with a badge such as Past due or Retrying, but those are labels on an open invoice, not separate statuses. The subscription is what moves to past_due.

Can I get an uncollectible invoice paid?

Yes. Stripe’s transition table lists uncollectible invoices as payable: attempting payment through the pay endpoint moves the invoice to paid if it succeeds, and it stays uncollectible if the attempt fails. So marking an invoice uncollectible is a bookkeeping decision, not a final one, and a customer who comes back with a new card can still settle it.

Why does my Stripe invoice stay in draft for an hour?

For subscription renewals Stripe leaves the invoice in draft for about an hour so your app can add invoice items, then finalizes and attempts payment. It waits one hour after getting a successful response to invoice.created from your webhooks. If it receives no successful response, finalization is delayed, up to 72 hours before Stripe finalizes and sends the invoice anyway. A broken webhook endpoint can therefore delay charges.

What is the difference between invoice.paid and invoice.payment_succeeded?

invoice.paid fires whenever the invoice reaches paid. invoice.payment_succeeded fires only when a payment attempt through a PaymentIntent succeeds. An invoice can become paid without one, for example when it relates to a trial or free subscription, when a customer credit balance covers it, when the amount is below the minimum charge, or when you mark it paid out of band. Provision access on invoice.paid.

Does voiding an invoice cancel the subscription?

Not by itself, but it can change the subscription status. Stripe documents that voiding the first invoice of an incomplete subscription moves it to incomplete_expired, voiding the first invoice of a past_due subscription returns it to active, and voiding the most recent invoice triggers a walk back through earlier invoices to decide the status. Void deliberately, and check the subscription afterwards.

How should my app use invoice status together with subscription status?

Use the subscription status for access decisions and the invoice for the money. Grant or revoke access from the subscription (and invoice.paid), and use the open invoice, its attempt count and next payment attempt to drive recovery emails. Stop sending recovery emails the moment the invoice is paid, whatever the subscription status says.

Turn open invoices back into paid ones

Revova emails customers when an invoice payment fails and stops when the invoice is paid. Starter is $29/mo, Pro is $79/mo, and the 14-day free trial needs no card.

Start my 14-day free trial →

No credit card · Free Lost Revenue scan · 30-day money-back guarantee

Found this useful? Tell Google you'd like to see more from us.