Logo

Invoices

Beta

Invoice Creation Process

OpenMeter creates invoices by transforming gathering invoices into draft invoices based on billing profile configurations. During this process, several key pieces of data are cloned to ensure invoice immutability:

  1. The effective billing profile at the time of creation
  2. Customer information and metadata
  3. Usage-based pricing quantities

This cloning mechanism ensures that invoices remain immutable once created, preserving the integrity of billing records even if the underlying data changes. The immutability is critical for maintaining accurate financial records and audit trails.

While this cloning behavior ensures invoice immutability, any subsequent changes to workflow configurations or customer information must be made directly on the invoice if it is expected to affect the invoice. This includes modifications to customer names, billing workflows, and other invoice-specific details. This approach maintains data consistency.

Invoice contents

In addition to the cloned information, an invoice contains essential financial data including the Currency and comprehensive totals information.

The invoice totals comprise the following monetary values, with all totals automatically rounded according to the currency's precision:

NameContents
amountThe total amount of lines before discounts and taxes
chargesTotalThe total amount of charges (minimum spend) before discounts and taxes
discountsTotalThe total amount of discounts applied
taxesInclusiveTotalThe total amount of taxes included in amount, chargesTotal
taxesExclusiveTotalThe total amount of taxes on top of amount, chargesTotal
taxesTotalSum of taxesInclusiveTotal and taxesExclusiveTotal
totalThe total amount after taxes and discounts charged to the customer

Note: the lines use the same totals format using the same calculation methods.

For a detailed view on the invoice's data structure please consult the Invoice API reference.

Validation errors

Invoices include validation errors that indicate any issues encountered during state transitions in the invoice processing workflow.

Validation errors are classified into two severity levels:

  • warning: Non-blocking issues that allow invoice processing to continue
  • critical: Blocking issues that prevent the invoice from proceeding to the next state

When encountering critical validation errors, resolution requires either:

  • Updating the invoice while in draft state
  • Addressing issues in connected external systems
  • Retrying the failed state transition after fixes are applied

Example validation issue:

{
  "component": "app.stripe.invoiceCustomers.validate",
  "createdAt": "2025-02-01T08:15:01.290049Z",
  "id": "01JK097N5A5WQ5JRD39SFAAFMS",
  "message": "customer with id 01JHNF6G3WE1E9K1T4FMDYDZ2W does not meet condition customer has no data for stripe app for stripe app type with id 01JHN7EJH63HBN4Z3S2K0B74HA in namespace org_2l3uuzkgTdvCyom82y11jeZO2u5",
  "severity": "critical",
  "updatedAt": "2025-02-01T08:15:01.290049Z"
}

Invoice line

Besides this data, the invoice also contains 0 or more lines. We allow empty invoices to signify that there's no outstanding liabilities against the customer.

On the invoice there can be two kinds of lines:

  • Flat Fee: It represents a single line item
  • Usage Based Line: Represents a collection of Flat fees based on the usage quantity (these flat fee lines are called detailed lines)

The .rateCard property represents the intended billing configuration for each line item, while properties outside of .rateCard reflect the actual invoiced values after all calculations and adjustments have been applied.

To illustrate:

  • The rateCard.discounts field defines the discount policy (e.g. a 50% reduction from the base price)
  • The discounts.amount field contains the calculated monetary value of the applied discount

Flat fee line

Flat fee lines represent the most basic line item structure in the invoice. Each flat fee line consists of two primary components:

  • A quantity, specified in .rateCard.quantity
  • A price amount, defined in .rateCard.price.amount

The billing timing preference (In Advance or In Arrears) is determined by the .rateCard.price.paymentTerm field.

The following example demonstrates a typical flat fee line structure:

{
  "category": "regular",
  "currency": "USD",
  "id": "01JSKQ8SWGXAQ27RSZGXFBD6NT",
  "invoice": {
    "id": "01JSKW4APSBN6PE0C2ZZV3DKYR"
  },
  "invoiceAt": "2025-04-24T10:24:52.635922Z",
  "managedBy": "subscription",
  "metadata": null,
  "name": "feature in advance fee",
  "paymentTerm": "in_advance",
  "period": {
    "from": "2025-04-24T10:24:52.635922Z",
    "to": "2025-05-01T10:24:52.635922Z"
  },
  "rateCard": {
    "price": {
      "amount": "100",
      "paymentTerm": "in_advance",
      "type": "flat"
    },
    "quantity": "1"
  },
  "status": "valid",
  "subscription": {
    "item": {
      "id": "01JQXJX8YM7TH3BADZB3EDSBQK"
    },
    "phase": {
      "id": "01JQXJX8YTA1YBJEVWVRHFPVJM"
    },
    "subscription": {
      "id": "01JQXJX8YYVB3RA6N79B25HG11"
    }
  },
  "totals": {
    "amount": "100",
    "total": "100"
  },
  "type": "flat_fee"
}

