Stripe billing_reason: What Reaches QuickBooks

Stripe's billing_reason is the only invoice field that says why the invoice exists. What each of the nine values means, which ones are not real invoices,...

Acodei Content Team · 8/23/2026 · 11 min read

Open any month of Stripe invoices and you can sort them by amount, by customer, by status, by date. Every one of those tells you something about the invoice. None of them tells you why the invoice exists.

That question matters more than it sounds. A $400 invoice raised because a subscription rolled into a new month is expected recurring revenue. A $400 invoice raised because someone upgraded mid-period is mostly a proration, and it will never repeat at that figure. A $400 invoice raised because metered usage crossed a limit is neither: it fired on a quantity, not a date. Three identical amounts, three completely different things to say about next month.

Stripe records the answer in a single field called billing_reason, and it is the only field on the invoice object that speaks to origin rather than content. If you sync Stripe to QuickBooks, it is also the field that predicts which invoices are going to behave strangely once they land.

Start a free trial and see how your Stripe invoices arrive in QuickBooks Online.

One field, nine values

Stripe's definition is one line: billing_reason "Indicates the reason why the invoice was created."

The API documents nine possible values:

ValueWhat Stripe says
manual"Unrelated to a subscription, for example, created via the invoice editor."
subscription_create"A new subscription was created."
subscription_cycle"A subscription advanced into a new period."
subscription_update"A subscription was updated."
subscription_threshold"A subscription reached a billing threshold."
subscription"No longer in use. Applies to subscriptions from before May 2018 where no distinction was made between updates, cycles, and thresholds."
upcoming"Reserved for upcoming invoices created through the Create Preview Invoice API or when an invoice.upcoming event is generated for an upcoming invoice on a subscription."
quote_acceptListed in the enum without a separate description.
automatic_pending_invoice_item_invoiceListed in the enum without a separate description.

Worth being precise about that last pair. Stripe's per-value list explains seven of the nine, and the other two appear only in the enum. Their names are readable enough to work with, but if you are building a rule on either one, test it against your own data rather than trusting an inference from the name.

The three subscription values are not interchangeable

Most invoices in a subscription business carry one of three values, and the difference between them is the difference between revenue you can forecast and revenue you cannot.

subscription_cycle is the baseline

This is the invoice you expect: the subscription reached the end of a period and Stripe raised the next one. Same customer, same price, same cadence. If your monthly recurring revenue means anything, it means the sum of these.

A useful property: a clean subscription_cycle invoice usually has line items whose period matches the invoice period. When it does not, something else got attached to it, which brings us to the next value.

subscription_update is where the prorations live

A mid-period change generates this. Upgrades, downgrades, quantity changes, plan swaps. The invoice exists because the subscription was altered, not because time passed.

These are the invoices that break naive revenue reporting, because the amount is an adjustment rather than a price. Stripe stacks the lines in a documented order: the lines list is sorted with "(1) pending invoice items (including prorations) in reverse chronological order, (2) subscription items in reverse chronological order, and (3) invoice items added after invoice creation in chronological order." The prorations sit at the top, and they can be negative.

A downgrade can produce an invoice whose credits exceed its charges. A mid-cycle change can produce one where amount_due lands at zero because account credit absorbed the whole thing. Stripe says as much about amount_due: it "may be 0" when "the invoice's total is smaller than the minimum charge amount, for example, or if there is account credit that can be applied to the invoice." Neither of those is an error. Both of them are subscription_update invoices doing exactly what they are supposed to do, and both need somewhere sensible to go in your books. See Stripe proration for the mechanics of how the credit and charge lines are calculated.

subscription_threshold fired on a quantity, not a date

This one is genuinely different in kind. Billing thresholds let you invoice when usage crosses a limit instead of waiting for the period to end, so the invoice arrives on a quantity event.

Stripe gives you a second field for it. threshold_reason is documented as: "If billing_reason is set to subscription_threshold this returns more information on which threshold rules triggered the invoice." So you can tell not just that a threshold fired, but which one.

The accounting consequence is that a subscription's invoice count stops being predictable. A customer on a monthly plan can generate four invoices in a month, one cycle and three thresholds. Anyone reconciling by counting invoices per subscription per month will be wrong about that customer, and billing_reason is what tells you why.

The values that are not what they look like

Two entries in the enum will mislead you if you treat them as ordinary invoices.

subscription is a fossil. Stripe's own description says it is "No longer in use" and applies to "subscriptions from before May 2018 where no distinction was made between updates, cycles, and thresholds." If you are importing historical data, you will see it, and you cannot recover the distinction it predates. Anything you do to split those into cycles and updates after the fact is a guess. Label them as legacy and stop there.

upcoming is not an invoice at all. Stripe reserves it for previews created through the Create Preview Invoice API and for invoice.upcoming events. The object exists to answer "what would the next invoice look like", not to bill anyone. Stripe even marks the identifier: for preview invoices the id "will be prefixed with upcoming_in."

Treat one of those as real and you have booked revenue for a period that has not happened. If you are pulling invoices through the API for reporting, filter on the value before you sum anything.

What actually reaches QuickBooks

Here is the part that matters if Stripe is your billing system and QuickBooks is your ledger, and it is worth stating plainly because it cuts the other way from what you might expect.

billing_reason does not change the record type. Acodei's Invoice Sync maps the Stripe invoice lifecycle to QuickBooks by event, not by origin: invoice.created and invoice.finalized create a QuickBooks Invoice, and invoice.paid or charge.succeeded create the Payment against it. The lifecycle has one row for invoice creation, and it does not branch on why Stripe raised the invoice. A threshold invoice and a cycle invoice arrive as the same kind of QuickBooks record.

