← Back to blog
Article

Who decides what goes on the invoice?

Most B2B SaaS count usage twice: once to enforce the contract, once to bill it. Kaiten Billing counts it once. Kaiten writes the invoice lines from the contract it already enforces; your billing provider taxes them, sends them and collects.

October 15, 2026 • 12 min read • Alexandre Bergère

Who decides what goes on the invoice? (light theme)Who decides what goes on the invoice? (dark theme)

Two counters that disagree

Open the code of almost any B2B SaaS that charges for usage and you will find the same quantity counted twice.

The first count lives in the product. Before an API call, an export or an inference, something checks how much of the customer's quota is left, then lets the call through or refuses it. That counter is the contract in action: it records what the customer actually received.

The second count lives in the billing provider. After the call, an event goes out to a meter, and at the end of the period the provider multiplies what it received by a price. That counter records what the customer will pay for.

Nobody designs it this way on purpose. The first counter appears with the first quota sold, the second with the first usage-based price. They are fed by different code paths, retried by different jobs and configured in different places: the limit in the product, the included quantity in the billing dashboard. And they drift. A retry reaches one counter twice and the other once. A request the gate refused still reaches the meter. Sales raises a customer's limit for a launch week, and billing keeps charging overage against the old one. A customer upgrades mid-month, and the two systems disagree about which limit applied on the 12th.

Each case is small. Together they produce the invoice nobody can explain: a number that cannot be traced back to what the gate let through. The vendor usually finds out when a customer disputes it, and the investigation crosses three tools and a spreadsheet.

On the left, one usage report feeds two counters, the product's gate and the provider's meter, which end the month on different numbers. On the right, one report goes through Kaiten's gate, which counts it once, and the invoice is composed from that count (light theme). On the left, one usage report feeds two counters, the product's gate and the provider's meter, which end the month on different numbers. On the right, one report goes through Kaiten's gate, which counts it once, and the invoice is composed from that count (dark theme).

Billing is the next large piece of Kaiten. It is not in a release yet; it is being built in the open, and this article describes its design. Most of that design follows from one decision: who decides what goes on the invoice.


The question underneath

An invoice is two things stuck together.

The first is its content: which lines, which quantities, at which unit prices, for which service period, minus which discounts. The second is everything that turns that content into money: tax, a legal invoice number, a PDF and an email, a card charge or a bank transfer, retries when the charge fails, reminders when the transfer doesn't arrive, fraud screening.

The second half is a hard, regulated and mature business. Billing providers are very good at it, and almost every SaaS we have talked to already pays one of them to do it.

The first half is a different problem. It is a function of the contract (what the customer bought, at what price, with which limits) and of what the customer consumed under it. In most stacks it ends up in the billing provider by default, because that is where prices get entered. But the provider sees only the part of the contract that carries a price. It does not know the limit the gate applied, the add-on that raised it on the 12th, or the quota boost sales granted for the launch. It rates the events it receives; whether they match what the product enforced is someone else's problem.

There are three honest answers to "who writes the content?", and we weighed each of them.

Let the provider rate. Mirror the catalogue into the provider, create the subscriptions there, stream every usage record to its meter, and listen to its webhooks. It works, and for a vendor whose pricing already lives in a rating system it can be the right answer. But it keeps two counters, and every single usage record now has to cross a network exactly once.

Build a billing engine. Own everything, from the price to the payment. We ruled this out before writing a line of billing code; it is written as a rule in our vision. Tax, payments and collections are categories with excellent tools already, and a control plane that tries to replace them dilutes the one thing that makes it useful.

Let the system that enforces the contract write the content, and let the provider handle the money. This is the one we chose.


Kaiten rates, your provider collects

Kaiten already holds the contract: the Licenses a vendor sells, the Entitlements they grant and, with billing, the prices on each License version and the add-ons stacked on top. It already holds the usage, too: every report goes through its gate, which accepts or refuses it against the customer's effective limit. Kaiten therefore has everything it needs to compose the invoice lines, from data it owns, without asking anyone.

Take a License priced at €99 a month plus €2 per million tokens, and a customer who used 4.2 million tokens in the period. At the period boundary, Kaiten composes an invoice with two lines, 99.00 and 8.40, and pushes it to Stripe. Stripe adds VAT, numbers the invoice, presents it, emails it, charges the card or waits for the transfer, and retries if the charge fails. The payment status comes back to Kaiten.

ConcernDecided by
What the customer bought: License, prices, add-ons, vouchersKaiten
What they can use right now: the effective limit every gate appliesKaiten
What they consumed: the live counter and the journal of every reportKaiten
Subscription state: periods, trial, cancellation, scheduled plan changeKaiten
Invoice content: lines, quantities, unit prices, service periods, discountsKaiten
Tax, invoice number, presentation, payment, retries, dunning, fraudYour provider
Payment statusYour provider, mirrored back into Kaiten
Payment methodYour provider. Kaiten keeps labels only: brand, last four digits, expiry

Two rules keep that line where it is.

The provider never decides content. Kaiten pushes an integer amount per line, in minor units. The provider adds tax and presentation, nothing else. Afterwards Kaiten reads the invoice back and compares every line, and the total before tax, with what it composed, at a tolerance of zero. A difference raises an alert. It never "corrects" Kaiten from the provider's copy, because the provider has no basis for being right about content.