Key Fields:

  • The category field indicates whether the line item represents a charge when set to "charge"
  • The managedBy field determines line item management:
    • When set to "subscription", the system automatically manages the line item and reflects subscription changes
    • Manual edits change this to "manual", preventing future subscription changes from affecting the line item to preserve manual modifications

The status field can have the following values:

  • valid: The line item is ready to be invoiced in its current state
  • detailed: The line item is a component of a Usage Based charge and should be included in billing
  • split: The line item serves as the parent entry for a Progressive Billing charge

Usage Based Lines

Usage Based Lines represent charges that are calculated based on actual usage measured by meters. These lines are fundamental to usage-based billing scenarios where customers are charged according to their consumption of specific services or resources.

Each Usage Based Line is associated with a meter defined by the feature reference, which tracks the actual usage data. The pricing structure for these charges is defined in the Rate Card, which specifies the unit price, any tiered pricing rules, volume discounts, and minimum or maximum charge constraints that should be applied to the measured usage.

A key feature of Usage Based Lines is their ability to contain multiple child line items marked with status="detailed". These detailed lines provide a comprehensive breakdown of the usage and associated charges. For instance, when dealing with API usage billing, the detailed lines might represent usage across different pricing tiers This granular breakdown is essential for transparency and enables accurate reporting.

Detailed lines are immutable and cannot be modified through the invoice edit API. Any modifications to detailed lines must be performed by updating their parent usage-based line item. This immutability ensures data consistency and maintains the integrity of usage-based billing calculations.

The relationship between a parent Usage Based Line and its detailed lines follows strict rules for consistency. The parent line's totals (both the amount and total fields) must exactly match the sum of all its detailed child lines. This requirement serves multiple purposes: it ensures data consistency within the system, enables accurate synchronization with external billing systems that may not support hierarchical grouping, and guarantees proper calculation of invoice-level adjustments such as taxes.

When accessing these lines through the API or viewing them in the UI, users can see both the consolidated view in the parent line and expand to view the complete usage breakdown in the detailed lines.

The following example demonstrates a typical usage-based line structure:

{
  "children": [
    {
      "category": "regular",
      "createdAt": "2025-02-01T08:15:01.621566Z",
      "currency": "USD",
      "managedBy": "system",
      "name": "Input Tokens Used: usage in period",
      "paymentTerm": "in_arrears",
      "perUnitAmount": "1",
      "period": {
        "from": "2024-12-22T17:55:00Z",
        "to": "2025-01-05T17:55:00Z"
      },
      "quantity": "152154",
      "rateCard": {
        "price": {
          "amount": "1",
          "paymentTerm": "in_arrears",
          "type": "flat"
        },
        "quantity": "152154"
      },
      "status": "detailed",
      "totals": {
        "amount": "152154",
        "chargesTotal": "0",
        "discountsTotal": "0",
        "taxesExclusiveTotal": "0",
        "taxesInclusiveTotal": "0",
        "taxesTotal": "0",
        "total": "152154"
      },
      "type": "flat_fee",
      "updatedAt": "2025-02-01T08:15:01.659988Z"
    }
  ],
  "createdAt": "2024-12-22T17:55:40.682568Z",
  "currency": "USD",
  "featureKey": "input_tokens_used",
  "id": "01JFQR5D0AKSD0FZZZWFRVVJNJ",
  "invoice": {
    "id": "01JK097NA9MP39JDPANHS6P6RH"
  },
  "invoiceAt": "2025-01-05T17:55:00Z",
  "managedBy": "subscription",
  "metadata": null,
  "meteredPreLinePeriodQuantity": "0",
  "meteredQuantity": "152154",
  "name": "Input Tokens Used",
  "period": {
    "from": "2024-12-22T17:55:00Z",
    "to": "2025-01-05T17:55:00Z"
  },
  "price": {
    "amount": "1",
    "type": "unit"
  },
  "quantity": "152154",
  "rateCard": {
    "featureKey": "input_tokens_used",
    "price": {
      "amount": "1",
      "type": "unit"
    }
  },
  "status": "valid",
  "totals": {
    "amount": "152154",
    "chargesTotal": "0",
    "discountsTotal": "0",
    "taxesExclusiveTotal": "0",
    "taxesInclusiveTotal": "0",
    "taxesTotal": "0",
    "total": "152154"
  },
  "type": "usage_based",
  "updatedAt": "2025-02-01T08:15:01.619753Z"
}