So the origin taxonomy is available in Stripe and absent in QuickBooks. If you want to analyze revenue by why it was billed, that analysis has to happen on the Stripe side. QuickBooks will tell you what you invoiced and what you collected. It will not tell you which invoices were adjustments.

What billing_reason does predict is which invoices are going to hit the interesting paths on the way over, and every one of these is a subscription_update problem:

  • Invoices whose lines net to zero. Acodei skips an invoice whose line items are all $0. An admin setting called "Enable $0 Invoices" allows an invoice whose amount_due is 0 but which has at least one line item greater than zero to sync, and it is off by default. A downgrade that credits exactly as much as it charges is the classic way to produce one.
  • Invoices whose total is negative. When credits exceed charges, Acodei converts the invoice to a Credit Memo, or splits it into a memo plus a $0 invoice, depending on amount_paid. That is the right answer in QuickBooks, where accounts receivable does not take a negative invoice, but it does mean the record type you find is not the one you went looking for. Zero-dollar and negative Stripe invoices in QuickBooks covers the shapes these take.
  • Invoices carrying an applied balance. Stripe can apply a customer balance to reduce or increase amount_due. By default Acodei includes that applied balance as a line item on the QuickBooks invoice so the record reflects the exact amount Stripe charged. A setting called "Skip 'Applied Balance' as line item on Invoice" makes it post the full gross amount instead, so accounts receivable carries the whole value of the sale. Which one you want depends on whether you are reconciling to Stripe's cash or to your own revenue.
  • Proration lines needing a product. Each invoice line uses the product returned by Multiple Product Mapping when it is enabled, and the default product otherwise. Proration lines are lines like any other, so a subscription_update invoice will map them the same way it maps a subscription item.

One validation note, because the condition on it matters: Acodei compares the invoice it built in QuickBooks against the Stripe invoice amount and requires an exact match, and that check applies only when tax is enabled. It is not an unconditional total check.

Invoice Sync itself is a premium feature, enabled per company under Account Mapping in the Premium Features block, so none of the above applies until it is switched on.

Reading a month by origin

The practical move is to stop reading the invoice list as a flat set and group it by billing_reason before anything else. A month of a healthy subscription business tends to look like this:

  • A large block of subscription_cycle, roughly equal to your recurring revenue, arriving on predictable dates.
  • A smaller block of subscription_create, which is new business, and the only block where an unfamiliar customer name is expected.
  • A scattered block of subscription_update, which is expansion, contraction and correction mixed together, and where the amounts mean the least on their own.
  • Possibly a block of subscription_threshold, which is usage.
  • A few manual invoices, which are the ones a human decided to raise, and therefore the ones most worth glancing at individually.

The signal is in the proportions and how they move. subscription_update volume climbing faster than subscription_create means your existing customers are changing plans more than you are adding new ones, and whether that is expansion or churn depends on the sign of the prorations, not on the count. A month where subscription_cycle drops without a matching cancellation count usually means subscriptions moved rather than ended.

None of that is visible in a QuickBooks revenue report, because by then every one of these is an Invoice. It is visible in Stripe, on one field, and it costs nothing to look.

For the neighbouring question of whether an invoice is being advanced toward payment at all, which is a different field and a different problem, see Stripe automatic collection and what it does in QuickBooks. For the statuses an invoice moves through once it exists, see Stripe invoice status.

Frequently asked questions

Does billing_reason change how the invoice syncs to QuickBooks?

No. Acodei's Invoice Sync creates a QuickBooks Invoice from invoice.created or invoice.finalized and a Payment from invoice.paid or charge.succeeded. Those mappings are by event, and the documented lifecycle does not branch on why Stripe raised the invoice. What differs between origins is the shape of the invoice, not the record type it becomes.

Can I filter Stripe invoices by billing_reason in the API?

The field is present on every invoice object you retrieve or list, so you can group and filter on it in your own code. If you are summing invoices for a period, filter out upcoming first: Stripe reserves that value for preview invoices, which are not bills.

Why do some of my invoices show subscription instead of a more specific value?

Because they predate May 2018. Stripe describes subscription as "No longer in use" and applying to "subscriptions from before May 2018 where no distinction was made between updates, cycles, and thresholds." The specific reason was never recorded, so it cannot be recovered.

What is threshold_reason?

A companion field to billing_reason. Stripe documents it as returning "more information on which threshold rules triggered the invoice" when billing_reason is subscription_threshold. It is how you tell which usage limit fired.

Why did a mid-period plan change produce a $0 invoice?

Because the proration credit and the proration charge cancelled out. Stripe notes that amount_due "may be 0" when account credit covers the invoice or the total falls below the minimum charge amount. In Acodei, an invoice whose line items are all $0 is skipped, while an invoice with amount_due of 0 and at least one line item above zero syncs only if the "Enable $0 Invoices" setting is on, which it is not by default.

Where this leaves you

billing_reason is a small field doing an unusually large amount of work. It is the only place Stripe records intent rather than outcome, it is the fastest way to separate recurring revenue from adjustments, and it flags the invoices most likely to arrive in QuickBooks as something other than a plain invoice.

It is also the sort of thing that only becomes obvious once the syncing itself stops being a daily problem. Acodei mirrors Stripe invoices, payments, credit notes and payouts into QuickBooks Online on its own, which leaves you free to spend the month-end reading the numbers instead of assembling them.

Start a free trial, or see how Stripe to QuickBooks sync handles the invoice lifecycle end to end.

Stripe field definitions quoted in this post come from Stripe's Invoice object reference, retrieved 2026-08-23.

Share

Automate your Stripe to QuickBooks sync

Save hours every month. Acodei automatically syncs your Stripe transactions, invoices, and payouts to QuickBooks Online.

Get more operational finance guides like this one

We will only send high-value product and finance content.