A held invoice beats a wrong one. If Kaiten finds an inconsistency in the usage it is about to bill, it holds the invoice instead of sending it, and says why. A late invoice costs a day. A wrong one costs a customer's trust, and the same mistake repeats on every invoice of every customer until someone notices it.

Because the gate and the invoice read the same effective limit, they agree by construction:

  • Overage is billed only on usage the gate accepted, against the limit it applied at the moment it accepted it.
  • A request refused at the gate is never stored, so it can never be billed.
  • An add-on that raises a quota mid-period does not rewrite the usage that came before it.
  • Every invoice line can be drilled down to the individual usage reports behind it.
The contract and the usage journal feed Kaiten, which composes the invoice lines. The lines go either to Stripe, which adds tax, numbers, sends and collects, or, with no provider, to a handoff queue that the vendor's ERP pulls from. Payment status flows back to Kaiten (light theme). The contract and the usage journal feed Kaiten, which composes the invoice lines. The lines go either to Stripe, which adds tax, numbers, sends and collects, or, with no provider, to a handoff queue that the vendor's ERP pulls from. Payment status flows back to Kaiten (dark theme).

Is this a billing engine under another name? We don't think so, and the distinction matters to us. Kaiten rates only its own primitives: the prices on its Licenses and add-ons, the usage its gate accepted, the vouchers it issued. It never computes tax, never sees a card number, never chases a payment and never issues a credit note. It owns the half of billing that is a function of the contract, which is exactly the half a control plane is supposed to own.


Two providers on day one: Stripe, and none

Every design that claims to be provider-agnostic meets its second provider eventually, and that is where the claim gets tested. If adding the second one means touching anything beyond its adapter, the abstraction was the first provider's data model under another name.

We test ours from the first version with two implementations that could hardly be further apart. One is Stripe, with both ways B2B customers pay: an invoice sent with payment terms, or a payment method charged automatically. The other is no provider at all.

With no provider, Kaiten composes exactly the same invoice. It just doesn't send it anywhere: the invoice waits in Kaiten, marked as waiting for your accounting. Your system picks it up through the API or the CLI, books it in your ERP and acknowledges it with the reference it got there; an invoice that is never acknowledged comes back, so nothing is lost if the job dies halfway through. On Kaiten Cloud, a webhook tells your system the moment an invoice is issued. In the console, the same invoices are a view of the invoice list, and all of them can be exported. Payments come back the same way: an invoice is marked paid, written off or voided.

That is what brings billing to self-hosted and air-gapped deployments. A Kaiten running inside a bank's perimeter, with no provider configured, delivers no webhooks and calls no outside service; picking up the waiting invoices works there exactly as it does on Kaiten Cloud. It is also the answer for every system we don't have an adapter for yet: if your company invoices through an ERP, a short cron job is your adapter, and you don't have to wait for us to write one. Our design notes sum it up in one line: Kaiten composes what each customer owes; collecting it is yours.

The same constraint shaped the inside. No optional component sits on the path that decides an amount: no event stream, no message broker, no webhook delivery. A default self-hosted install has to bill correctly, or self-hosting means nothing for the one part of the product that touches money.


What we will not build

A boundary is only useful if it is written down, so here is ours.

  • Kaiten will not compute tax, process payments, run dunning, issue credit notes, recognize revenue or design invoice PDFs.
  • It will never receive, store or transmit card data. Cards are captured on pages the provider hosts.
  • It will not do quotes, CPQ or e-signature. Those belong to the CRM.
  • It is not your legal accounting system. Invoices can be exported, and your provider or your ERP remains the record your accountant relies on.

Each of these is a mature category, with tools that are better at it than we will ever be. Our job is to make sure the invoice they receive is right.


What comes next

Stripe is the first provider. Others will follow behind the same adapter boundary: Lago, Chargebee or others, depending on the roadmap. Some vendors would rather have their provider meter and price the usage itself, and we may offer that as an option later. In the first version, Kaiten is the reference: the usage it enforced is the usage it bills, and the provider receives finished lines.

The rest of this series goes one level deeper. The next article is about the usage journal: how a usage report becomes billable evidence exactly once, why we write it in the same transaction as the counter instead of reading it from an event stream, and how long a retry has to stay recognizable. The one after is about what sales actually negotiates (prices, add-ons, temporary quota boosts) and what the first version of vouchers can and cannot do.


Where it stands

Billing is being built in the open, in the Kaiten repository. It is not in a release yet. When it lands, it will sit behind a flag that stays off by default until we call it generally available.

The first version brings:

  • prices on License versions: flat fees, usage-based prices and overage, billed monthly to yearly, in advance or in arrears;
  • add-ons with quantities;
  • vouchers that discount a price or temporarily raise a quota;
  • subscriptions with trials, cancellation and scheduled plan changes;
  • the Stripe connector and the no-provider handoff queue;
  • React components for the pricing table, the customer portal and checkout.

The first customer it will bill is us. Every Kaiten Cloud organization is already a customer in our own Kaiten instance, with a License that sets its limits; with billing, the same instance will invoice it. The bar we set for the first version is plain: one real customer billed through Stripe in live mode, for a full cycle, without a single manual step. If our invoices are wrong, we will be the first to find out.

— Alexandre Bergère, co-founder & CEO, Kaiten

Billing is being built in the open

Read the code as it lands, and tell us how your invoices are made today. The design is still open to the people who will run it.

You might also like