Calculating an invoice
Basic definitions
An invoice consists of the following elements:
- A set of line items
- A set of "adjustments" (minimums, maximums, amount discounts, usage discounts, percentage discounts) that may either be incorporated at the line item level or be applied across line items. Adjustments can only be applied to prices with a real world currency, and usage discounts can only be applied to a quantity and hence at the line item level. Other than usage adjustments, all adjustments can be applied at the line item or across line items. Adjustments must be applied to
Price
s with the same cadence, billing mode (in-arrears or in-advance), and currency. Percent discounts can be used across cadences since they distribute proportionally to anyPrice
. - [Optional] A tax amount per line item, if tax is enabled
- [Optional] A "balance transaction" – this is derived from the customer invoicing balance and is applied post-tax.
Some invariants that hold for invoices:
- Each line item is associated with a
Price
object. Note that this is true for line items added by invoice edits as well as those that are generated from the billing engine, where the price is derived through the subscription’s plan or added directly to the subscription. - Each invoice can only have up to one line item that references a specific price – prices cannot be repeated on an invoice
- An invoice should only have line items in a single real-world currency, but may have line items of multiple virtual currencies – each with a conversion rate to the relevant real-world currency.
- Each adjustment is associated with a set of one or more Price objects.
Calculating the true total for an invoice line item
An invoice’s finalized total_with_tax can be calculated by summing the "true total" of each line item. This means that you can calculate each line item independently and then just sum the true totals – there is nothing that happens exclusively at an invoice level.
Note, however, that the "customer invoice balance" (distinct from prepaid credits) applies to the whole invoice after tax. This specifically cannot be traced to a per-line item level and you apply the balance (if applicable/available) to determine the amount_due for the invoice.
Determine line item quantity
To calculate the true total of a line item, Orb first starts with the line item quantity. Each line item has a quantity that is either dictated by the latest fixed fee quantity or from the usage total in the service period of the line item.
In some cases, a line item can have multiple underlying quantities – e.g. imagine a case where the same Price
has a different unit rate per region of compute. In that case, the line item would have a matrix price attached t oit, so one Price
operates over many quantities, one per region.
Apply the pricing function
The pricing function takes as input either a single quantity or a list of quantities (see above, e.g. per region). It outputs a single monetary amount that’s determined by the pricing function itself.
Pricing functions are associated with a currency that they output the monetary value in; this could either be a real-world currency like "USD" or a virtual currency like "Database credits". If it’s a virtual currency, there must be a conversion rate specified to the plan’s real-world currency (e.g. Database credits → USD).
At this step, we're calculating a subtotal which is in the Price
currency, so the conversion rate – if applicable – has not been applied.
Apply line item level adjustments
Adjustments that are applied when configuring the individual line item are applied to the subtotal. For example, you might apply a minimum or a percentage/amount discount here.
Notably, these adjustments operate in the price's currency which can be a virtual currency.
Adjustments are always applied in the following order:
- Usage discount (e.g. 100 units off)
- Amount discount (e.g. $100 off or 100 credits off)
- Percent discount (e.g. 10% off)
- Minimum (e.g. at least $10, at least 10 credits)
- Maximum (e.g. at most $100, at most 100 credits)
Apply multi-price/invoice level adjustments
Adjustments that are applied across a group of Price
s (either at the Plan
level, or for example when executing an invoice edit) are then applied. Note that within these multi-price adjustments, the ordering of adjustment type is the same as line item level adjustments. These adjustments must be applied to prices that share the same price currency.
Apply prepaid credits
Any prepaid "credit balance" is applied to the adjusted subtotal, calculated above. Note that prepurchase can only be applied to usage-based prices (and thus never applies to fixed fees).
This prepurchase balance could be in USD or a custom credit unit, but note that it will only apply to prices whose currencies match the prepurchase currency.
Apply overage conversion
If the price’s currency is not a real-world currency, apply the per-price overage conversion rate. This rate translates, for example, credits -> USD.
Currently, this can only be a unit rate, and each price might have a separate conversion rate originating from the same price currency. All the rates must translate to the same real-world currency.
At the end of this process, Orb is guaranteed to produce a line item amount in a real-world invoicable currency.
Subtract amounts previously invoiced by partial (threshold) invoices
If you use threshold-based invoicing, Orb might issue an invoice mid-billing period while charges are being accrued. This is to minimize unlimited "fraud risk", so that you’re charging customers for example as soon as they hit a set threshold in spend.
Orb keeps track of the previously invoiced amount per line item, and subtracts it in this step from the line item’s amount.
Apply line item tax
Tax is calculated at the line item level (if it’s being used), and derived from a third-party solution like TaxJar or Avalara. Orb adds tax to the line item total when the invoice is issued – you will not see tax on a draft invoice in the middle of the period.
Note that in cases where our customer is syncing the invoice to a different invoicing provider (e.g. Stripe Invoicing) then Orb does not keep track of tax – tax may be added to the invoice later in Stripe. This step applies when Orb invoicing is being used, and tax must be added by Orb via an integrated tax provider.
FAQ
If I have an adjustment that applies across multiple prices.How is it distributed between them?
For all adjustments other than minimums, the adjustment will be distributed proportionally to the line item’s portion of the summed line item subtotals. So if an amount discount of $12 applies to Price A
and Price B
, and Price A
’s line item subtotal is $5 and Price B
’s line item subtotal is $15, Price A
’s line item will have $3 of discount applied to it, and Price B
’s line item will have $9 applied to it.
For minimum adjustments, the adjustment will be distributed evenly between all applicable line items. The distribution of adjustments across line items will not affect the total amount due on the invoice.
I have an invoice-level minimum amount, but my invoice is below that amount. Why?
This is typically because the minimum is applied before prepaid credits (as expected). If a customer has a $300 minimum and $200 of prepaid credits balance, the minimum will bring the adjusted_subtotal to $300 and then the $200 in prepaid credits will be applied, resulting in a final amount due on the invoice of $100.
Note that this is true even if it’s an invoice level minimum.
Another reason might be that the minimum will be prorated to the service period.
Is it possible for me to always invoice for a fixed amount for each invoice, regardless of the customer's prepurchase balance?
That is not possible, as it would lead to potentially charging a customer more than expected. Because minimums apply before prepurchase, they functionally guarantee a minimum spend on the invoice, which should be agnostic to whether it's paid via prepurchase or as part of the invoice payment. If this wasn't the case, customers would be overpaying if they had prepurchase. For example, if a customer had $100 in prepurchase and a $200 minimum, Orb guarantees that the total they are charged is $200, with $100 coming from prepurchase and $100 coming from the invoice. To guarantee that the invoice balance was $200 as specified in the minimum, the minimum would have to be applied after prepurchase, which would result in cosuming the $100 of prepurchase and applying the $200 minimum, resulting in a $200 invoice, but functionally charging the customer $300!
Can I have an adjustment that applies to only the overage incurred on an invoice?
Adjustments are apply always before prepurchase – see the example above.
What’s the difference between invoice balance and prepurchase?
Invoice balance is an invoice-level concept that is used to "apply" a future amount to an invoice – think of it as a "payment method" that applies to the next invoice that gets issued.
Prepurchase is applied before tax and you can think of it as a usage commitment (it doesn’t apply to fixed fees). Prepurchase also typically has an effective time and expiration time.
In what cases will Orb produce a negative invoice (i.e. amount due is negative)?
This can happen in certain fixed fee downgrade scenarios where a negative invoice is produced, but typically "credits" as a result of downgrade are applied as credit notes on the original invoice.
How does prepurchase in a given currency get distributed across prices in that currency? For example, if I have $10 USD prepurchase balance and two USD prices, which price "gets to use" the prepurchase, and which price gets into overage?
Orb distributes it in a stable way according to price ID. Note that which price it applies to doesn’t affect the actual calculation of the total for the invoice.