How should a B2B SaaS product design billing: plan changes, seats, invoices and failed payments?
A B2B SaaS team can design billing by writing one rule for each event, such as a downgrade, a seat removal or a failed renewal, and showing the customer what happens before, at and after it.
Illustrative situation: the operations lead of a 30-seat customer wants to drop 10 seats. She finds Billing, which is a pricing page and a button called “Manage subscription” that opens a payment provider’s portal. The portal lets her lower the seat count. It does not say what the change costs, whether 10 people lose access today or at renewal, or whether the credit goes back to her card or onto the next invoice. A few weeks later the company card expires. The warning email goes to the engineer who created the account two years ago and has since left. Finance learns about it when the product locks. The scene is invented, but the pattern is common: billing was bolted on as a payment page, and nobody designed it as a place where several people make decisions with money attached.
Humbleteam, a digital product design agency, publishes this guide. It treats billing as a list of events, such as an upgrade, a seat removal or a failed renewal. For each event it asks what the customer sees before, at and after the moment, and who hears about it. A table near the end collects the answers so a team can copy it. This is general information about product design and the rules named in it, not legal or tax advice.
Who opens the billing area, and what must it tell them?
Start with people, not screens. A B2B account has at least four, and they rarely overlap.
| Role | Questions billing must answer | Design consequence |
|---|---|---|
| Workspace admin | What do we pay for, what do we use, what does this change cost, and when does it take effect? | Owns plan and seat changes and sees the preview before confirming |
| Billing contact | Is the payment method valid, when is the next charge, how do I fix a failure? | May not use the product daily, so email must reach them and they should not need a paid seat |
| Finance or accounts payable | Where is the invoice with our legal entity, tax ID and PO number? | Often has no login; gets documents by email or link and needs correctable details |
| Ordinary user | Why is this feature locked, or my seat gone, and who can fix it? | Sees a plain message that names who to ask, and can send a request |
GitHub shows the billing contact idea in practice. Its billing manager role can update payment methods, download receipts and move an organization between the Free and Team plans, and it receives billing receipts by email. It cannot open the organization’s repositories, and it does not use a paid license. Billing managers can also review member requests for extra Copilot budget, which is a request path for ordinary users.
Payment-provider portals know customers, not people. Stripe’s guide says to authenticate customers on your site before creating a portal session, so your product decides which of your users may open it. Stripe’s billing emails go to the customer’s account email by default. Extra recipients can be added in its Dashboard, but its docs said on October 27, 2026 that the API does not support adding recipients to billing emails. A “billing contacts” screen may therefore need its own record and its own sending. Check this with engineering before designing the screen.
Should a plan change apply now or at renewal?
Pick one rule per direction and say it on the screen. GitHub’s published rules are a clear example: an upgrade is billed and applied immediately with proration, and a downgrade or cancellation takes effect at the end of the current cycle with no proration. Switching from yearly to monthly waits for the next renewal.
Provider portals do not choose for you. In Stripe’s portal settings, switching plans, changing quantities and prorating are all off by default. Downgrades apply immediately unless you turn on scheduling, and scheduled downgrades work only between prices of the same product. Paddle offers five proration modes, from prorate and bill now to skip billing. One more trap: in Stripe, moving from monthly to yearly moves the billing date to the day of the switch. Say so before the customer confirms.
The harder question is what happens above the new limit. Slack’s downgrade page is a useful model. It says the free version keeps 90 days of message and file history, that upgrading reveals the older material, and that data over a year old is deleted. It also tells admins to open workspace analytics first, to see how many messages and files will be hidden and how many deleted. Slack Connect channels disconnect too. That is the right level of detail: counts and dates, not a generic warning.
Our suggestion is to sort every consequence of a downgrade into one of four buckets before the confirm button: turns off, becomes read-only, stays but over the limit, or is deleted. Give each a date and a count, and put an export link beside the last two.
How should seats be added, removed and trued up?
Policies differ, so write yours down. GitHub prorates added seats and grants access at once. Removed seats take effect in the next cycle, with no proration, unless access is revoked manually. Slack bills for active members. When a paid member becomes inactive, it adds a prorated credit to the next statement. Customers who pay annually by invoice and outgrow the paid count get an invoice once per calendar quarter. That quarterly invoice is a true-up, and customers should read about it before they buy.
Engineering details leak into billing here. Stripe’s docs note that changing a subscription’s price resets the quantity to 1 unless the update restates it. For a 30-seat account that is a wrong invoice, in one direction or the other. Ask engineering to test the plan-change path with a seat count above 1.
Our suggestions for the screen:
- Show three numbers: seats paid for, seats assigned and seats active. A gap between the first and the third is what an admin needs to see before deciding which seats to remove.
- Separate “free this seat” from “remove it from the subscription”. The first is an access action. The second is a billing action with a date.
- When removing seats, make the admin choose the people. The tool can propose the least recently active, but the admin confirms.
- Let ordinary users who hit the seat limit send a request to admins and the billing contact, instead of showing a buy button they cannot use.
- State the true-up rule on the plan page: when extra seats are counted and when they are billed.
How do you show the charge before the customer confirms?
Proration is the part customers cannot work out for themselves. Stripe’s own example is a monthly plan going from $10 to $20 halfway through the period: the customer gets a $5 credit for unused time on the old plan and a $10 debit for the remaining time on the new one, so the net is $5. Its docs add that negative prorations are not refunded automatically and positive ones are not billed immediately. They land on the next invoice unless you arrange otherwise. A customer who expects an instant refund to her card will be surprised.
Vendors calculate differently. Stripe prorates to the second and Paddle to the minute. Chargebee lets a site choose day-based or millisecond-based proration. A preview from the same engine as the final charge avoids arguments. Stripe’s preview-invoice endpoint can show the prorations, and it says to pass the same proration date on the real update so the amounts match. Paddle’s preview returns an immediate transaction, a next transaction and recurring details, and tells teams to show these in in-app upgrade and downgrade flows.
Those three results make a good confirm panel:
- Due today: the amount charged now, or “$0, credit applied to your next invoice”.
- Next invoice: the date, the amount and the lines that make it up.
- Then: the recurring amount, with the billing date and whether it moved.
Mark credits as credits, state whether tax is included, give the effective date, and repeat the amount on the button. If the change is charged immediately, add the failed-payment state. With Stripe’s pending updates, the change applies only if payment on the new invoice succeeds, and an unpaid update expires, so the screen needs a “change not applied” message.
What do finance teams need from invoices and tax details?
Finance teams need invoices they can file and defend. Stripe shows a customer’s tax ID in the header of invoice and credit note PDFs. Its customer portal can let customers edit that ID, but the setting is off by default. Validation checks the number against registries such as the EU’s VIES and the UK’s HMRC. It confirms the number is valid, not that the name and address match. Stripe Tax applies a reverse charge or zero rate when the ID has the required format, whatever the government check says. Whether that is correct for a given customer is a question for a tax adviser.
PO numbers are the other common request. Stripe supports up to four custom invoice fields, with PO numbers as an example. They can be set on the customer and inherited by new invoices, but they cannot be changed once an invoice finalizes. Stripe also says invoices attached to subscriptions cannot be revised after finalization, and that editing them is in preview. In the EU it suggests voiding and issuing a credit note, so ask counsel what applies to you.
The design consequence is that wrong details must be caught before the first invoice, not after. A billing profile screen should hold the legal entity name, address, tax ID, PO number and invoice recipients. Each field should say when it takes effect: “Used on invoices issued after you save.” Next to the invoice list, add a line that says what to do about one already issued, such as “Ask us to reissue it”. Prompt for a new PO number before each renewal. Give every row a PDF, a status and any credit note.
What should the product do when a payment fails?
Stripe says many failed payments are recoverable, and its retry defaults are a useful starting point. Smart Retries is Stripe’s recommended setting, with a default of 8 tries within 2 weeks. A custom schedule allows up to three retries. Stripe does not retry when no payment method exists, and hard declines such as a lost card or required authentication wait until a new method arrives. When recovery fails, you choose whether the subscription is canceled, marked unpaid, left past due or paused. Chargebee’s dunning can retry up to 12 times and also holds hard declines until the payment method changes. One detail for engineers: update the payment method field where the payment failed, or retries keep using the old one.
Stripe’s customer emails cover failed payments, renewal reminders and expiring cards, which it sends one month before expiry. Their links lead to a page where the payment method can be updated. Those emails go to the billing email, which is the account email by default, so the person reached may not be the person who can pay.
Access is the part that needs a product decision. GitHub locks paid features when a payment is past due. It does not charge for the locked period, and the account unlocks automatically after payment is processed, which it says can take up to 24 hours. Our suggestion is a short ladder with dates on every rung:
- Payment failed. Full access. A banner for admins and billing contacts, an email to both, the reason in plain words and the next retry date.
- Past due. Full access, a countdown and a reminder schedule. Name the date access will change.
- Restricted. Read-only, with export open. Never delete anything at this step.
- Ended. Follows the cancellation rules, with a stated data-retention period.
Show the banner to ordinary users only when they are blocked, and then say who to ask. Give each cause its own copy: expired card, authentication needed, bank decline, no method on file, or an unpaid invoice for customers who pay by transfer. After a card update, say “We’re retrying now” and give a time for the result. Baymard’s checkout research found that 34% of tested ecommerce sites clear card details after an error. In that testing it directly caused abandonment, so a card-update form should keep what the person typed.
How can cancel and pause work without dark patterns?
Decide when cancellation takes effect. In Stripe’s API a cancel call is immediate by default, and ending at the period end is an option. Its portal settings turn cancellation reasons on and retention coupons off by default. Our suggestion for most B2B plans is to end at the period end: show the date, tell the admin what happens to the data, offer an export and allow undo until that date. Cancellation should be an admin action, with notice to the billing contact and other admins.
Pause is a different thing from cancel, and customers should be told which kind they get. In Stripe, pausing a subscription suspends service delivery and invoice generation, while pausing payment collection leaves access on. Offer pause as one clear option on the cancel screen, not as a detour.
NN/g defines obstruction as making it harder to choose the option that does not benefit the company, and notes that the FTC sued Amazon partly over Prime cancellation. NN/g also lists forced continuity among deceptive patterns: charging after a trial with little warning. The fixes are plain: renewal notices that carry the amount and date, and a cancel path no longer than the sign-up path.
On the law, this is where the United States federal level stood on October 27, 2026. It is general information, not legal advice, and it does not cover the EU or UK. The FTC’s 2024 “click-to-cancel” amendments were vacated by the Eighth Circuit on July 8, 2025, because the FTC had skipped a required preliminary regulatory analysis. On February 12, 2026 the FTC restored the older rule text, which covers only prenotification plans. In March 2026 it published an advance notice asking whether to keep that rule, revive parts of the vacated one, or rely on education. Comments closed April 13, 2026. A Federal Register search on October 27, 2026 showed no proposed rule since then, and an FTC notice dated October 14, 2026 still calls it the restored rule.
What remains is ROSCA, which covers online sales to consumers. It requires clear disclosure of material terms before billing information is taken, express informed consent, and simple mechanisms to stop recurring charges. Whether business buyers are protected the same way is not settled: the FTC’s notice itself asks whether these practices are less common in transactions between sophisticated businesses, and it asks how much longer cancellation takes when a customer declines a retention offer. A law firm summary puts the number of states with their own automatic-renewal laws at about 30. Ask counsel which apply to your customers. As a design test, time your cancel path with the retention offer declined, and compare it with sign-up.
Where does usage-based billing fit?
Briefly: Stripe notes that prorations apply to charges billed ahead of the period, and usage-based billing is not prorated. A plan that mixes seats and metered usage needs a confirm panel that separates the two. Credits, meters and balance screens are a separate design problem, which our guide to AI SaaS pricing and credits UX covers.
The billing event table
Fill one row per event your product supports. The cells are suggestions to adapt, not standards.
| Event | Before the customer confirms | At the moment | After | Who is notified |
|---|---|---|---|---|
| Upgrade | Due today, next invoice, then recurring; list of new features | Charge now, prorated; access changes now | Receipt; invoice shows the proration period | Actor on screen; billing contact by email |
| Downgrade | Effective date; what turns off, goes read-only or is deleted, with counts; export link | Scheduled change banner with Undo | Features change on the date; credit or final invoice | All admins and billing contact now; affected users on the date |
| Add seats | Price per seat; prorated amount; true-up rule | Seats usable at once | Invoice line names the seats and dates | Billing contact |
| Remove seats | Admin names the people; effective date; credit or no credit | Seats marked “ending” | Access ends on the date; credit appears | Billing contact; the people affected |
| Renewal ahead | Amount, date, plan, seats; price change called out | None | Invoice and receipt | Billing contact and admins, for example 30 and 7 days before |
| Card expiring | Expiry date; update link | None | Confirmation after update | Billing contact and admins |
| Payment fails | Reason in plain words; next retry date | Banner for admins and billing contacts | Retry result within a stated window | Billing contact and admins by email |
| Retries end | Restriction date stated in earlier messages | Read-only mode; export stays open | Full restore on payment, no charge for the restricted time | Billing contact, admins, account owner |
| Billing details change | Note “applies to the next invoice”; validation result | Saved with timestamp | New invoices carry the details; old ones do not change | Billing contact and finance recipients |
| Cancel | End date; data handling; export; pause as an option | Confirmation with Undo until the date | Access ends; data held for a stated period | All admins and billing contact |
| Pause | Whether access continues and invoices stop | Status shown on the plan | Reminder before the resume date | Admins and billing contact |
Illustrative worked example: a 30-seat customer moves to a smaller plan
All numbers here are invented. A customer has 30 seats on a Business plan at $40 per seat per month. Business includes single sign-on and an audit log. Team costs $25 per seat per month and has neither. The cycle runs November 1 to November 30, and the next renewal is December 1. On November 16 the admin moves to Team and 20 seats. This product’s policy is to apply downgrades at once and credit the difference to the next invoice, with 15 of the 30 days left.
| Line | Calculation | Amount |
|---|---|---|
| Paid on November 1: Business, 30 seats | 30 x $40 | $1,200 |
| Credit for 15 unused days on Business | $1,200 x 15/30 | -$600 |
| Team, 20 seats, 15 remaining days | 20 x $25 x 15/30 | +$250 |
| Net credit from the change | -$350 | |
| Due today | $0 | |
| Next invoice on December 1 | 20 x $25 = $500, less $350 credit | $150 |
| Then every month | 20 x $25 | $500 |
The confirm panel would read: “Due today: $0. Your $350 credit will be applied to your December 1 invoice, which will be $150. From January 1: $500 a month. Prices exclude tax.” A real provider calculates to the second or minute, so a live preview will differ by cents from this day-based arithmetic.
Before the button, the screen lists the consequences. Single sign-on and the audit log switch off today. In this example, audit history stays readable and exportable for 90 days, which is an invented policy. Ten seats must be freed: the screen proposes the 10 people with the least recent activity, and the admin confirms or swaps them. The admins and the billing contact get an email at once. The 10 people lose access and are told when it happens. Finance receives the updated invoice on December 1.
The alternative is GitHub’s rule, with the change at renewal. The customer keeps Business and all 30 seats through November 30, pays nothing extra and gets no credit. The December 1 invoice is $500. In that version the screen says “Your plan changes on December 1. Until then you keep everything.” The customer pays $350 more for the second half of November than under the immediate rule. Which version you ship is a business decision. Either way, the confirm panel states the rule.
Where do these defaults stop working?
The sources here are vendor documentation, one regulator’s notices and well-known UX research. They show how billing tools and big products behave, not how your customers will. No study of B2B billing screens was found, and none is claimed. Baymard’s card-form finding comes from consumer ecommerce checkout. Provider details change, so confirm the ones that matter with engineering. This guide leaves out sales-led contracts with custom terms and net-60 payment, multi-entity billing, tax calculation and the EU and UK subscription rules.
What can you produce now?
Four things, before anyone draws a screen:
- A role map: who is admin, billing contact, finance recipient and ordinary user in your product, and what each can do in billing.
- A policy sheet with one rule each for upgrades, downgrades, seat additions, seat removals, true-ups and cancellation timing.
- The event table above, filled in for every billing event you support, with draft copy for the confirm panel and each banner.
- A test list: the 30-seat plan-change path, a failed card, an expired card, a wrong tax ID, and a cancel path timed with a retention offer declined.
If you plan to bring in outside designers for billing, ask each team to fill in the event table for two of your events and to explain the policy sheet. Our comparison of UX/UI agencies that design complex B2B SaaS platforms shows which studios publish work on screens like these.
