Stripe Discounts in QuickBooks: Gross or Net Revenue?
A Stripe coupon is a marketing decision that lands in your books as a permanent choice about what your revenue number means. Gross plus a discount line,...
A customer buys your $200 plan with the code SPRING25. Stripe collects $150. Three weeks later someone asks what discounting cost you this quarter, and you open QuickBooks to find out.
The answer may not be in there. Depending on one setting, QuickBooks either recorded $200 of revenue and a $50 discount, or it recorded $150 of revenue and nothing else. Both are defensible bookkeeping. Only one of them can answer the question.
That is the part of discounting nobody sets up in advance. A coupon is a marketing decision, made quickly, often by someone who does not open the accounting system. It arrives in your books as a permanent choice about what your revenue number means. If you want to see the full picture of how your Stripe settings shape your books, Acodei syncs Stripe invoices and payments into QuickBooks Online with the discount treatment configurable rather than assumed.
Coupons and promotion codes are not the same object
Most people use the two words interchangeably. Stripe does not, and the distinction turns out to matter for what you can control.
A coupon is the discount logic itself. Stripe describes coupons as "backend-driven discounts (your system decides who gets the discount)". You apply one directly to a customer, a subscription or an invoice, and the customer never types anything.
A promotion code is the customer-facing string that points at a coupon. Stripe calls it "a customer-facing code that wraps around a coupon, adding a distribution and control layer on top of coupons." The relationship is many-to-one: "Many promotion codes can reference one coupon." So FALLPROMO and SPRINGPROMO can both be 25% off, tracked separately, backed by a single coupon.
The control layer is the real difference. Stripe's own comparison is blunt about which restrictions exist where:
| Capability | Coupon | Promotion code |
|---|---|---|
| Restrict to a specific customer | Unsupported | Supported |
| Apply to first-time purchase only | Unsupported | Supported |
| Minimum spend to redeem | Unsupported | Supported |
| Deactivate without deleting | Delete only | Archive via the active flag |
There is a third object underneath both. When a code is redeemed, Stripe creates a Discount: "When a customer redeems a coupon, Stripe creates a Discount object to track that redemption." The coupon is the rule, the promotion code is the door, and the discount is the event.
One consequence of that separation catches people out. Stripe notes that deleting a coupon "prevents it from being applied to future subscriptions or invoices, but it doesn't remove the discount from any subscription or invoice that already has it", and that "Deleting a coupon will archive its associated promotion codes." Ending a promotion does not end the discounts already running on it.
Where the discount actually sits on the invoice
Before asking what QuickBooks does with a discount, it helps to know what Stripe hands over, because a discount is not a single number sitting at the bottom of the invoice.
Discounts attach at two levels. Individual invoice lines carry their own discount detail, in a field Stripe describes as "The amount of discount calculated per discount for this line item". The invoice separately carries the aggregate, "The aggregate amounts calculated per discount across all line items."
That produces a subtlety worth knowing before you reconcile anything. Stripe defines the invoice subtotal as the total of subscriptions, invoice items and prorations "before any invoice level discount or exclusive tax is applied", then adds four words that change its meaning: "Item discounts are already incorporated". Line-level discounts are inside the subtotal. Invoice-level discounts are not. Two invoices with identical totals and identical discounts can show different subtotals purely because of where the discount was applied.
There is also a category of line that cannot be discounted at all. Stripe's discountable field is documented as "If true, discounts will apply to this line item. Always false for prorations", and the coupons documentation says the same thing from the other side: "You can't discount proration line items further on the invoice that's generated." So a 25% off subscription coupon does not touch the proration generated when that subscription changes mid-cycle. The customer sees a discounted plan and an undiscounted adjustment on the same invoice, which is correct and looks like a bug.
If you want the full anatomy of these fields, we have a reference on the Stripe invoice line item.
The two shapes a discount can take in QuickBooks
Now the accounting question. A $200 sale with $50 off can be recorded two ways, and they are not equivalent.
Net. One line, $150. Revenue is $150. This is clean, it ties to the cash, and it is what most integrations do by default because it is the simplest thing that balances. The cost is permanent: the $50 is not recorded anywhere, so no report in QuickBooks can ever tell you it existed.
Gross plus contra. Two lines: $200 of revenue, and a $50 discount line pointing at a discount account. The net is still $150 and it still ties to the cash. But now discounting is a number you can pull, trend and compare against the campaign that caused it.
Accountants generally want the second one, and not out of neatness. Gross revenue with a separate discount line is what makes discounting visible as a cost of sale rather than as revenue that never happened. It is the difference between "we did $150,000 last quarter" and "we did $180,000 and gave back $30,000", which are the same business and two very different conversations.
Acodei documents a setting for exactly this. Coupon tracking posts coupons and discounts as a separate line item rather than folding them into the sale, and its documented purpose is stated plainly as the need for a gross-versus-discount split in QuickBooks. It has one prerequisite worth handling before you ask for it: a Discounts product must be configured first, because the discount line needs somewhere to go.
Two practical notes on that product. It should point at a contra-revenue or discount account in your chart of accounts rather than at an ordinary income account, or you have moved the problem rather than solved it. And Acodei documents a general constraint on every QuickBooks product used in its mapping: they must be marked as non-taxable, because taxable products in QuickBooks conflict with the sales and payout math.
Coupon tracking is an advanced setting rather than a self-serve toggle, so turning it on means asking support. The broader survey of settings that quietly change what your books say is in our guide to Stripe sync settings and their accounting impact.
The mapping trap: "gross" does not mean what you think
This is the failure that costs the most time, because nothing about it looks like an error.
Acodei can route revenue to different QuickBooks products using several matching strategies. One of them, Transaction Value, matches on the amount. The documentation describes it as comparing "the gross amount (before fees)" against a value you configure, such as 9.99.
Read that qualifier carefully. Gross means before Stripe's fees. It does not mean before discounts. The number being matched is what the customer actually paid.
So a rule that says "$200 maps to Pro Plan Revenue" matches every full-price Pro sale and none of the discounted ones. Acodei's documentation states the failure directly: promotional discounts can cause the final charge amount to differ from the base product amount, "breaking the match unless the user configures a separate rule for the discounted price." Its troubleshooting section repeats the advice: "If using Transaction Value matching, the final charged amount after discount no longer equals the base price. Consider a separate rule or switch to Product ID mapping."
Three things make this worse than an ordinary misconfiguration.
It is usually silent. The revenue does not disappear. The transaction matched some other rule, or fell through to the catch-all product, and posted successfully, so there is nothing in an error queue to investigate. The exception is worth knowing because it is the one lever that makes this loud: Acodei documents two possible fallbacks when no rule matches, defaulting to a single catch-all product or throwing a sync error, and which one you get depends on whether your configuration allows uncategorized items. An account configured to disallow them finds out immediately. An account with a catch-all finds out in March.
It is correlated with your best months. The transactions that break the rule are the discounted ones, which means the more successful a promotion is, the larger the share of revenue that lands in the wrong account. Your books look strangest in the months you did the most business.
Fixing the rule does not fix the history. Acodei documents that mapping rules are not versioned and that a changed rule "takes effect for future transactions only". Correcting the rule in November does nothing for the September and October records already written. Those have to be resynced or adjusted deliberately.
The durable fix is to stop matching on amounts. Mapping on the Stripe product and price ID is stable under discounting, because the product does not change when the price paid does. Acodei stores references to both the product and the price, so monthly and annual variants of the same plan stay distinguishable. General mapping troubleshooting, including the other ways rules go wrong, is covered in why Stripe charges land on the wrong QuickBooks product.
The 100% off case
A full-coverage discount is its own situation, because the invoice total goes to zero while the sale is real.
Stripe's line items stay at their normal price and the discount drives the total to zero, so the invoice genuinely represents a $200 sale that collected nothing. Whether that reaches QuickBooks at all is a setting: Acodei documents a $0 invoice option that allows invoices with a zero balance but non-zero lines to sync, aimed at 100% discount and freemium flows. Invoices consisting only of zero-value lines are still skipped.
This matters for anyone running a free tier or a full-comp promotion, because the default behavior leaves those customers absent from your books entirely. The wider treatment of zero and negative invoices is in our post on zero dollar and negative Stripe invoices.
Duration is where discounts get forgotten
Coupons have a lifespan, and the way Stripe implements it produces a reporting surprise.
Duration is one of three values: once, repeating with a month count, or forever. Stripe notes it "defaults to once, which applies only to the first invoice."
The surprise is what happens after a one-time coupon is consumed. Stripe documents the sequence: before it is applied the subscription's discounts array contains the discount, after the invoice finalizes it no longer does, and "The invoice that consumed the coupon still shows the applied discount on the invoice resource and line items." Stripe states the consequence outright: "This means a subscription may appear to have no discount even though a coupon was applied."
If you audit discounting by looking at subscriptions, you will undercount. The record of a one-time discount lives on the invoice it was applied to, not on the subscription that received it. Your accounting system, which is built from invoices and payments, is the more reliable place to count from, provided the discount was recorded there in the first place.
Stacking has a similar sharp edge. You can apply up to 20 discounts to a subscription, subscription item or invoice, and when both a percentage and a fixed amount are involved, the order changes the result. Stripe's example is "20% off then 5 USD off" versus "5 USD off then 20% off", which are different numbers.
Discounts that are not coupons
Stripe lists three other ways to reduce what a customer pays: a negative customer balance, negative invoice items, or a second cheaper price for the same product. Each lands differently in your books.
A second, cheaper price is invisible as a discount. It is simply a lower-priced sale, and no discount line can exist because nothing was discounted. Fine for a permanent tier, misleading if you think of it as a promotion.
A negative customer balance appears as an applied balance rather than a discount, which is a different mechanism with different bookkeeping. Acodei includes the applied balance as a line item on the QuickBooks invoice by default, specifically so the invoice reflects the amount Stripe actually charged.
Negative invoice items are the most legible of the three, and Stripe says so: of the alternatives, "negative invoice items provide more detailed information as to what discount was created, when, and why." If you are going to discount outside the coupon system, this is the option that leaves a trail.
A short checklist
- Decide gross or net before you run a campaign, not after. If anyone will ever ask what discounting cost, you need the gross-plus-discount-line treatment, and it needs to be configured first.
- Point the discount product at a contra-revenue account, not at an income account, and make sure it is non-taxable.
- Do not map revenue by transaction amount if you discount. Map on product and price ID. Amount-based rules break the moment a coupon exists, silently.
- Audit discounts from invoices, not subscriptions. One-time coupons vanish from the subscription once consumed.
- Check whether 100% off sales are reaching QuickBooks at all, especially if you run comped accounts or a free tier.
- Remember that deleting a coupon does not stop discounts already applied. It only prevents new ones.
The theme underneath all six is that a discount is not just a smaller number. It is information about why the number is smaller, and that information survives into your accounting system only if something is configured to carry it.
Acodei mirrors Stripe invoices, payments and credit notes into QuickBooks Online, can map revenue by product and price rather than by amount, and can post discounts as their own line so gross revenue stays gross. Start a free trial.
Frequently Asked Questions
What is the difference between a Stripe coupon and a promotion code?
A coupon is the discount logic. Stripe describes coupons as "backend-driven discounts (your system decides who gets the discount)". A promotion code is the customer-facing string that points at one, described as "a customer-facing code that wraps around a coupon, adding a distribution and control layer on top of coupons". Many promotion codes can reference a single coupon, and only promotion codes support restrictions like first-time-order-only, minimum spend, or limiting to a specific customer.
Should Stripe discounts show as gross revenue with a discount line, or as net revenue?
Gross plus a separate discount line is what lets you report on discounting later, because the discount becomes a number you can pull rather than revenue that was never recorded. Net is simpler and still ties to the cash, but the discounted amount is unrecoverable from your books. Acodei documents a coupon tracking setting that posts coupons and discounts as a separate line item rather than folding them into the sale, with the stated purpose of producing a gross-versus-discount split in QuickBooks. It requires a Discounts product to be configured first.
Why do my discounted Stripe sales map to the wrong QuickBooks product?
Almost certainly because the mapping rule matches on transaction amount. Acodei's Transaction Value strategy compares the gross amount before fees, which is the amount after any discount. Its documentation states that promotional discounts can cause the final charge amount to differ from the base product amount, "breaking the match unless the user configures a separate rule for the discounted price". The fix is to map on the Stripe product and price ID instead, which does not change when the price paid does.
Will fixing a mapping rule correct transactions that already synced?
No. Acodei documents that mapping rules are not versioned and that a changed rule takes effect for future transactions only. Records written under the old rule stay as they were written, so correcting historical months means resyncing or adjusting those records deliberately.
Do 100% off Stripe invoices sync to QuickBooks?
Only if the relevant setting is enabled. Acodei documents a $0 invoice option that allows invoices with a zero balance but non-zero line items to sync, aimed at 100% discount and freemium flows. Invoices made up entirely of zero-value lines are still skipped.
Why does a subscription show no discount when a coupon was definitely applied?
Because the coupon was probably a one-time one. Stripe documents that after the invoice finalizes, a duration=once discount is removed from the subscription's discounts array while "The invoice that consumed the coupon still shows the applied discount on the invoice resource and line items." Stripe puts the consequence plainly: "This means a subscription may appear to have no discount even though a coupon was applied."
Can a Stripe coupon discount a proration?
No. Stripe's discountable field is documented as "Always false for prorations", and its coupons documentation states "You can't discount proration line items further on the invoice that's generated." A discounted subscription that changes mid-cycle will show an undiscounted proration line alongside the discounted plan line.
Automate your Stripe to QuickBooks sync
Save hours every month. Acodei automatically syncs your Stripe transactions, invoices, and payouts to QuickBooks Online.
How Acodei handles this in your stack
Stripe QuickBooks Integration
See how Acodei syncs Stripe payments, fees, refunds, invoices, and payouts into QuickBooks Online automatically.
Or go straight to a capability
Advanced Product Mapping
Map Stripe products to QuickBooks with rule-based logic on product ID, price ID, metadata, and account. Set rule priority and extend mapping to refunds and fees.
Automated Invoice Sync
Bring Stripe invoices into QuickBooks and auto-apply payments and credit memos, with numbering, invoice matching, and quantity tracking to cut double-entry.
Multi-Currency Mastery
Sync Stripe transactions across currencies with automatic exchange rate handling, currency-specific customer records, and invoice-level multicurrency.
Class Mapping
Map Stripe products to QuickBooks classes for scalable categorization and multi-entity reporting, enabling precise insights without manual effort.
Historical Data Import
Backfill historical Stripe data into QuickBooks by month range. Preview volume and cost before syncing so reporting starts from a complete baseline.
How to Connect Stripe to QuickBooks Online
Connect Stripe to QuickBooks Online in minutes. Acodei links both accounts with secure OAuth and syncs payments, fees, refunds, and payouts automatically.
Reconcile Stripe Payments in QuickBooks
Reconcile Stripe in QuickBooks Online automatically. Acodei splits out fees, matches payouts to deposits, and keeps every charge audit-ready.
Related articles
Acodei Journal
Cash vs Accrual for Stripe Revenue: What Actually Posts
Acodei Content Team
Cash vs Accrual for Stripe Revenue: What Actually Posts
8/16/2026
Acodei Journal
QuickBooks API Rate Limits and a Slow Stripe Sync
Acodei Content Team
QuickBooks API Rate Limits and a Slow Stripe Sync
8/15/2026
Acodei Journal
A Stripe Invoice Resync Rebuilds Two QuickBooks Records
Acodei Content Team
A Stripe Invoice Resync Rebuilds Two QuickBooks Records
8/13/2026
Get more operational finance guides like this one
We will only send high-value product and finance content.